You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@struts.apache.org by "David Evans (JIRA)" <ji...@apache.org> on 2006/05/02 06:08:20 UTC
[jira] Closed: (STR-590) Indexed row validation patch
[ http://issues.apache.org/struts/browse/STR-590?page=all ]
David Evans closed STR-590:
---------------------------
Resolution: Fixed
> Indexed row validation patch
> ----------------------------
>
> Key: STR-590
> URL: http://issues.apache.org/struts/browse/STR-590
> Project: Struts Action 1
> Type: Improvement
> Components: Taglibs
> Versions: Nightly Build
> Environment: Operating System: All
> Platform: All
> Reporter: Jose Quinteiro
> Assignee: James Mitchell
> Priority: Minor
> Attachments: JspValidatorTag.patch
>
> My earlier patch did not generate field names properly. This one does.
> 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 -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 4 May 2002 00:07:31 -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.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 @@
>
>
> // ----------------------------------------------------------- Properties
> +
> /**
> + * The message resources for this package.
> + */
> + protected static MessageResources messages =
> +
> MessageResources.getMessageResources
> +
> ("org.apache.struts.taglib.html.LocalStrings");
>
>
> /**
> @@ -106,18 +117,18 @@
> 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 @@
> 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 @@
> }
>
> /**
> - * 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 @@
> }
>
> /**
> - * 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 @@
> }
>
> /**
> - * 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 @@
> }
>
> /**
> - * 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 @@
> }
>
> /**
> - * 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 @@
> 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 @@
> 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(); ) {
> @@ -336,7 +347,7 @@
>
> for (Iterator i = lActions.iterator(); i.hasNext(); ) {
> ValidatorAction va = (ValidatorAction)i.next();
> - String jscriptVar = null;
> +
> String jscriptVar = null;
> String functionName = null;
>
> if (va.getJsFunctionName() != null &&
> va.getJsFunctionName().length() > 0) {
> @@ -347,43 +358,47 @@
>
> 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");
> + jscriptVar = 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 +459,12 @@
>
> 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,14 +504,119 @@
> sb.append("</SCRIPT>\n\n");
>
> return sb.toString();
> - }
> + }
> +
> +
> /**
> +
> * Hopefully creates correct parameter names for indexed fields
> +
> */
> +
> protected String generateParameterNames( StringBuffer results, Field field,
> +
> String message, String jscriptVar )
> +
> throws JspException
> +
> {
> +
> String l_jscriptVar = jscriptVar;
> +
> 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(" this." );
> +
> results.append( l_jscriptVar = getNextVar(l_jscriptVar) );
> +
> 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() );
> +
> }
> +
> }
> +
> else {
> +
> results.append(" this." );
> +
> results.append( l_jscriptVar = getNextVar(l_jscriptVar) );
> +
> results.append( " = new Array(\"" );
> +
> generateParameterName( results, field, message, field.getKey() );
> +
> }
> +
> return l_jscriptVar;
> +
> }
> +
> /**
> +
> * 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];\"));\n");
> +
> }
> /**
> - * 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.
> * ex: "zz" will return <code>null</code>
> - */
> - private String getNextVar(String input) {
> + */
> + private static String getNextVar(String input) {
> if (input == null) {
> - return "aa";
> + return "aaa";
> }
>
> input = input.toLowerCase();
> @@ -528,7 +648,7 @@
> /**
> * 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 +657,9 @@
> 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 -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 4 May 2002 00:07:31 -0000
> @@ -23,7 +23,8 @@
> 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
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://issues.apache.org/struts/secure/Administrators.jspa
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira