DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT <http://nagoya.apache.org/bugzilla/show_bug.cgi?id=8787>. ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND INSERTED IN THE BUG DATABASE.
http://nagoya.apache.org/bugzilla/show_bug.cgi?id=8787 Indexed field validation patch Summary: Indexed field validation patch Product: Commons Version: Nightly Builds Platform: All OS/Version: All Status: NEW Severity: Enhancement Priority: Other Component: Validator AssignedTo: [EMAIL PROTECTED] ReportedBy: [EMAIL PROTECTED] I need indexed field validation for my application. I've started to work on it and realized it's quite a large project. This is what I've got so far. I still need to change validation-rules.xml to work with these changes, but this code generates field names for indexed properties. Comments? Suggestions? Am I even on the right path? ? validator/validator.patch ? validator/src/share/validator.patch Index: validator/src/share/org/apache/commons/validator/Field.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/validator/src/share/org/apache/commons/validator/Field.java,v retrieving revision 1.5 diff -u -3 -p -r1.5 Field.java --- validator/src/share/org/apache/commons/validator/Field.java 30 Mar 2002 04:33:17 -0000 1.5 +++ validator/src/share/org/apache/commons/validator/Field.java 3 May 2002 16:56:26 +-0000 @@ -68,11 +68,11 @@ import java.util.Collections; import java.util.Iterator; import java.util.Map; import java.util.StringTokenizer; -import org.apache.commons.collections.FastHashMap; +import org.apache.commons.collections.FastHashMap; /** - * <p>This contains the list of pluggable validators to + * <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.</p> * @@ -83,7 +83,7 @@ import org.apache.commons.collections.Fa public class Field implements Cloneable, Serializable { /** - * This is the value that will be used as a key if the <code>Arg</code> + * This is the value that will be used as a key if the <code>Arg</code> * name field has no value. */ public final static String ARG_DEFAULT = "org.apache.commons.validator.Field.DEFAULT"; @@ -100,6 +100,7 @@ public class Field implements Cloneable, protected String property = null; protected String indexedProperty = null; protected String indexedListProperty = null; + protected String iteratorName = null; protected String key = null; protected String depends = null; protected int page = 0; @@ -115,26 +116,26 @@ public class Field implements Cloneable, /** - * Gets the page value that the Field is associated with for + * Gets the page value that the Field is associated with for * validation. */ public int getPage() { - return page; + return page; } /** - * Sets the page value that the Field is associated with for + * Sets the page value that the Field is associated with for * validation. */ public void setPage(int page) { - this.page = page; + this.page = page; } /** * Gets the position of the <code>Field</code> in the validation list. */ public int getFieldOrder() { - return fieldOrder; + return fieldOrder; } @@ -142,7 +143,7 @@ public class Field implements Cloneable, * Sets the position of the <code>Field</code> in the validation list. */ public void setFieldOrder(int fieldOrder) { - this.fieldOrder = fieldOrder; + this.fieldOrder = fieldOrder; } @@ -150,7 +151,7 @@ public class Field implements Cloneable, * Gets the property name of the field. */ public String getProperty() { - return property; + return property; } @@ -158,16 +159,16 @@ public class Field implements Cloneable, * Sets the property name of the field. */ public void setProperty(String property) { - this.property = property; + this.property = property; } /** - * Gets the indexed property name of the field. This - * is the method name that can take an <code>int</code> as + * Gets the indexed property name of the field. This + * is the method name that can take an <code>int</code> as * a parameter for indexed property value retrieval. */ public String getIndexedProperty() { - return indexedProperty; + return indexedProperty; } @@ -175,18 +176,18 @@ public class Field implements Cloneable, * Sets the indexed property name of the field. */ public void setIndexedProperty(String indexedProperty) { - this.indexedProperty = indexedProperty; + this.indexedProperty = indexedProperty; } /** - * Gets the indexed property name of the field. This - * is the method name that will return an array or a - * <code>Collection</code> used to retrieve the - * list and then loop through the list performing the specified + * Gets the indexed property name of the field. This + * is the method name that will return an array or a + * <code>Collection</code> used to retrieve the + * list and then loop through the list performing the specified * validations. */ public String getIndexedListProperty() { - return indexedListProperty; + return indexedListProperty; } @@ -194,21 +195,39 @@ public class Field implements Cloneable, * Sets the indexed property name of the field. */ public void setIndexedListProperty(String indexedListProperty) { - this.indexedListProperty = indexedListProperty; + this.indexedListProperty = indexedListProperty; } + /** + * For indexed properties, the name of the JSP bean containing the + * <code>Collection</code> that was iterated (if indexedListProperty is not + * specified), or the JSP bean whose property getter returns the collection + * that was iterated (if indexedListProperty is specified). + */ + public String getIteratorName() { + return iteratorName; + } + + + /** + * For indexed properties, sets the name of the JSP bean containing the + * <code>Collection</code> that was iterated. + */ + public void setIteratorName(String iteratorName) { + this.iteratorName = iteratorName; + } /** * Gets the validation rules for this field. */ public String getDepends() { - return depends; + return depends; } /** * Sets the validation rules for this field. */ public void setDepends(String depends) { - this.depends = depends; + this.depends = depends; } /** @@ -245,11 +264,11 @@ public class Field implements Cloneable, * Gets the default arg0 <code>Arg</code> object. */ public Arg getArg0() { - return (Arg)hArg0.get(ARG_DEFAULT); + return (Arg)hArg0.get(ARG_DEFAULT); } /** - * Gets the arg0 <code>Arg</code> object based on the key passed in. If the key + * Gets the arg0 <code>Arg</code> object based on the key passed in. If the key * finds a <code>null</code> value then the default value will try to be retrieved. */ public Arg getArg0(String key) { @@ -275,11 +294,11 @@ public class Field implements Cloneable, * Gets the default arg1 <code>Arg</code> object. */ public Arg getArg1() { - return (Arg)hArg1.get(ARG_DEFAULT); + return (Arg)hArg1.get(ARG_DEFAULT); } /** - * Gets the arg1 <code>Arg</code> object based on the key passed in. If the key + * Gets the arg1 <code>Arg</code> object based on the key passed in. If the key * finds a <code>null</code> value then the default value will try to be retrieved. */ public Arg getArg1(String key) { @@ -305,11 +324,11 @@ public class Field implements Cloneable, * Gets the default arg2 <code>Arg</code> object. */ public Arg getArg2() { - return (Arg)hArg2.get(ARG_DEFAULT); + return (Arg)hArg2.get(ARG_DEFAULT); } /** - * Gets the arg2 <code>Arg</code> object based on the key passed in. If the key + * Gets the arg2 <code>Arg</code> object based on the key passed in. If the key * finds a <code>null</code> value then the default value will try to be retrieved. */ public Arg getArg2(String key) { @@ -335,11 +354,11 @@ public class Field implements Cloneable, * Gets the default arg3 <code>Arg</code> object. */ public Arg getArg3() { - return (Arg)hArg3.get(ARG_DEFAULT); + return (Arg)hArg3.get(ARG_DEFAULT); } /** - * Gets the arg3 <code>Arg</code> object based on the key passed in. If the key + * Gets the arg3 <code>Arg</code> object based on the key passed in. If the key * finds a <code>null</code> value then the default value will try to be retrieved. */ public Arg getArg3(String key) { @@ -389,7 +408,7 @@ public class Field implements Cloneable, } /** - * The <code>Field</code>'s variables are returned as an + * The <code>Field</code>'s variables are returned as an * unmodifiable <code>Map</code>. */ public Map getVars() { @@ -401,14 +420,13 @@ public class Field implements Cloneable, */ public String getKey() { if (key == null) { - generateKey(); + key = property; } - return key; } /** - * Sets a unique key for the field. This can be used to change + * Sets a unique key for the field. This can be used to change * the key temporarily to have a unique key for an indexed field. */ public void setKey(String key) { @@ -416,26 +434,22 @@ public class Field implements Cloneable, } /** - * If there is a value specified for the indexedProperty field then - * <code>true</code> will be returned. Otherwise it will be <code>false</code>. + * If there is a value specified for the indexedProperty field and either + * iteratorName or indexedListProperty then <code>true</code> will be + * returned. Otherwise it will be <code>false</code>. */ public boolean isIndexed() { - return ((indexedListProperty != null && indexedListProperty.length() > 0)); - } - - /** - * Generate correct <code>key</code> value. - */ - public void generateKey() { - if (isIndexed()) { - key = indexedListProperty + TOKEN_INDEXED + "." + property; - } else { - key = property; - } + return ( + (indexedProperty != null && indexedProperty.length() > 0) && + ( + (iteratorName != null && iteratorName.length() > 0) || + (indexedListProperty != null && indexedListProperty.length() > 0) + ) + ); } /** - * Replace constants with values in fields and process the depends field + * Replace constants with values in fields and process the depends field * to create the dependency <code>Map</code>. */ public void process(Map globalConstants, Map constants) { @@ -446,7 +460,7 @@ public class Field implements Cloneable, hArg3.setFast(true); hVars.setFast(true); - generateKey(); + getKey(); // Process FormSet Constants for (Iterator i = constants.keySet().iterator(); i.hasNext(); ) { @@ -556,7 +570,7 @@ public class Field implements Cloneable, */ public boolean isDependency(String key) { if (hDependencies != null) { - return hDependencies.containsKey(key); + return hDependencies.containsKey(key); } else { return false; } @@ -610,11 +624,11 @@ public class Field implements Cloneable, } catch (CloneNotSupportedException e) { throw new InternalError(e.toString()); } - } + } /** * Returns a string representation of the object. - */ + */ public String toString() { StringBuffer results = new StringBuffer(); @@ -642,3 +656,4 @@ public class Field implements Cloneable, } } + Index: validator/src/share/org/apache/commons/validator/Validator.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/validator/src/share/org/apache/commons/validator/Validator.java,v retrieving revision 1.7 diff -u -3 -p -r1.7 Validator.java --- validator/src/share/org/apache/commons/validator/Validator.java 30 Mar 2002 04:28:35 -0000 1.7 +++ validator/src/share/org/apache/commons/validator/Validator.java 3 May 2002 +16:56:26 -0000 @@ -67,12 +67,14 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; +import java.util.Enumeration; 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 java.lang.reflect.Array; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import org.apache.commons.beanutils.PropertyUtils; @@ -81,9 +83,9 @@ import org.apache.commons.logging.LogSou /** - * <p>Validations are processed by the validate method. - * An instance of <code>ValidatorResources</code> is - * used to define the validators (validation methods) + * <p>Validations are processed by the validate method. + * An instance of <code>ValidatorResources</code> is + * used to define the validators (validation methods) * and the validation rules for a JavaBean.</p> * * @author David Winterfeldt @@ -102,25 +104,25 @@ public class Validator implements Serial public static String BEAN_KEY = "java.lang.Object"; /** - * Resources key the <code>ValidatorAction</code> is stored under. - * This will be automatically passed into a validation method - * with the current <code>ValidatorAction</code> if it is + * Resources key the <code>ValidatorAction</code> is stored under. + * This will be automatically passed into a validation method + * with the current <code>ValidatorAction</code> if it is * specified in the method signature. */ public static String VALIDATOR_ACTION_KEY = "org.apache.commons.validator.ValidatorAction"; /** - * Resources key the <code>Field</code> is stored under. - * This will be automatically passed into a validation method - * with the current <code>Field</code> if it is + * Resources key the <code>Field</code> is stored under. + * This will be automatically passed into a validation method + * with the current <code>Field</code> if it is * specified in the method signature. */ public static String FIELD_KEY = "org.apache.commons.validator.Field"; /** * Resources key the <code>Locale</code> is stored. - * This will be used to retrieve the appropriate - * <code>FormSet</code> and <code>Form</code> to be + * This will be used to retrieve the appropriate + * <code>FormSet</code> and <code>Form</code> to be * processed. */ public static String LOCALE_KEY = "java.util.Locale"; @@ -128,7 +130,7 @@ public class Validator implements Serial protected ValidatorResources resources = null; protected String formName = null; protected HashMap hResources = new HashMap(); - protected int page = 0; + protected int page = 0; /** * The class loader to use for instantiating application objects. @@ -145,12 +147,12 @@ public class Validator implements Serial protected boolean useContextClassLoader = false; /** - * Construct a <code>Validator</code> that will - * use the <code>ValidatorResources</code> - * passed in to retrieve pluggable validators + * Construct a <code>Validator</code> that will + * use the <code>ValidatorResources</code> + * passed in to retrieve pluggable validators * the different sets of validation rules. * - * @param resources <code>ValidatorResources</code> + * @param resources <code>ValidatorResources</code> * to use during validation. */ public Validator(ValidatorResources resources) { @@ -158,14 +160,14 @@ public class Validator implements Serial } /** - * Construct a <code>Validator</code> that will - * use the <code>ValidatorResources</code> - * passed in to retrieve pluggable validators + * Construct a <code>Validator</code> that will + * use the <code>ValidatorResources</code> + * passed in to retrieve pluggable validators * the different sets of validation rules. * - * @param resources <code>ValidatorResources</code> + * @param resources <code>ValidatorResources</code> * to use during validation. - * @param formName Key used for retrieving the set of + * @param formName Key used for retrieving the set of * validation rules. */ public Validator(ValidatorResources resources, String formName) { @@ -174,14 +176,14 @@ public class Validator implements Serial } /** - * Add a resource to be used during the processing + * Add a resource to be used during the processing * of validations. * - * @param key The full class name of the parameter - * of the validation method that - * corresponds to the value/instance + * @param key The full class name of the parameter + * of the validation method that + * corresponds to the value/instance * passed in with it. - * @param value The instance that will be passed + * @param value The instance that will be passed * into the validation method. */ public void addResource(String key, Object value) { @@ -189,58 +191,58 @@ public class Validator implements Serial } /** - * Gets the form name which is the key + * Gets the form name which is the key * to a set of validation rules. */ public String getFormName() { - return formName; + return formName; } /** - * Sets the form name which is the key + * Sets the form name which is the key * to a set of validation rules. */ public void setFormName(String formName) { - this.formName = formName; + this.formName = formName; } /** - * Gets the page. This in conjunction with - * the page property of a <code>Field<code> - * can control the processing of fields. - * If the field's page is less than or equal + * Gets the page. This in conjunction with + * the page property of a <code>Field<code> + * can control the processing of fields. + * If the field's page is less than or equal * to this page value, it will be processed. */ public int getPage() { - return page; + return page; } /** - * Sets the page. This in conjunction with - * the page property of a <code>Field<code> - * can control the processing of fields. - * If the field's page is less than or equal + * Sets the page. This in conjunction with + * the page property of a <code>Field<code> + * can control the processing of fields. + * If the field's page is less than or equal * to this page value, it will be processed. */ public void setPage(int page) { - this.page = page; + this.page = page; } /** - * Clears the form name, resources that were added, - * and the page that was set (if any). This can - * be called to reinitialize the Validator instance - * so it can be reused. The form name (key to - * set of validation rules) and any resources needed, - * like the JavaBean being validated, will need to - * set and/or added to this instance again. The - * <code>ValidatorResources</code> will not be removed + * Clears the form name, resources that were added, + * and the page that was set (if any). This can + * be called to reinitialize the Validator instance + * so it can be reused. The form name (key to + * set of validation rules) and any resources needed, + * like the JavaBean being validated, will need to + * set and/or added to this instance again. The + * <code>ValidatorResources</code> will not be removed * since it can be used again and is thread safe. */ public void clear() { formName = null; hResources = new HashMap(); - page = 0; + page = 0; } /** @@ -307,12 +309,12 @@ public class Validator implements Serial } /** - * Performs validations based on the configured resources. - * - * @return The <code>Map</code> returned uses the property - * of the <code>Field</code> for the key and the value + * Performs validations based on the configured resources. + * + * @return The <code>Map</code> returned uses the property + * of the <code>Field</code> for the key and the value * is the number of error the field had. - */ + */ public ValidatorResults validate() throws ValidatorException { ValidatorResults results = new ValidatorResults(); Locale locale = null; @@ -326,7 +328,7 @@ public class Validator implements Serial } Form form = null; - if ((form = resources.get(locale, formName)) != null) { + if ((form = resources.get(locale, formName)) != null) { Map hActions = resources.getValidatorActions(); List lActions = new ArrayList(); Map hActionsRun = new HashMap(); @@ -382,7 +384,7 @@ public class Validator implements Serial } } - // For debug + // For debug if (log.isDebugEnabled()) { StringBuffer sbLog = new StringBuffer(); @@ -398,11 +400,11 @@ public class Validator implements Serial if (va != null) { for (Iterator i = form.getFields().iterator(); i.hasNext(); ) { - Field field = (Field)i.next(); + Field field = (Field)i.next(); if (field.getPage() <= page && (field.getDepends() != null && field.isDependency(va.getName()))) { try { - // Add these two Objects to the resources since they reference + // Add these two Objects to the resources since they reference // the current validator action and field hResources.put(VALIDATOR_ACTION_KEY, va); hResources.put(FIELD_KEY, field); @@ -435,7 +437,7 @@ public class Validator implements Serial Method m = c.getMethod(va.getMethod(), paramClass); - // If the method is static we don't need an instance of the class + // If the method is static we don't need an instance of the +class // to call the method. If it isn't, we do. if (!Modifier.isStatic(m.getModifiers())) { try { @@ -451,20 +453,33 @@ public class Validator implements Serial Object result = null; if (field.isIndexed()) { - Object oIndexed = PropertyUtils.getProperty(hResources.get(BEAN_KEY), field.getIndexedListProperty()); - Object indexedList[] = new Object[0]; + Object oIndexed; + Iterator iterator = null; + + if( field.getIndexedListProperty() == null ) + oIndexed = hResources.get(BEAN_KEY); + else + oIndexed = PropertyUtils.getProperty(hResources.get(BEAN_KEY), field.getIndexedListProperty()); - if (oIndexed instanceof Collection) { - indexedList = ((Collection)oIndexed).toArray(); - } else if(oIndexed.getClass().isArray()) { - indexedList = (Object[])oIndexed; - } + if (oIndexed.getClass().isArray()) { + int length = Array.getLength(oIndexed); + ArrayList cList = new ArrayList(length); + for (int pos = 0; pos < length; pos++) { + cList.add(Array.get(oIndexed, pos)); + } + iterator = cList.iterator(); + } else if (oIndexed instanceof Collection) + iterator = ((Collection) oIndexed).iterator(); + else if (oIndexed instanceof Iterator) + iterator = (Iterator) oIndexed; + else if (oIndexed instanceof Map) + iterator = ((Map) oIndexed).entrySet().iterator(); - for (int pos = 0; pos < indexedList.length; pos++) { + for (int pos = 0; (iterator != null) && iterator.hasNext(); pos++) { // Set current iteration object to the parameter array - paramValue[beanIndexPos] = indexedList[pos]; + paramValue[beanIndexPos] = iterator.next(); - // Set field clone with the key modified to represent + // Set field clone with the key modified to represent // the current field Field indexedField = (Field)field.clone(); indexedField.setKey(ValidatorUtil.replace(indexedField.getKey(), Field.TOKEN_INDEXED, "[" + pos + "]")); @@ -524,11 +539,11 @@ public class Validator implements Serial } /** - * 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 + * 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) { @@ -553,13 +568,13 @@ public class Validator implements Serial ValidatorAction va1 = (ValidatorAction)o1; ValidatorAction va2 = (ValidatorAction)o2; - if ((va1.getDepends() == null || va1.getDepends().length() == 0) && + if ((va1.getDepends() == null || va1.getDepends().length() == 0) && (va2.getDepends() == null || va2.getDepends().length() == 0)) { return 0; } else if ((va1.getDepends() != null && va1.getDepends().length() > 0) && (va2.getDepends() == null || va2.getDepends().length() == 0)) { return 1; - } else if ((va1.getDepends() == null || va1.getDepends().length() == 0) && + } else if ((va1.getDepends() == null || va1.getDepends().length() == 0) && (va2.getDepends() != null && va2.getDepends().length() > 0)) { return -1; } else { @@ -583,13 +598,13 @@ public class Validator implements Serial ValidatorAction va1 = (ValidatorAction)o1; ValidatorAction va2 = (ValidatorAction)o2; - if ((va1.getDepends() == null || va1.getDepends().length() == 0) && + if ((va1.getDepends() == null || va1.getDepends().length() == 0) && (va2.getDepends() == null || va2.getDepends().length() == 0)) { return 0; } else if ((va1.getDepends() != null && va1.getDepends().length() > 0) && (va2.getDepends() == null || va2.getDepends().length() == 0)) { return 1; - } else if ((va1.getDepends() == null || va1.getDepends().length() == 0) && + } else if ((va1.getDepends() == null || va1.getDepends().length() == 0) && (va2.getDepends() != null && va2.getDepends().length() > 0)) { return -1; } else { @@ -613,7 +628,7 @@ public class Validator implements Serial if (o != null) { if (((Boolean)o).booleanValue()) iVA2++; - } + } } return iVA1 - iVA2; -- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>