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=8788>.
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=8788

Indexed field validation patch

           Summary: Indexed field validation patch
           Product: Struts
           Version: Nightly Build
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: Enhancement
          Priority: Other
         Component: Custom Tags
        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.  You'll also need the patch I've
submitted for commons-validator.

Comments? Suggestions?  Am I even on the right path?

Index: src/share/org/apache/struts/taglib/html/JavascriptValidatorTag.java
===================================================================
RCS file:
/home/cvspublic/jakarta-struts/src/share/org/apache/struts/taglib/html/JavascriptValidatorTag.java,v
retrieving revision 1.2
diff -u -3 -p -r1.2 JavascriptValidatorTag.java
--- src/share/org/apache/struts/taglib/html/JavascriptValidatorTag.java 18 Mar 2002 
02:06:41 -0000      1.2
+++ src/share/org/apache/struts/taglib/html/JavascriptValidatorTag.java 3 May 2002 
+17:12:41 -0000
@@ -56,10 +56,13 @@
 package org.apache.struts.taglib.html;
 
 
+import java.lang.reflect.Array;
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Collections; 
-import java.util.Comparator; 
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Enumeration;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
@@ -76,13 +79,15 @@ import org.apache.commons.validator.Vali
 import org.apache.commons.validator.Var;
 import org.apache.struts.action.Action;
 import org.apache.struts.validator.ValidatorPlugIn;
+import org.apache.struts.util.IteratorAdapter;
 import org.apache.struts.util.MessageResources;
+import org.apache.struts.util.RequestUtils;
 import org.apache.struts.util.StrutsValidatorUtil;
 
 
 /**
- * Custom tag that generates JavaScript for client side validation based 
- * on the validation rules loaded by the <code>ValidatorPlugIn</code> 
+ * Custom tag that generates JavaScript for client side validation based
+ * on the validation rules loaded by the <code>ValidatorPlugIn</code>
  * defined in the struts-config.xml file.
  *
  * @since 1.1
@@ -92,6 +97,12 @@ public class JavascriptValidatorTag exte
 
 
     // ----------------------------------------------------------- Properties
+
/**
+     * The message resources for this package.
+     */
+    protected static MessageResources messages =
+
MessageResources.getMessageResources
+
("org.apache.struts.taglib.html.LocalStrings");
 
 
     /**
@@ -106,18 +117,18 @@ public class JavascriptValidatorTag exte
     protected static Locale defaultLocale = Locale.getDefault();
 
     /**
-     * The name of the form that corresponds with the action name 
+     * The name of the form that corresponds with the action name
      * in struts-config.xml.
     */
     protected String formName = null;
 
     /**
-     * The current page number of a multi-part form. 
+     * The current page number of a multi-part form.
     */
     protected int page = 0;
 
     /**
-     * This will be used as is for the JavaScript validation method name if it
has a value.  This is 
+     * This will be used as is for the JavaScript validation method name if it
has a value.  This is
      * the method name of the main JavaScript method that the form calls to
perform validations.
     */
     protected String methodName = null;
@@ -138,17 +149,17 @@ public class JavascriptValidatorTag exte
     protected String src = null;
     
     /**
-     * Gets the key (form name) that will be used 
-     * to retrieve a set of validation rules to be 
+     * Gets the key (form name) that will be used
+     * to retrieve a set of validation rules to be
      * performed on the bean passed in for validation.
     */
     public String getFormName() {
-       return formName;        
+       return formName;
     }
 
     /**
-     * Sets the key (form name) that will be used 
-     * to retrieve a set of validation rules to be 
+     * Sets the key (form name) that will be used
+     * to retrieve a set of validation rules to be
      * performed on the bean passed in for validation.
     */
     public void setFormName(String formName) {
@@ -156,17 +167,17 @@ public class JavascriptValidatorTag exte
     }
 
     /**
-     * Gets the current page number of a multi-part form. 
-     * Only field validations with a matching page numer 
+     * Gets the current page number of a multi-part form.
+     * Only field validations with a matching page numer
      * will be generated that match the current page number.
     */
     public int getPage() {
-       return page;    
+       return page;
     }
 
     /**
-     * Sets the current page number of a multi-part form. 
-     * Only field validations with a matching page numer 
+     * Sets the current page number of a multi-part form.
+     * Only field validations with a matching page numer
      * will be generated that match the current page number.
     */
     public void setPage(int page) {
@@ -174,19 +185,19 @@ public class JavascriptValidatorTag exte
     }
 
     /**
-     * Gets the method name that will be used for the Javascript 
-     * validation method name if it has a value.  This overrides 
-     * the auto-generated method name based on the key (form name) 
+     * Gets the method name that will be used for the Javascript
+     * validation method name if it has a value.  This overrides
+     * the auto-generated method name based on the key (form name)
      * passed in.
     */
     public String getMethod() {
-       return methodName;      
+       return methodName;
     }
 
     /**
-     * Sets the method name that will be used for the Javascript 
-     * validation method name if it has a value.  This overrides 
-     * the auto-generated method name based on the key (form name) 
+     * Sets the method name that will be used for the Javascript
+     * validation method name if it has a value.  This overrides
+     * the auto-generated method name based on the key (form name)
      * passed in.
     */
     public void setMethod(String methodName) {
@@ -194,17 +205,17 @@ public class JavascriptValidatorTag exte
     }
     
     /**
-     * Gets whether or not to generate the static 
-     * JavaScript.  If this is set to 'true', which 
+     * Gets whether or not to generate the static
+     * JavaScript.  If this is set to 'true', which
      * is the default, the static JavaScript will be generated.
     */
     public String getStaticJavascript() {
-       return staticJavascript;        
+       return staticJavascript;
     }
 
     /**
-     * Sets whether or not to generate the static 
-     * JavaScript.  If this is set to 'true', which 
+     * Sets whether or not to generate the static
+     * JavaScript.  If this is set to 'true', which
      * is the default, the static JavaScript will be generated.
     */
     public void setStaticJavascript(String staticJavascript) {
@@ -212,17 +223,17 @@ public class JavascriptValidatorTag exte
     }
 
     /**
-     * Gets whether or not to generate the dynamic 
-     * JavaScript.  If this is set to 'true', which 
+     * Gets whether or not to generate the dynamic
+     * JavaScript.  If this is set to 'true', which
      * is the default, the dynamic JavaScript will be generated.
     */
     public String getDynamicJavascript() {
-       return dynamicJavascript;       
+       return dynamicJavascript;
     }
 
     /**
-     * Sets whether or not to generate the dynamic 
-     * JavaScript.  If this is set to 'true', which 
+     * Sets whether or not to generate the dynamic
+     * JavaScript.  If this is set to 'true', which
      * is the default, the dynamic JavaScript will be generated.
     */
     public void setDynamicJavascript(String dynamicJavascript) {
@@ -230,15 +241,15 @@ public class JavascriptValidatorTag exte
     }
 
     /**
-     * Gets the src attribute's value when defining 
+     * Gets the src attribute's value when defining
      * the html script element.
     */
     public String getSrc() {
-       return src;     
+       return src;
     }
 
     /**
-     * Sets the src attribute's value when defining 
+     * Sets the src attribute's value when defining
      * the html script element.
     */
     public void setSrc(String src) {
@@ -279,7 +290,7 @@ public class JavascriptValidatorTag exte
           for (Iterator i = form.getFields().iterator(); i.hasNext(); ) {
              Field field = (Field)i.next();
           
-             for (Iterator x = field.getDependencies().iterator(); x.hasNext();
) {   
+             for (Iterator x = field.getDependencies().iterator(); x.hasNext(); ) {
                Object o = x.next();
                
                if (o != null && !lActionMethods.contains(o)) {
@@ -306,20 +317,20 @@ public class JavascriptValidatorTag exte
                 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 {
                    return va1.getDependencies().size() -
va2.getDependencies().size();
                 }
              }
-          });             
+          });
           
           String methods = null;
           for (Iterator i = lActions.iterator(); i.hasNext(); ) {
@@ -347,43 +358,46 @@ public class JavascriptValidatorTag exte
              
              results.append("   function " + functionName + " () { \n");
              for (Iterator x = form.getFields().iterator(); x.hasNext(); ) {
-                Field field = (Field)x.next();         
+                Field field = (Field)x.next();
 
-                // Skip indexed fields for now until there is 
+                // Skip indexed fields for now until there is
                 // a good way to handle error messages (and the length of the
list (could retrieve from scope?))
-                if (!field.isIndexed() && field.getPage() == page &&
field.isDependency(va.getName())) {
+                if ( field.getPage() == page && field.isDependency(va.getName())) {
                   String message = StrutsValidatorUtil.getMessage(messages, locale, 
va, field);
                   message = (message != null ? message : "");
           
-                   jscriptVar = getNextVar(jscriptVar);
-          
-                   results.append("        this." + jscriptVar + " = new Array(\"" + 
field.getKey()
+ "\", \"" + message + "\", ");
-                   
-                   results.append("new Function (\"varName\", \"");
-                   
-                   Map hVars = field.getVars();
-                   // Loop through the field's variables.
-                   for (Iterator iVars = hVars.keySet().iterator();
iVars.hasNext(); ) {
-                      String varKey = (String)iVars.next();
-                      Var var = (Var)hVars.get(varKey);
-                      String varValue = var.getValue();
-                      String jsType = var.getJsType();
-
               
-
               if (Var.JSTYPE_INT.equalsIgnoreCase(jsType)) {
-
                  results.append("this." + varKey + "=" +
ValidatorUtil.replace(varValue, "\\", "\\\\") + "; ");
-
               } else if (Var.JSTYPE_REGEXP.equalsIgnoreCase(jsType)) {
-
                  results.append("this." + varKey + "=/" +
ValidatorUtil.replace(varValue, "\\", "\\\\") + "/; ");
-
               } else if (Var.JSTYPE_STRING.equalsIgnoreCase(jsType)) {
-
                  results.append("this." + varKey + "='" +
ValidatorUtil.replace(varValue, "\\", "\\\\") + "'; ");
-
               // So everyone using the latest format doesn't need to change
their xml files immediately.
-
               } else if ("mask".equalsIgnoreCase(varKey)) {
-
                  results.append("this." + varKey + "=/" +
ValidatorUtil.replace(varValue, "\\", "\\\\") + "/; ");
-
               } else {
-
                  results.append("this." + varKey + "='" +
ValidatorUtil.replace(varValue, "\\", "\\\\") + "'; ");
-
               }
-                   }
-                                               
-                   results.append(" return this[varName];\"));\n");
+                   generateParameterNames( results, field, message, jscriptVar );
+//
                           jscriptVar = getNextVar(jscriptVar);
+//
+//                   results.append("      this." + jscriptVar + " = new Array(\"" );
+//
                           results.append( field.getKey() );
+//
                           results.append( "\", \"" + message + "\", ");
+//
+//                   results.append("new Function (\"varName\", \"");
+//
+//                   Map hVars = field.getVars();
+//                   // Loop through the field's variables.
+//                   for (Iterator iVars = hVars.keySet().iterator();
iVars.hasNext(); ) {
+//                      String varKey = (String)iVars.next();
+//                      Var var = (Var)hVars.get(varKey);
+//                      String varValue = var.getValue();
+//                      String jsType = var.getJsType();
+//
+//
               if (Var.JSTYPE_INT.equalsIgnoreCase(jsType)) {
+//
                  results.append("this." + varKey + "=" +
ValidatorUtil.replace(varValue, "\\", "\\\\") + "; ");
+//
               } else if (Var.JSTYPE_REGEXP.equalsIgnoreCase(jsType)) {
+//
                  results.append("this." + varKey + "=/" +
ValidatorUtil.replace(varValue, "\\", "\\\\") + "/; ");
+//
               } else if (Var.JSTYPE_STRING.equalsIgnoreCase(jsType)) {
+//
                  results.append("this." + varKey + "='" +
ValidatorUtil.replace(varValue, "\\", "\\\\") + "'; ");
+//
               // So everyone using the latest format doesn't need to change
their xml files immediately.
+//
               } else if ("mask".equalsIgnoreCase(varKey)) {
+//
                  results.append("this." + varKey + "=/" +
ValidatorUtil.replace(varValue, "\\", "\\\\") + "/; ");
+//
               } else {
+//
                  results.append("this." + varKey + "='" +
ValidatorUtil.replace(varValue, "\\", "\\\\") + "'; ");
+//
               }
+//                   }
+//
+//                   results.append(" return this[varName];\"));\n");
                 }
              }
              results.append("   } \n\n");
@@ -444,12 +458,12 @@ public class JavascriptValidatorTag exte
 
        if (methodName == null || methodName.length() == 0)
           sb.append("   function validate" + name + "(form) {                         
      
                                   \n");
-       else              
+       else
           sb.append("   function " + methodName + "(form) {                           
      
                                 \n");
                          
        sb.append("           if (bCancel) \n");
        sb.append("             return true; \n");
-       sb.append("           else \n");     
+       sb.append("           else \n");
        
        // Always return true if there aren't any Javascript validation methods
        if (methods == null || methods.length() == 0) {
@@ -489,12 +503,119 @@ public class JavascriptValidatorTag exte
        sb.append("</SCRIPT>\n\n");
        
        return sb.toString();
-    }    
+    }
+

+
/**
+
 * Hopefully creates correct parameter names for indexed fields
+
 */
+
protected void generateParameterNames( StringBuffer results,
+
                                                                                       
  Field field, String message,
+
                                                                                       
 String jscriptVar )
+
        throws JspException
+
{
+
        jscriptVar = getNextVar(jscriptVar);
+
        results.append("            this." + jscriptVar + " = new Array(" );
+
        
+
        if( field.isIndexed() ) {
+
                //Get the collection (worry about scope??)
+
                Object collection = RequestUtils.lookup(pageContext,
+
                                                                                       
         field.getIteratorName(),
+
                                                                                       
         field.getIndexedListProperty(),
+
                                                                                       
         null );
+
                if (collection == null) {
+
                        JspException e = new JspException(
messages.getMessage("javascriptValidatorTag.collection"));
+
                        RequestUtils.saveException(pageContext, e);
+
                        throw e;
+
                }
+
                // Construct an iterator for this collection
+
                Iterator iterator = null;
+
                
+
                if (collection.getClass().isArray()) {
+
                        int length = Array.getLength(collection);
+
                        ArrayList c = new ArrayList(length);
+
                        for (int i = 0; i < length; i++) {
+
                                c.add(Array.get(collection, i));
+
                        }
+
                        iterator = c.iterator();
+
                } else if (collection instanceof Collection)
+
                        iterator = ((Collection) collection).iterator();
+
                else if (collection instanceof Iterator)
+
                        iterator = (Iterator) collection;
+
                else if (collection instanceof Map)
+
                        iterator = ((Map) collection).entrySet().iterator();
+
                else if (collection instanceof Enumeration)
+
                        iterator = new IteratorAdapter((Enumeration)collection);
+
                else {
+
                        JspException e = new JspException
+
                                
(messages.getMessage("javascriptValidatorTag.iterator"));
+
                        RequestUtils.saveException(pageContext, e);
+
                        throw e;
+
                }
+
                
+
                //And finally build the parameter names
+
                for (int pos = 0; (iterator != null) && iterator.hasNext(); pos++) {
+
                        StringBuffer fieldName = new StringBuffer();
+
                        iterator.next();
+
                        
+
                        results.append( "new Array(\"" );
+
                        fieldName.append( field.getIndexedProperty() );
+
                        fieldName.append( "[" );
+
                        fieldName.append( pos );
+
                        fieldName.append( "]." );
+
                        fieldName.append( field.getKey() );
+
                        generateParameterName( results, field, message, 
fieldName.toString() );
+
                        
+
                        if( iterator.hasNext() ) results.append( ",\n" );
+
                }
+
                results.append( ")" );
+
        }
+
        else {
+
                results.append( "\"" );
+
                generateParameterName( results, field, message, field.getKey() );
+
        }
+
        
+
        results.append( ";\n" );
+
}
+
/**
+
 * Hopefully creates correct parameter names for indexed fields
+
 */
+
protected static void generateParameterName( StringBuffer results,
+
                                                                                       
  Field field, String message,
+
                                                                                       
  String fieldName )
+
{
+
        results.append( fieldName );
+
        results.append( "\", \"" + message + "\", ");
+
        results.append("new Function (\"varName\", \"");
+
        
+
        Map hVars = field.getVars();
+
        // Loop through the field's variables.
+
        for (Iterator iVars = hVars.keySet().iterator(); iVars.hasNext(); ) {
+
                String varKey = (String)iVars.next();
+
                Var var = (Var)hVars.get(varKey);
+
                String varValue = var.getValue();
+
                String jsType = var.getJsType();
+
                
+
                if (Var.JSTYPE_INT.equalsIgnoreCase(jsType)) {
+
                        results.append("this." + varKey + "=" + 
ValidatorUtil.replace(varValue, "\\",
"\\\\") + "; ");
+
                } else if (Var.JSTYPE_REGEXP.equalsIgnoreCase(jsType)) {
+
                        results.append("this." + varKey + "=/" + 
ValidatorUtil.replace(varValue, "\\",
"\\\\") + "/; ");
+
                } else if (Var.JSTYPE_STRING.equalsIgnoreCase(jsType)) {
+
                        results.append("this." + varKey + "='" + 
ValidatorUtil.replace(varValue, "\\",
"\\\\") + "'; ");
+
                // So everyone using the latest format doesn't need to change their 
xml files
immediately.
+
                } else if ("mask".equalsIgnoreCase(varKey)) {
+
                        results.append("this." + varKey + "=/" + 
ValidatorUtil.replace(varValue, "\\",
"\\\\") + "/; ");
+
                } else {
+
                        results.append("this." + varKey + "='" + 
ValidatorUtil.replace(varValue, "\\",
"\\\\") + "'; ");
+
                }
+
        }
+
        
+
        results.append(" return this[varName];\"))");
+
}
     /**
-     * The value <code>null</code> will be returned at the end of the sequence.  
+     * The value <code>null</code> will be returned at the end of the sequence.
      * &nbsp;&nbsp;&nbsp; ex: "zz" will return <code>null</code>
-    */ 
-    private String getNextVar(String input) {
+    */
+    private static String getNextVar(String input) {
        if (input == null) {
           return "aa";
        }
@@ -528,7 +649,7 @@ public class JavascriptValidatorTag exte
     /**
      * Replaces a single character in a <code>String</code>
     */
-    private String replaceChar(String input, int pos, char c) {
+    private static String replaceChar(String input, int pos, char c) {
        if (pos == 0) {
           return c + input.substring(pos, input.length());
        } else if (pos == input.length()) {
@@ -537,6 +658,9 @@ public class JavascriptValidatorTag exte
           return input.substring(0, pos) + c + input.substring(pos,
input.length() - 1);
        }
     }
+
+

+

 
     
 }
Index: src/share/org/apache/struts/taglib/html/LocalStrings.properties
===================================================================
RCS file:
/home/cvspublic/jakarta-struts/src/share/org/apache/struts/taglib/html/LocalStrings.properties,v
retrieving revision 1.14
diff -u -3 -p -r1.14 LocalStrings.properties
--- src/share/org/apache/struts/taglib/html/LocalStrings.properties     23 Feb 2002 
07:10:30 -0000      1.14
+++ src/share/org/apache/struts/taglib/html/LocalStrings.properties     3 May 2002 
+17:12:41 -0000
@@ -23,7 +23,8 @@ imgTag.type=Object must be of type Map
 includeTag.include=Error including page {0}: {1}
 includeTag.lookup=Cannot find global forward named {0}
 indexed.noEnclosingIterate=indexed=\"true\" is only valid within an enclosing
iterate tag
-iterateTag.iterator=Cannot create iterator for {0}
+javascriptValidatorTag.iterator=Cannot create iterator for {0}
+javascriptValidatorTag.collection=No collection found
 linkTag.destination=You must specify exactly one of 'forward', 'href', or 'page'
 linkTag.forward=Cannot locate global forwarding for {0}
 linkTag.forwards=Cannot locate forwards mapping table

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

Reply via email to