dgraham     2004/01/31 18:25:08

  Modified:    validator/src/share/org/apache/commons/validator Field.java
                        Validator.java Form.java ValidatorAction.java
  Log:
  Refactored Validator class to place methods closer to the data required to 
  run them.  Now ValidatorActions know how to execute their validation
  method, Forms know how to validate a set of their Fields, and Fields
  can run the validations configured on them.
  
  Revision  Changes    Path
  1.30      +168 -5    
jakarta-commons/validator/src/share/org/apache/commons/validator/Field.java
  
  Index: Field.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons/validator/src/share/org/apache/commons/validator/Field.java,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -r1.29 -r1.30
  --- Field.java        17 Jan 2004 17:35:27 -0000      1.29
  +++ Field.java        1 Feb 2004 02:25:08 -0000       1.30
  @@ -62,6 +62,7 @@
   package org.apache.commons.validator;
   
   import java.io.Serializable;
  +import java.lang.reflect.InvocationTargetException;
   import java.util.ArrayList;
   import java.util.Collection;
   import java.util.Collections;
  @@ -71,16 +72,15 @@
   import java.util.Map;
   import java.util.StringTokenizer;
   
  +import org.apache.commons.beanutils.PropertyUtils;
   import org.apache.commons.collections.FastHashMap;
   import org.apache.commons.validator.util.ValidatorUtils;
   
   /**
  - * <p>
    * This contains the list of pluggable validators to run on a field and any 
    * message information and variables to perform the validations and generate 
    * error messages.  Instances of this class are configured with a 
    * &lt;field&gt; xml element.
  - * </p>
    *
    * @see org.apache.commons.validator.Form
    */
  @@ -787,6 +787,169 @@
           }
   
           return results.toString();
  +    }
  +    
  +    /**
  +     * Returns an indexed property from the object we're validating.
  +     *
  +     * @param bean The bean to extract the indexed values from.
  +     * @throws ValidatorException If there's an error looking up the property 
  +     * or, the property found is not indexed.
  +     */
  +    Object[] getIndexedProperty(Object bean) throws ValidatorException {
  +        Object indexedProperty = null;
  +
  +        try {
  +            indexedProperty =
  +                PropertyUtils.getProperty(bean, this.getIndexedListProperty());
  +
  +        } catch(IllegalAccessException e) {
  +            throw new ValidatorException(e.getMessage());
  +        } catch(InvocationTargetException e) {
  +            throw new ValidatorException(e.getMessage());
  +        } catch(NoSuchMethodException e) {
  +            throw new ValidatorException(e.getMessage());
  +        }
  +
  +        if (indexedProperty instanceof Collection) {
  +            return ((Collection) indexedProperty).toArray();
  +
  +        } else if (indexedProperty.getClass().isArray()) {
  +            return (Object[]) indexedProperty;
  +
  +        } else {
  +            throw new ValidatorException(this.getKey() + " is not indexed");
  +        }
  +
  +    }
  +    
  +    /**
  +     * Executes the given ValidatorAction and all ValidatorActions that it 
  +     * depends on.
  +     * @return true if the validation succeeded.
  +     */
  +    private boolean validateForRule(
  +        ValidatorAction va,
  +        ValidatorResults results,
  +        Map actions,
  +        Map params,
  +        int pos)
  +        throws ValidatorException {
  +
  +        ValidatorResult result = results.getValidatorResult(this.getKey());
  +        if (result != null && result.containsAction(va.getName())) {
  +            return result.isValid(va.getName());
  +        }
  +
  +        if (!this.runDependentValidators(va, results, actions, params, pos)) {
  +            return false;
  +        }
  +
  +        return va.executeValidationMethod(this, params, results, pos);
  +    }
  +
  +    /**
  +     * Calls all of the validators that this validator depends on.
  +     * TODO ValidatorAction should know how to run its own dependencies.
  +     * @param va Run dependent validators for this action.
  +     * @param results
  +     * @param actions
  +     * @param pos
  +     * @return true if all of the dependent validations passed.
  +     * @throws ValidatorException
  +     */
  +    private boolean runDependentValidators(
  +        ValidatorAction va,
  +        ValidatorResults results,
  +        Map actions,
  +        Map params,
  +        int pos)
  +        throws ValidatorException {
  +
  +        List dependentValidators = va.getDependencyList();
  +
  +        if (dependentValidators.isEmpty()) {
  +            return true;
  +        }
  +
  +        Iterator iter = dependentValidators.iterator();
  +        while (iter.hasNext()) {
  +            String depend = (String) iter.next();
  +
  +            ValidatorAction action = (ValidatorAction) actions.get(depend);
  +            if (action == null) {
  +                this.handleMissingAction(depend);
  +            }
  +
  +            if (!this.validateForRule(action, results, actions, params, pos)) {
  +                return false;
  +            }
  +        }
  +
  +        return true;
  +    }
  +
  +    /**
  +     * Run the configured validations on this field.  Run all validations 
  +     * in the depends clause over each item in turn, returning when the first 
  +     * one fails.
  +     * @param params A Map of parameter class names to parameter values to pass
  +     * into validation methods.
  +     * @param actions A Map of validator names to ValidatorAction objects.
  +     * @return A ValidatorResults object containing validation messages for 
  +     * this field.
  +     */
  +    ValidatorResults validate(Map params, Map actions)
  +        throws ValidatorException {
  +        
  +        if (this.getDepends() == null) {
  +            return new ValidatorResults();
  +        }
  +
  +        ValidatorResults allResults = new ValidatorResults();
  +
  +        Object bean = params.get(Validator.BEAN_PARAM);
  +        int numberOfFieldsToValidate =
  +            this.isIndexed() ? this.getIndexedProperty(bean).length : 1;
  +
  +        for (int fieldNumber = 0; fieldNumber < numberOfFieldsToValidate; 
fieldNumber++) {
  +            
  +            Iterator dependencies = this.dependencyList.iterator();
  +            while (dependencies.hasNext()) {
  +                String depend = (String) dependencies.next();
  +
  +                ValidatorAction action = (ValidatorAction) actions.get(depend);
  +                if (action == null) {
  +                    this.handleMissingAction(depend);
  +                }
  +
  +                ValidatorResults results = new ValidatorResults();
  +                boolean good =
  +                    validateForRule(action, results, actions, params, fieldNumber);
  +
  +                allResults.merge(results);
  +
  +                if (!good) {
  +                    return allResults;
  +                }
  +            }
  +        }
  +        
  +        return allResults;
  +    }
  +    
  +    /**
  +     * Called when a validator name is used in a depends clause but there is
  +     * no know ValidatorAction configured for that name.
  +     * @param name The name of the validator in the depends list.
  +     * @throws ValidatorException
  +     */
  +    private void handleMissingAction(String name) throws ValidatorException {
  +        throw new ValidatorException(
  +            "No ValidatorAction named "
  +                + name
  +                + " found for field "
  +                + this.getProperty());
       }
   
   }
  
  
  
  1.33      +8 -392    
jakarta-commons/validator/src/share/org/apache/commons/validator/Validator.java
  
  Index: Validator.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons/validator/src/share/org/apache/commons/validator/Validator.java,v
  retrieving revision 1.32
  retrieving revision 1.33
  diff -u -r1.32 -r1.33
  --- Validator.java    17 Jan 2004 21:37:20 -0000      1.32
  +++ Validator.java    1 Feb 2004 02:25:08 -0000       1.33
  @@ -62,21 +62,12 @@
   package org.apache.commons.validator;
   
   import java.io.Serializable;
  -import java.lang.reflect.InvocationTargetException;
  -import java.lang.reflect.Method;
  -import java.lang.reflect.Modifier;
  -import java.util.Collection;
   import java.util.HashMap;
  -import java.util.Iterator;
  -import java.util.List;
   import java.util.Locale;
   import java.util.Map;
  -import java.util.StringTokenizer;
   
  -import org.apache.commons.beanutils.PropertyUtils;
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogFactory;
  -import org.apache.commons.validator.util.ValidatorUtils;
   
   /**
    * Validations are processed by the validate method. An instance of
  @@ -396,357 +387,6 @@
       }
   
       /**
  -     * Executes the given ValidatorAction and all ValidatorActions that it 
  -     * depends on.
  -     * @return true if the validation succeeded.
  -     */
  -    private boolean validateFieldForRule(
  -            Field field,
  -            ValidatorAction va,
  -            ValidatorResults results,
  -            Map actions,
  -            int pos)
  -            throws ValidatorException {
  -
  -        ValidatorResult result = results.getValidatorResult(field.getKey());
  -        if (result != null && result.containsAction(va.getName())) {
  -            return result.isValid(va.getName());
  -        }
  -
  -        if (!this.runDependentValidators(field, va, results, actions, pos)) {
  -            return false;
  -        }
  -
  -        return this.executeValidationMethod(field, va, results, pos);
  -    }
  -
  -    /**
  -     * Calls all of the validators that this validator depends on.
  -     * @param field
  -     * @param va
  -     * @param results
  -     * @param actions
  -     * @param pos
  -     * @return true if all of the dependent validations passed.
  -     * @throws ValidatorException
  -     */
  -    private boolean runDependentValidators(
  -            Field field,
  -            ValidatorAction va,
  -            ValidatorResults results,
  -            Map actions,
  -            int pos)
  -            throws ValidatorException {
  -
  -        if (va.getDepends() == null) {
  -            return true;
  -        }
  -
  -        StringTokenizer st = new StringTokenizer(va.getDepends(), ",");
  -        while (st.hasMoreTokens()) {
  -            String depend = st.nextToken().trim();
  -
  -            ValidatorAction action = (ValidatorAction) actions.get(depend);
  -            if (action == null) {
  -                log.error(
  -                        "No ValidatorAction named "
  -                        + depend
  -                        + " found for field "
  -                        + field.getProperty());
  -
  -                return false;
  -            }
  -
  -            if (!this.validateFieldForRule(field, action, results, actions, pos)) {
  -                return false;
  -            }
  -        }
  -
  -        return true;
  -    }
  -
  -    /**
  -     * Dynamically runs the validation method for this validator and returns 
  -     * true if the data is valid.
  -     * @param field
  -     * @param va
  -     * @param results
  -     * @param pos
  -     * @throws ValidatorException
  -     */
  -    private boolean executeValidationMethod(
  -        Field field,
  -        ValidatorAction va,
  -        ValidatorResults results,
  -        int pos)
  -        throws ValidatorException {
  -
  -        // Add these two Objects to the resources since they reference
  -        // the current validator action and field
  -        this.setParameter(VALIDATOR_ACTION_PARAM, va);
  -        this.setParameter(FIELD_PARAM, field);
  -
  -        try {
  -            Class validationClass;
  -            try {
  -                validationClass = getClassLoader().loadClass(va.getClassname());
  -            } catch (ClassNotFoundException e) {
  -                throw new ValidatorException(e.getMessage());
  -            }
  -
  -            List params = va.getMethodParamsList();
  -
  -            Class[] paramClass = this.getParameterClasses(params);
  -            Object[] paramValue = this.getParameterValues(params);
  -
  -            Method validationMethod;
  -            try {
  -                validationMethod = validationClass.getMethod(va.getMethod(), 
paramClass);
  -            } catch (NoSuchMethodException e) {
  -                throw new ValidatorException(e.getMessage());
  -            }
  -
  -            // If the method is static, we don't need an instance of the class
  -            // to call the method.
  -            if (!Modifier.isStatic(validationMethod.getModifiers())) {
  -                this.storeClassInAction(validationClass, va);
  -            }
  -
  -            if (field.isIndexed()) {
  -                this.handleIndexedField(field, pos, params, paramValue);
  -            }
  -
  -            Object result = null;
  -            try {
  -                result = validationMethod.invoke(va.getClassnameInstance(), 
paramValue);
  -            } catch (IllegalArgumentException e) {
  -                throw new ValidatorException(e.getMessage());
  -            } catch (IllegalAccessException e) {
  -                throw new ValidatorException(e.getMessage());
  -            } catch (InvocationTargetException e) {
  -                
  -                if (e.getTargetException() instanceof Exception) {
  -                    throw (Exception) e.getTargetException();
  -                
  -                } else if (e.getTargetException() instanceof Error) {
  -                    throw (Error) e.getTargetException();
  -                }
  -            }
  -
  -            boolean valid = this.isValid(result);
  -            if (!valid || (valid && !this.onlyReturnErrors)) {
  -                results.add(field, va.getName(), valid, result);
  -            }
  -
  -            if (!valid) {
  -                return false;
  -            }
  -
  -        // TODO This catch block remains for backward compatibility.  Remove
  -        // this for Validator 2.0 when exception scheme changes.
  -        } catch (Exception e) {
  -            if (e instanceof ValidatorException) {
  -                throw (ValidatorException) e;
  -            }
  -            
  -            log.error(
  -                "Unhandled exception thrown during validation: " + e.getMessage(),
  -                e);
  -
  -            results.add(field, va.getName(), false);
  -            return false;
  -        }
  -
  -        return true;
  -    }
  -
  -    /**
  -     * Converts a List of parameter class names into their Class objects.
  -     * @param paramNames
  -     * @return An array containing the Class object for each parameter.  This 
  -     * array is in the same order as the given List and is suitable for passing 
  -     * to the validation method.
  -     * @throws ValidatorException if a class cannot be loaded.
  -     */
  -    private Class[] getParameterClasses(List paramNames)
  -        throws ValidatorException {
  -
  -        Class[] paramClass = new Class[paramNames.size()];
  -
  -        for (int i = 0; i < paramNames.size(); i++) {
  -            String paramClassName = (String) paramNames.get(i);
  -
  -            // There were problems calling getClass on paramValue[]
  -            try {
  -                paramClass[i] = this.getClassLoader().loadClass(paramClassName);
  -            } catch (ClassNotFoundException e) {
  -                throw new ValidatorException(e.getMessage());
  -            }
  -        }
  -
  -        return paramClass;
  -    }
  -
  -    /**
  -     * Converts a List of parameter class names into their values contained in 
  -     * the parameters Map.
  -     * @param paramNames
  -     * @return An array containing the value object for each parameter.  This 
  -     * array is in the same order as the given List and is suitable for passing 
  -     * to the validation method.
  -     */
  -    private Object[] getParameterValues(List paramNames) {
  -
  -        Object[] paramValue = new Object[paramNames.size()];
  -
  -        for (int i = 0; i < paramNames.size(); i++) {
  -            String paramClassName = (String) paramNames.get(i);
  -            paramValue[i] = this.getParameterValue(paramClassName);
  -        }
  -
  -        return paramValue;
  -    }
  -
  -    /**
  -     * If the given action doesn't already have an instance of the class, 
  -     * store a new instance in the action.
  -     * @param validationClass The pluggable validation class to store.
  -     * @param va The ValidatorAction to store the object in.
  -     */
  -    private void storeClassInAction(Class validationClass, ValidatorAction va) {
  -        try {
  -            if (va.getClassnameInstance() == null) {
  -                va.setClassnameInstance(validationClass.newInstance());
  -            }
  -        } catch(Exception ex) {
  -            log.error(
  -                    "Couldn't load instance "
  -                    + "of class "
  -                    + va.getClassname()
  -                    + ".  "
  -                    + ex.getMessage());
  -        }
  -    }
  -
  -    /**
  -     * Modifies the paramValue array with indexed fields.
  -     *
  -     * @param field
  -     * @param pos
  -     * @param params
  -     * @param paramValue
  -     */
  -    private void handleIndexedField(
  -            Field field,
  -            int pos,
  -            List params,
  -            Object[] paramValue)
  -            throws ValidatorException {
  -
  -        int beanIndexPos = params.indexOf(BEAN_PARAM);
  -        int fieldIndexPos = params.indexOf(FIELD_PARAM);
  -
  -        Object indexedList[] = this.getIndexedProperty(field);
  -
  -        // Set current iteration object to the parameter array
  -        paramValue[beanIndexPos] = indexedList[pos];
  -
  -        // Set field clone with the key modified to represent
  -        // the current field
  -        Field indexedField = (Field) field.clone();
  -        indexedField.setKey(
  -                ValidatorUtils.replace(
  -                        indexedField.getKey(),
  -                        Field.TOKEN_INDEXED,
  -                        "[" + pos + "]"));
  -
  -        paramValue[fieldIndexPos] = indexedField;
  -    }
  -
  -    /**
  -     * Run the validations on a given field, modifying the passed
  -     * ValidatorResults to add in any new errors found.  Run all the 
  -     * validations in the depends clause over each item in turn, returning 
  -     * when the first one fails.
  -     */
  -    private void validateField(Field field, ValidatorResults allResults)
  -        throws ValidatorException {
  -
  -        int numberOfFieldsToValidate =
  -                field.isIndexed() ? this.getIndexedProperty(field).length : 1;
  -
  -        Map actions = this.resources.getValidatorActions();
  -
  -        for (int fieldNumber = 0; fieldNumber < numberOfFieldsToValidate; 
fieldNumber++) {
  -            StringTokenizer st = new StringTokenizer(field.getDepends(), ",");
  -            while (st.hasMoreTokens()) {
  -                String depend = st.nextToken().trim();
  -
  -                ValidatorAction action = (ValidatorAction) actions.get(depend);
  -                if (action == null) {
  -                    log.error(
  -                            "No ValidatorAction named "
  -                            + depend
  -                            + " found for field "
  -                            + field.getProperty());
  -
  -                    return;
  -                }
  -
  -                ValidatorResults results = new ValidatorResults();
  -                boolean good =
  -                        validateFieldForRule(field, action, results, actions, 
fieldNumber);
  -
  -                allResults.merge(results);
  -
  -                if (!good) {
  -                    return;
  -                }
  -            }
  -        }
  -    }
  -
  -    /**
  -     * Returns an indexed property from the object we're validating.
  -     *
  -     * @param field This field.getIndexedListProperty() will be found in the object 
we're
  -     * currently validating
  -     * @throws ValidatorException If there's an error looking up the property or, 
the
  -     * property found is not indexed.
  -     */
  -    private Object[] getIndexedProperty(Field field) throws ValidatorException {
  -        Object indexedProperty = null;
  -
  -        try {
  -            indexedProperty =
  -                    PropertyUtils.getProperty(
  -                            this.getParameterValue(BEAN_PARAM),
  -                            field.getIndexedListProperty());
  -
  -        } catch(IllegalAccessException e) {
  -            throw new ValidatorException(e.getMessage());
  -        } catch(InvocationTargetException e) {
  -            throw new ValidatorException(e.getMessage());
  -        } catch(NoSuchMethodException e) {
  -            throw new ValidatorException(e.getMessage());
  -        }
  -
  -        if (indexedProperty instanceof Collection) {
  -            return ((Collection) indexedProperty).toArray();
  -
  -        } else if (indexedProperty.getClass().isArray()) {
  -            return (Object[]) indexedProperty;
  -
  -        } else {
  -            throw new ValidatorException(
  -                    "Non-collection, non-array indexed property "
  -                    + field.getKey()
  -                    + " found");
  -        }
  -
  -    }
  -
  -    /**
        * Performs validations based on the configured resources.
        *
        * @return The <code>Map</code> returned uses the property of the
  @@ -754,7 +394,6 @@
        * field had.
        */
       public ValidatorResults validate() throws ValidatorException {
  -        ValidatorResults results = new ValidatorResults();
           Locale locale = (Locale) this.getParameterValue(LOCALE_PARAM);
   
           if (locale == null) {
  @@ -765,36 +404,13 @@
   
           Form form = this.resources.getForm(locale, this.formName);
           if (form != null) {
  -            Iterator fields = form.getFields().iterator();
  -            while (fields.hasNext()) {
  -                Field field = (Field) fields.next();
  -
  -                if ((field.getPage() <= page) && (field.getDepends() != null)) {
  -                    this.validateField(field, results);
  -                }
  -            }
  -
  -        }
  -
  -        return results;
  -    }
  -
  -    /**
  -     * Returns if the result if valid.  If the
  -     * result object is <code>Boolean</code>, then it will
  -     * the value.  If the result object isn't <code>Boolean</code>,
  -     * then it will return <code>false</code> if the result
  -     * object is <code>null</code> and <code>true</code> if it isn't.
  -     */
  -    private boolean isValid(Object result) {
  -
  -        if (result instanceof Boolean) {
  -            Boolean valid = (Boolean) result;
  -            return valid.booleanValue();
  -        } else {
  -            return (result != null);
  +            return form.validate(
  +                this.parameters,
  +                this.resources.getValidatorActions(),
  +                this.page);
           }
   
  +        return new ValidatorResults();
       }
   
       /**
  
  
  
  1.13      +31 -3     
jakarta-commons/validator/src/share/org/apache/commons/validator/Form.java
  
  Index: Form.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons/validator/src/share/org/apache/commons/validator/Form.java,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- Form.java 11 Jan 2004 23:30:20 -0000      1.12
  +++ Form.java 1 Feb 2004 02:25:08 -0000       1.13
  @@ -186,5 +186,33 @@
   
           return results.toString();
       }
  +    
  +    /**
  +     * Validate all Fields in this Form on the given page and below.
  +     * @param params A Map of parameter class names to parameter values to pass
  +     * into validation methods.
  +     * @param actions A Map of validator names to ValidatorAction objects.
  +     * @param page Fields on pages higher than this will not be validated.
  +     * @return A ValidatorResults object containing all validation messages.
  +     * @throws ValidatorException
  +     */
  +    ValidatorResults validate(Map params, Map actions, int page)
  +        throws ValidatorException {
  +
  +        ValidatorResults results = new ValidatorResults();
  +
  +        Iterator fields = this.lFields.iterator();
  +        while (fields.hasNext()) {
  +            Field field = (Field) fields.next();
  +
  +            params.put(Validator.FIELD_PARAM, field);
  +
  +            if (field.getPage() <= page) {
  +                results.merge(field.validate(params, actions));
  +            }
  +        }
  +
  +        return results;
  +    }
   
   }
  
  
  
  1.19      +286 -5    
jakarta-commons/validator/src/share/org/apache/commons/validator/ValidatorAction.java
  
  Index: ValidatorAction.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons/validator/src/share/org/apache/commons/validator/ValidatorAction.java,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- ValidatorAction.java      18 Jan 2004 19:38:46 -0000      1.18
  +++ ValidatorAction.java      1 Feb 2004 02:25:08 -0000       1.19
  @@ -64,6 +64,9 @@
   import java.io.IOException;
   import java.io.InputStream;
   import java.io.Serializable;
  +import java.lang.reflect.InvocationTargetException;
  +import java.lang.reflect.Method;
  +import java.lang.reflect.Modifier;
   import java.util.ArrayList;
   import java.util.Collection;
   import java.util.Collections;
  @@ -73,13 +76,12 @@
   
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogFactory;
  +import org.apache.commons.validator.util.ValidatorUtils;
   
   /**
  - * <p>
    * Contains the information to dynamically create and run a validation
    * method.  This is the class representation of a pluggable validator that can 
    * be defined in an xml file with the &lt;validator&gt; element.
  - * </p>
    *
    * <strong>Note</strong>: The validation method is assumed to be thread safe.
    */
  @@ -100,12 +102,22 @@
        * the validation method associated with this action.
        */
       private String classname = null;
  +    
  +    /**
  +     * The Class object loaded from the classname.
  +     */
  +    private Class validationClass = null;
   
       /**
        * The full method name of the validation to be performed.  The method
        * must be thread safe.
        */
       private String method = null;
  +    
  +    /**
  +     * The Method object loaded from the method name.
  +     */
  +    private Method validationMethod = null;
   
       /**
        * <p>
  @@ -127,6 +139,11 @@
               + Validator.VALIDATOR_ACTION_PARAM
               + ","
               + Validator.FIELD_PARAM;
  +            
  +    /**
  +     * The Class objects for each entry in methodParameterList.
  +     */        
  +    private Class[] parameterClasses = null;
   
       /**
        * The other <code>ValidatorAction</code>s that this one depends on.  If 
  @@ -250,6 +267,7 @@
   
       /**
        * Gets the method parameters for the method as an unmodifiable List.
  +     * @deprecated This will be removed after Validator 1.1.2
        */
       public List getMethodParamsList() {
           return Collections.unmodifiableList(this.methodParameterList);
  @@ -369,6 +387,7 @@
   
       /**
        * Gets an instance based on the validator action's classname.
  +     * @deprecated This will be removed after Validator 1.1.2
        */
       public Object getClassnameInstance() {
           return instance;
  @@ -376,6 +395,7 @@
   
       /**
        * Sets an instance based on the validator action's classname.
  +     * @deprecated This will be removed after Validator 1.1.2
        */
       public void setClassnameInstance(Object instance) {
           this.instance = instance;
  @@ -553,6 +573,267 @@
           results.append("\n");
   
           return results.toString();
  +    }
  +    
  +    /**
  +     * Dynamically runs the validation method for this validator and returns 
  +     * true if the data is valid.
  +     * @param field
  +     * @param params A Map of class names to parameter values.
  +     * @param results
  +     * @param pos The index of the list property to validate if it's indexed.
  +     * @throws ValidatorException
  +     */
  +    boolean executeValidationMethod(
  +        Field field,
  +        Map params,
  +        ValidatorResults results,
  +        int pos)
  +        throws ValidatorException {
  +
  +        params.put(Validator.VALIDATOR_ACTION_PARAM, this);
  +
  +        try {
  +            ClassLoader loader = this.getClassLoader(params);
  +            this.loadValidationClass(loader);
  +            this.loadParameterClasses(loader);
  +            this.loadValidationMethod();
  +
  +            Object[] paramValues = this.getParameterValues(params);
  +            
  +            if (field.isIndexed()) {
  +                this.handleIndexedField(field, pos, paramValues);
  +            }
  +
  +            Object result = null;
  +            try {
  +                result =
  +                    validationMethod.invoke(
  +                        getValidationClassInstance(),
  +                        paramValues);
  +
  +            } catch (IllegalArgumentException e) {
  +                throw new ValidatorException(e.getMessage());
  +            } catch (IllegalAccessException e) {
  +                throw new ValidatorException(e.getMessage());
  +            } catch (InvocationTargetException e) {
  +
  +                if (e.getTargetException() instanceof Exception) {
  +                    throw (Exception) e.getTargetException();
  +
  +                } else if (e.getTargetException() instanceof Error) {
  +                    throw (Error) e.getTargetException();
  +                }
  +            }
  +
  +            boolean valid = this.isValid(result);
  +            if (!valid || (valid && !onlyReturnErrors(params))) {
  +                results.add(field, this.name, valid, result);
  +            }
  +
  +            if (!valid) {
  +                return false;
  +            }
  +
  +            // TODO This catch block remains for backward compatibility.  Remove
  +            // this for Validator 2.0 when exception scheme changes.
  +        } catch (Exception e) {
  +            if (e instanceof ValidatorException) {
  +                throw (ValidatorException) e;
  +            }
  +
  +            log.error(
  +                "Unhandled exception thrown during validation: " + e.getMessage(),
  +                e);
  +
  +            results.add(field, this.name, false);
  +            return false;
  +        }
  +
  +        return true;
  +    }
  +    
  +    /**
  +     * Load the Method object for the configured validation method name.
  +     * @throws ValidatorException
  +     */
  +    private void loadValidationMethod() throws ValidatorException {
  +        if (this.validationMethod != null) {
  +            return;
  +        }
  +     
  +        try {
  +            this.validationMethod =
  +                this.validationClass.getMethod(this.method, this.parameterClasses);
  +     
  +        } catch (NoSuchMethodException e) {
  +            throw new ValidatorException(e.getMessage());
  +        }
  +    }
  +    
  +    /**
  +     * Load the Class object for the configured validation class name.
  +     * @param loader The ClassLoader used to load the Class object.
  +     * @throws ValidatorException
  +     */
  +    private void loadValidationClass(ClassLoader loader) 
  +        throws ValidatorException {
  +        
  +        if (this.validationClass != null) {
  +            return;
  +        }
  +        
  +        try {
  +            this.validationClass = loader.loadClass(this.classname);
  +        } catch (ClassNotFoundException e) {
  +            throw new ValidatorException(e.getMessage());
  +        }
  +    }
  +    
  +    /**
  +     * Converts a List of parameter class names into their Class objects.
  +     * @return An array containing the Class object for each parameter.  This 
  +     * array is in the same order as the given List and is suitable for passing 
  +     * to the validation method.
  +     * @throws ValidatorException if a class cannot be loaded.
  +     */
  +    private void loadParameterClasses(ClassLoader loader)
  +        throws ValidatorException {
  +
  +        if (this.parameterClasses != null) {
  +            return;
  +        }
  +        
  +        this.parameterClasses = new Class[this.methodParameterList.size()];
  +
  +        for (int i = 0; i < this.methodParameterList.size(); i++) {
  +            String paramClassName = (String) this.methodParameterList.get(i);
  +
  +            try {
  +                this.parameterClasses[i] = loader.loadClass(paramClassName);
  +                    
  +            } catch (ClassNotFoundException e) {
  +                throw new ValidatorException(e.getMessage());
  +            }
  +        }
  +    }
  +    
  +    /**
  +     * Converts a List of parameter class names into their values contained in 
  +     * the parameters Map.
  +     * @param params A Map of class names to parameter values.
  +     * @return An array containing the value object for each parameter.  This 
  +     * array is in the same order as the given List and is suitable for passing 
  +     * to the validation method.
  +     */
  +    private Object[] getParameterValues(Map params) {
  +
  +        Object[] paramValue = new Object[this.methodParameterList.size()];
  +
  +        for (int i = 0; i < this.methodParameterList.size(); i++) {
  +            String paramClassName = (String) this.methodParameterList.get(i);
  +            paramValue[i] = params.get(paramClassName);
  +        }
  +
  +        return paramValue;
  +    }
  +    
  +    /**
  +     * Return an instance of the validation class or null if the validation 
  +     * method is static so does not require an instance to be executed.
  +     */
  +    private Object getValidationClassInstance() throws ValidatorException {
  +        if (Modifier.isStatic(this.validationMethod.getModifiers())) {
  +            this.instance = null;
  +
  +        } else {
  +            if (this.instance == null) {
  +                try {
  +                    this.instance = this.validationClass.newInstance();
  +                } catch (InstantiationException e) {
  +                    String msg =
  +                        "Couldn't create instance of "
  +                            + this.classname
  +                            + ".  "
  +                            + e.getMessage();
  +
  +                    throw new ValidatorException(msg);
  +
  +                } catch (IllegalAccessException e) {
  +                    String msg =
  +                        "Couldn't create instance of "
  +                            + this.classname
  +                            + ".  "
  +                            + e.getMessage();
  +
  +                    throw new ValidatorException(msg);
  +                }
  +            }
  +        }
  +
  +        return this.instance;
  +    }
  +    
  +    /**
  +     * Modifies the paramValue array with indexed fields.
  +     *
  +     * @param field
  +     * @param pos
  +     * @param paramValues
  +     */
  +    private void handleIndexedField(Field field, int pos, Object[] paramValues)
  +        throws ValidatorException {
  +
  +        int beanIndex = this.methodParameterList.indexOf(Validator.BEAN_PARAM);
  +        int fieldIndex = this.methodParameterList.indexOf(Validator.FIELD_PARAM);
  +
  +        Object indexedList[] = field.getIndexedProperty(paramValues[beanIndex]);
  +
  +        // Set current iteration object to the parameter array
  +        paramValues[beanIndex] = indexedList[pos];
  +
  +        // Set field clone with the key modified to represent
  +        // the current field
  +        Field indexedField = (Field) field.clone();
  +        indexedField.setKey(
  +            ValidatorUtils.replace(
  +                indexedField.getKey(),
  +                Field.TOKEN_INDEXED,
  +                "[" + pos + "]"));
  +
  +        paramValues[fieldIndex] = indexedField;
  +    }
  +    
  +    /**
  +     * If the result object is a <code>Boolean</code>, it will return its 
  +     * value.  If not it will return <code>false</code> if the object is 
  +     * <code>null</code> and <code>true</code> if it isn't.
  +     */
  +    private boolean isValid(Object result) {
  +        if (result instanceof Boolean) {
  +            Boolean valid = (Boolean) result;
  +            return valid.booleanValue();
  +        } else {
  +            return (result != null);
  +        }
  +    }
  +
  +    /**
  +     * Returns the ClassLoader set in the Validator contained in the parameter
  +     * Map.
  +     */
  +    private ClassLoader getClassLoader(Map params) {
  +        Validator v = (Validator) params.get(Validator.VALIDATOR_PARAM);
  +        return v.getClassLoader();
  +    }
  +    
  +    /**
  +     * Returns the onlyReturnErrors setting in the Validator contained in the 
  +     * parameter Map.
  +     */
  +    private boolean onlyReturnErrors(Map params) {
  +        Validator v = (Validator) params.get(Validator.VALIDATOR_PARAM);
  +        return v.getOnlyReturnErrors();
       }
   
   }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to