You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shale.apache.org by Gary VanMatre <gv...@apache.org> on 2006/11/28 05:10:22 UTC

Re: svn commit: r479836 - in /shale/framework/trunk/shale-validator/src: main/java/org/apache/shale/validator/converter/ main/java/org/apache/shale/validator/util/ main/java/org/apache/shale/validator/validator/ main/resources/META-INF/ main/resources/org/

From: <cr...@apache.org>
To: <co...@shale.apache.org>
Sent: Monday, November 27, 2006 6:17 PM
Subject: svn commit: r479836 - in 
/shale/framework/trunk/shale-validator/src: 
main/java/org/apache/shale/validator/converter/ 
main/java/org/apache/shale/validator/util/ 
main/java/org/apache/shale/validator/validator/ main/resources/META-INF/ 
main/resources/org/...


> Author: craigmcc
> Date: Mon Nov 27 17:17:42 2006
> New Revision: 479836
>
> URL: http://svn.apache.org/viewvc?view=rev&rev=479836
> Log:
> Upon further review, the original strategy (for SHALE-340) of writing an
> individual Validator for each Commons Validator validator, but still going
> through the general purpose lookup mechanisms, is more work than needed.
> We know exactly what Commons Validator instance we want to use, so lets
> just use it directly.
>

The only issue I see with this solution is that you can not override 
validation messages.
Instead of creating one generic mechanism, you rewrite code specific for 
each validator.  In the
end you will end up with a bunch of wrapper code versus common code.


> At the same time, leverage the fact that Commons Validator validators can 
> do
> formatting as well to provide a JSF Converter that goes along with the
> validator.  Still only done Integer so far, and not dealt with the client
> side aspects yet ... that will come next.
>
> SHALE-342
>
> Added:
> 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/converter/
> 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/converter/AbstractConverter.java 
> (with props)
> 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/converter/IntegerConverter.java 
> (with props)
> 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/converter/package.html 
> (with props)
> 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/util/AbstractUtilities.java 
> (with props)
> 
> shale/framework/trunk/shale-validator/src/test/java/org/apache/shale/validator/converter/
> Modified:
> 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/validator/AbstractValidator.java
> 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/validator/IntegerValidator.java
> 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/validator/package.html
> 
> shale/framework/trunk/shale-validator/src/main/resources/META-INF/faces-config.xml
> 
> shale/framework/trunk/shale-validator/src/main/resources/org/apache/shale/validator/resources/Bundle.properties
> 
> shale/framework/trunk/shale-validator/src/test/java/org/apache/shale/validator/validator/IntegerValidatorTestCase.java
>
> Added: 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/converter/AbstractConverter.java
> URL: 
> http://svn.apache.org/viewvc/shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/converter/AbstractConverter.java?view=auto&rev=479836
> ==============================================================================
> ---  
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/converter/AbstractConverter.java 
> (added)
> +++ 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/converter/AbstractConverter.java 
> Mon Nov 27 17:17:42 2006
> @@ -0,0 +1,81 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements.  See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to you under the Apache License, Version 
> 2.0
> + * (the "License"); you may not use this file except in compliance with
> + * the License.  You may obtain a copy of the License at
> + *
> + *      http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
> implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +
> +package org.apache.shale.validator.converter;
> +
> +import javax.faces.component.UIComponent;
> +import javax.faces.context.FacesContext;
> +import javax.faces.convert.Converter;
> +import org.apache.shale.validator.util.AbstractUtilities;
> +
> +/**
> + * <p>Abstract base class for converters that use Apache Commons 
> Validator
> + * as their foundation.</p>
> + */
> +public abstract class AbstractConverter extends AbstractUtilities
> +  implements Converter {
> +
> +
> +    // ------------------------------------------------------------  
> Constructors
> +
> +
> +    // --------------------------------------------------------------  
> Properties
> +
> +
> +    // ------------------------------------------------------- Converter 
> Methods
> +
> +
> +    /**
> +     * <p>Convert the specified string value, associated with the 
> specified
> +     * <code>UIComponent</code>, into a corresponding model data 
> object.</p>
> +     *
> +     * @param context <code>FacesContext</code> for the current request
> +     * @param component <code>UIComponent</code> associated with the
> +     *  value to be converted
> +     * @param value String value to be converted
> +     *
> +     * @exception ConverterException if conversion cannot be successfully
> +     *  performed
> +     * @exception NullPointerException if <code>context</code> or
> +     *  <code>component</code> is <code>null</code>
> +     */
> +    public abstract Object getAsObject(FacesContext context, UIComponent 
> component,
> +                                       String value);
> +
> +
> +    /**
> +     * <p>Convert the specified model data object, associated with the
> +     * specified <code>UIComponent</code>, into a string suitable for 
> rendering.</p>
> +     *
> +     * @param context <code>FacesContext</code> for the current request
> +     * @param component <code>UIComponent</code> associated with the
> +     *  model data object to be converted
> +     * @param value Model data object to be converted
> +     *
> +     * @exception ConverterException if conversion cannot be successfully
> +     *  performed
> +     * @exception NullPointerException if <code>context</code> or
> +     *  <code>component</code> is <code>null</code>
> +     */
> +    public abstract String getAsString(FacesContext context, UIComponent 
> component,
> +                                       Object value);
> +
> +
> +    // ------------------------------------------------------- Protected 
> Methods
> +
> +
> +}
>
> Propchange: 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/converter/AbstractConverter.java
> ------------------------------------------------------------------------------
>    svn:eol-style = native
>
> Propchange: 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/converter/AbstractConverter.java
> ------------------------------------------------------------------------------
>    svn:keywords = Date Author Id Revision HeadURL
>
> Added: 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/converter/IntegerConverter.java
> URL: 
> http://svn.apache.org/viewvc/shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/converter/IntegerConverter.java?view=auto&rev=479836
> ==============================================================================
> ---  
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/converter/IntegerConverter.java 
> (added)
> +++ 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/converter/IntegerConverter.java 
> Mon Nov 27 17:17:42 2006
> @@ -0,0 +1,169 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements.  See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to you under the Apache License, Version 
> 2.0
> + * (the "License"); you may not use this file except in compliance with
> + * the License.  You may obtain a copy of the License at
> + *
> + *      http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
> implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +
> +package org.apache.shale.validator.converter;
> +
> +import java.util.Locale;
> +import javax.faces.component.UIComponent;
> +import javax.faces.context.FacesContext;
> +import javax.faces.convert.ConverterException;
> +import org.apache.commons.validator.routines.IntegerValidator;
> +
> +/**
> + * <p>JavaServer Faces <code>Converter</code> for Integer (and int)
> + * instances.  Parsing and formatting is controlled by the properties
> + * that are set on a Converter instance.</p>
> + */
> +public final class IntegerConverter extends AbstractConverter {
> +
> +
> +    // -------------------------------------------------------- Static 
> Variables
> +
> +
> +    /**
> +     * <p>The Apache Commons Validator instance we will use to perform
> +     * our formatting and parsing.</p>
> +     */
> +    private static final IntegerValidator INSTANCE =
> +            IntegerValidator.getInstance();
> +
> +
> +
> +    // --------------------------------------------------------------  
> Properties
> +
> +
> +    /**
> +     * <p>The <code>Locale</code> to apply to this conversion, if 
> any.</p>
> +     */
> +    private Locale locale = null;
> +
> +
> +    /**
> +     * <p>Return the <code>Locale</code> to apply to this conversion, or
> +     * <code>null</code> to use the <code>Locale</code> for the current 
> view.</p>
> +     */
> +    public Locale getLocale() {
> +        return this.locale;
> +    }
> +
> +
> +    /**
> +     * <p>Set the <code>Locale</code> to apply to this conversion, or
> +     * <code>null</code> to use the <code>Locale</code> for the current 
> view.</p>
> +     *
> +     * @param locale The new Locale
> +     */
> +    public void setLocale(Locale locale) {
> +        this.locale = locale;
> +    }
> +
> +
> +    /**
> +     * <p>The formatting pattern to apply to this conversion, if any.</p>
> +     */
> +    private String pattern = null;
> +
> +
> +    /**
> +     * <p>Return the <code>java.text.NumberFormat</code> pattern to apply
> +     * to this conversion, or <code>null</code> for using no pattern.</p>
> +     */
> +    public String getPattern() {
> +        return this.pattern;
> +    }
> +
> +
> +    /**
> +     * <p>Set the <code>java.text.NumberFormat</code> pattern to apply to
> +     * this conversion, or <code>null</code> for using no pattern.</p>
> +     *
> +     * @param pattern The new formatting pattern
> +     */
> +    public void setPattern(String pattern) {
> +        this.pattern = null;
> +    }
> +
> +
> +    // ------------------------------------------------------- Converter 
> Methods
> +
> +
> +    /** {@inheritDoc} */
> +    public Object getAsObject(FacesContext context, UIComponent 
> component,
> +                              String value) {
> +
> +        if ((context == null) || (component == null)) {
> +            throw new NullPointerException(message(context, 
> "common.null"));
> +        }
> +
> +        try {
> +            if (locale == null) {
> +                return INSTANCE.validate(value, pattern, 
> context.getViewRoot().getLocale());
> +            } else {
> +                return INSTANCE.validate(value, pattern, locale);
> +            }
> +        } catch (Exception e) {
> +            throw new ConverterException(e);
> +        }
> +
> +    }
> +
> +
> +    /** {@inheritDoc} */
> +    public String getAsString(FacesContext context, UIComponent 
> component,
> +                              Object value) {
> +
> +        if ((context == null) || (component == null)) {
> +            throw new NullPointerException(message(context, 
> "common.null"));
> +        }
> +
> +        try {
> +            if (locale == null) {
> +                return INSTANCE.format(value, pattern, 
> context.getViewRoot().getLocale());
> +            } else {
> +                return INSTANCE.format(value, pattern, locale);
> +            }
> +        } catch (Exception e) {
> +            throw new ConverterException(e);
> +        }
> +
> +    }
> +
> +
> +
> +    // ----------------------------------------------------- StateHolder 
> Methods
> +
> +
> +    /** {@inheritDoc} */
> +    public void restoreState(FacesContext context, Object state) {
> +        Object[] values = (Object[]) state;
> +        super.restoreState(context, values[0]);
> +        this.locale = (Locale) values[1];
> +        this.pattern = (String) values[2];
> +    }
> +
> +
> +    /** {@inheritDoc} */
> +    public Object saveState(FacesContext context) {
> +        Object[] values = new Object[3];
> +        values[0] = super.saveState(context);
> +        values[1] = this.locale;
> +        values[2] = this.pattern;
> +        return values;
> +    }
> +
> +
> +}
>
> Propchange: 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/converter/IntegerConverter.java
> ------------------------------------------------------------------------------
>    svn:eol-style = native
>
> Propchange: 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/converter/IntegerConverter.java
> ------------------------------------------------------------------------------
>    svn:keywords = Date Author Id Revision HeadURL
>
> Added: 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/converter/package.html
> URL: 
> http://svn.apache.org/viewvc/shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/converter/package.html?view=auto&rev=479836
> ==============================================================================
> ---  
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/converter/package.html 
> (added)
> +++ 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/converter/package.html 
> Mon Nov 27 17:17:42 2006
> @@ -0,0 +1,28 @@
> +<!--
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements.  See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to you under the Apache License, Version 
> 2.0
> + * (the "License"); you may not use this file except in compliance with
> + * the License.  You may obtain a copy of the License at
> + *
> + *      http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
> implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> +-->
> +
> +<!-- $Id$ -->
> +
> +<body>
> +
> +<p>This package contains a set of JSF converters that use
> +the Apache Commons Validator API to perform both feature rich
> +parsing and formatting of internal objects.  They work in
> +conjunction with a corresponding set of validators to support
> +client- and server-side validation as well.</p>
> +
> +</body>
>
> Propchange: 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/converter/package.html
> ------------------------------------------------------------------------------
>    svn:eol-style = native
>
> Propchange: 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/converter/package.html
> ------------------------------------------------------------------------------
>    svn:keywords = Date Author Id Revision HeadURL
>
> Added: 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/util/AbstractUtilities.java
> URL: 
> http://svn.apache.org/viewvc/shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/util/AbstractUtilities.java?view=auto&rev=479836
> ==============================================================================
> ---  
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/util/AbstractUtilities.java 
> (added)
> +++ 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/util/AbstractUtilities.java 
> Mon Nov 27 17:17:42 2006
> @@ -0,0 +1,215 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements.  See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to you under the Apache License, Version 
> 2.0
> + * (the "License"); you may not use this file except in compliance with
> + * the License.  You may obtain a copy of the License at
> + *
> + *      http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
> implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +
> +package org.apache.shale.validator.util;
> +
> +import java.text.MessageFormat;
> +import java.util.Locale;
> +import java.util.MissingResourceException;
> +import java.util.ResourceBundle;
> +import javax.faces.component.StateHolder;
> +import javax.faces.context.FacesContext;
> +
> +/**
> + * <p>Abstract base class for converters and validators that use Apache 
> Commons
> + * Validator as their foundation.  This class provides common utility 
> methods
> + * for concrete converter and validator implementations.</p>
> + */
> +public abstract class AbstractUtilities implements StateHolder {
> +
> +
> +    // ------------------------------------------------------------  
> Constructors
> +
> +
> +    // ------------------------------------------------------ Manifest 
> Constants
> +
> +
> +    /**
> +     * <p>Name of the resource bundle containing default message 
> strings.</p>
> +     */
> +    static final String DEFAULT_RESOURCE_BUNDLE =
> +            "org.apache.shale.validator.resources.Bundle";
> +
> +
> +    // --------------------------------------------------------------  
> Properties
> +
> +
> +    /**
> +     * <p>Custom error message template, if any.</p>
> +     */
> +    private String message = null;
> +
> +
> +    /**
> +     * <p>Return the custom error message template for this converter or
> +     * validator, if any.  If not defined, a standard error message 
> template
> +     * will be used instead.</p>
> +     */
> +    public String getMessage() {
> +        return this.message;
> +    }
> +
> +
> +    /**
> +     * <p>Set the custom error message template for this validator.</p>
> +     *
> +     * @param message The new custom error message template, or 
> <code>null</code>
> +     *  to select the standard template
> +     */
> +    public void setMessage(String message) {
> +        this.message = message;
> +    }
> +
> +
> +    // ----------------------------------------------------- StateHolder 
> Methods
> +
> +
> +    /** {@inheritDoc} */
> +    public void restoreState(FacesContext context, Object state) {
> +        Object[] values = (Object[]) state;
> +        this.message = (String) values[0];
> +    }
> +
> +
> +    /** {@inheritDoc} */
> +    public Object saveState(FacesContext context) {
> +        Object[] values = new Object[1];
> +        values[1] = this.message;
> +        return values;
> +    }
> +
> +
> +    private boolean transientValue = false;
> +
> +
> +    /** {@inheritDoc} */
> +    public boolean isTransient() {
> +        return this.transientValue;
> +    }
> +
> +
> +    /** {@inheritDoc} */
> +    public void setTransient(boolean transientValue) {
> +        this.transientValue = transientValue;
> +    }
> +
> +
> +    // ---------------------------------------------------------- Object 
> Methods
> +
> +
> +    // ------------------------------------------------------- Protected 
> Methods
> +
> +
> +    /**
> +     * <p>Return a locale-sensitive message for this converter or
> +     * validator.  The following algorithm is applied to select the
> +     * appropriate message:</p>
> +     * <ul>
> +     * <li>If the <code>message</code> property has been set, use
> +     *     that value explicitly</li>
> +     * <li>If the application specifies a message resource bundle,
> +     *     and this resource bundle includes a value for the specified
> +     *     key, use that value</li>
> +     * <li>If the default message resource bundle for this module
> +     *     includes a value for the specified key, use that value</li>
> +     * <li>Create and return a dummy value</li>
> +     * </ul>
> +     *
> +     * @param context <code>FaceContext</code> for the current request
> +     * @param key Message key for the requested message
> +     */
> +    protected String message(FacesContext context, String key) {
> +
> +        // Return any explicitly specified message
> +        String message = getMessage();
> +        if (message != null) {
> +            return message;
> +        }
> +
> +        // Set up variables we will need
> +        ResourceBundle bundle = null;
> +        Locale locale = context.getViewRoot().getLocale();
> +        ClassLoader loader = 
> Thread.currentThread().getContextClassLoader();
> +
> +        // Search for a match in the application resource bundle (if any)
> +        String name = context.getApplication().getMessageBundle();
> +        if (name != null) {
> +            bundle = ResourceBundle.getBundle(name, locale, loader);
> +            if (bundle != null) {
> +                try {
> +                    message = bundle.getString(key);
> +                } catch (MissingResourceException e) {
> +                    message = null;
> +                }
> +                if (message != null) {
> +                    return message;
> +                }
> +            }
> +        }
> +
> +        // Otherwise, search the default resource bundle
> +        bundle = ResourceBundle.getBundle(DEFAULT_RESOURCE_BUNDLE, 
> locale, loader);
> +        try {
> +            return bundle.getString(key);
> +        } catch (MissingResourceException e) {
> +            return "???" + key + "???";
> +        }
> +
> +    }
> +
> +
> +    /**
> +     * <p>Retrieve a locale-specific message for the specified key, then
> +     * treat it as a message format pattern, and substitute in the 
> specified
> +     * parameter values and return the resulting string.</p>
> +     *
> +     * @param context <code>FaceContext</code> for the current request
> +     * @param key Message key for the requested message
> +     * @param parameters Replacement parameters to substitute in to
> +     *  the retrieved message
> +     */
> +    protected String message(FacesContext context, String key,
> +                             Object[] parameters) {
> +
> +        String message = message(context, key);
> +        if ((parameters == null) || (parameters.length < 1)) {
> +            return message;
> +        }
> +        return message(context.getViewRoot().getLocale(), message, 
> parameters);
> +
> +    }
> +
> +
> +    /**
> +     * <p>Use the specified message as a message format pattern, 
> substitute
> +     * in the specified parameter values, and return the resulting 
> string.</p>
> +     *
> +     * @param locale Locale for performing parameter replacement
> +     * @param message Message format pattern string
> +     * @param parameters Replacement parameters to substitute in to
> +     *  the message format pattern
> +     */
> +    protected String message(Locale locale, String message, Object[] 
> parameters) {
> +
> +        MessageFormat format =
> +          new MessageFormat(message, locale);
> +        return format.format(parameters);
> +
> +    }
> +
> +
> +}
>
> Propchange: 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/util/AbstractUtilities.java
> ------------------------------------------------------------------------------
>    svn:eol-style = native
>
> Propchange: 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/util/AbstractUtilities.java
> ------------------------------------------------------------------------------
>    svn:keywords = Date Author Id Revision HeadURL
>
> Modified: 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/validator/AbstractValidator.java
> URL: 
> http://svn.apache.org/viewvc/shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/validator/AbstractValidator.java?view=diff&rev=479836&r1=479835&r2=479836
> ==============================================================================
> ---  
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/validator/AbstractValidator.java 
> (original)
> +++ 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/validator/AbstractValidator.java 
> Mon Nov 27 17:17:42 2006
> @@ -34,13 +34,15 @@
> import org.apache.commons.validator.ValidatorResources;
> import org.apache.shale.util.ConverterHelper;
> import org.apache.shale.validator.Globals;
> +import org.apache.shale.validator.util.AbstractUtilities;
> import org.apache.shale.validator.util.ShaleValidatorAction;
>
> /**
>  * <p>Abstract base class for validators that use Apache Commons Validator
>  * as their foundation.</p>
>  */
> -public abstract class AbstractValidator implements Validator, StateHolder 
> {
> +public abstract class AbstractValidator extends AbstractUtilities
> +  implements Validator {
>
>
>     // ------------------------------------------------------------  
> Constructors
> @@ -127,30 +129,6 @@
>     }
>
>
> -    private String message = null;
> -
> -
> -    /**
> -     * <p>Return the custom error message template for this validator, if 
> any.
> -     * If not defined, a standard error message template (based on which
> -     * validator type is selected) will be used instead.</p>
> -     */
> -    public String getMessage() {
> -        return this.message;
> -    }
> -
> -
> -    /**
> -     * <p>Set the custom error message template for this validator.</p>
> -     *
> -     * @param message The new custom error message template, or 
> <code>null</code>
> -     *  to select the standard template
> -     */
> -    public void setMessage(String message) {
> -        this.message = message;
> -    }
> -
> -
>     // ------------------------------------------------------- Validator 
> Methods
>
>
> @@ -184,35 +162,20 @@
>     /** {@inheritDoc} */
>     public void restoreState(FacesContext context, Object state) {
>         Object[] values = (Object[]) state;
> -        this.client = Boolean.TRUE.equals((Boolean) values[0]);
> -        this.message = (String) values[1];
> +        super.restoreState(context, values[0]);
> +        this.client = Boolean.TRUE.equals((Boolean) values[1]);
>     }
>
>
>     /** {@inheritDoc} */
>     public Object saveState(FacesContext context) {
>         Object[] values = new Object[2];
> -        values[0] = this.client ? Boolean.TRUE : Boolean.FALSE;
> -        values[1] = this.message;
> +        values[0] = super.saveState(context);
> +        values[1] = this.client ? Boolean.TRUE : Boolean.FALSE;
>         return values;
>     }
>
>
> -    private boolean transientValue = false;
> -
> -
> -    /** {@inheritDoc} */
> -    public boolean isTransient() {
> -        return this.transientValue;
> -    }
> -
> -
> -    /** {@inheritDoc} */
> -    public void setTransient(boolean transientValue) {
> -        this.transientValue = transientValue;
> -    }
> -
> -
>     // ---------------------------------------------------------- Object 
> Methods
>
>
> @@ -276,52 +239,6 @@
>         // Fall back to converting to String, then to the requested type
>         String string = helper.asString(context, value.getClass(), value);
>         return helper.asObject(context, type, string);
> -
> -    }
> -
> -
> -    /**
> -     * <p>Return the locale-sensitive error message template for this
> -     * validator.  The application specified resource bundle (if any)
> -     * is searched first, followed by the default resource bundle.</p>
> -     *
> -     * @param context <code>FaceContext</code> for the current request
> -     * @param key Message key for the requested template
> -     */
> -    protected String message(FacesContext context, String key) {
> -
> -        // Set up variables we will need
> -        ResourceBundle bundle = null;
> -        Locale locale = context.getViewRoot().getLocale();
> -        ClassLoader loader = 
> Thread.currentThread().getContextClassLoader();
> -        if (loader == null) {
> -            loader = this.getClass().getClassLoader();
> -        }
> -        String message = null;
> -
> -        // Search for a match in the application resource bundle (if any)
> -        String name = context.getApplication().getMessageBundle();
> -        if (name != null) {
> -            bundle = ResourceBundle.getBundle(name, locale, loader);
> -            if (bundle != null) {
> -                try {
> -                    message = bundle.getString(key);
> -                } catch (MissingResourceException e) {
> -                    message = null;
> -                }
> -                if (message != null) {
> -                    return message;
> -                }
> -            }
> -        }
> -
> -        // Otherwise, search the default resource bundle
> -        bundle = ResourceBundle.getBundle(DEFAULT_RESOURCE_BUNDLE, 
> locale, loader);
> -        try {
> -            return bundle.getString(key);
> -        } catch (MissingResourceException e) {
> -            return "???" + key + "???";
> -        }
>
>     }
>
>
> Modified: 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/validator/IntegerValidator.java
> URL: 
> http://svn.apache.org/viewvc/shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/validator/IntegerValidator.java?view=diff&rev=479836&r1=479835&r2=479836
> ==============================================================================
> ---  
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/validator/IntegerValidator.java 
> (original)
> +++ 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/validator/IntegerValidator.java 
> Mon Nov 27 17:17:42 2006
> @@ -17,9 +17,8 @@
>
> package org.apache.shale.validator.validator;
>
> -import java.util.HashMap;
> -import java.util.Map;
> -import javax.faces.component.EditableValueHolder;
> +import javax.faces.application.FacesMessage;
> +import javax.faces.component.StateHolder;
> import javax.faces.component.UIComponent;
> import javax.faces.context.FacesContext;
> import javax.faces.validator.ValidatorException;
> @@ -28,7 +27,19 @@
>  * <p><code>Validator</code> implementation that will perform both format
>  * and (optional) range checks on an integer value.</p>
>  */
> -public final class IntegerValidator extends AbstractValidator {
> +public final class IntegerValidator extends AbstractValidator
> +  implements StateHolder {
> +
> +
> +    // -------------------------------------------------------- Static 
> Variables
> +
> +
> +    /**
> +     * <p>The Apache Commons Validator instance we will be using.</p>
> +     */
> +    private static final
> +      org.apache.commons.validator.routines.IntegerValidator INSTANCE =
> + 
> org.apache.commons.validator.routines.IntegerValidator.getInstance();
>
>
>     // --------------------------------------------------------------  
> Properties
> @@ -88,28 +99,56 @@
>                          UIComponent  component,
>                          Object       value) throws ValidatorException {
>
> -        // Build a map of variables passed in to Commons Validator
> -        Map vars = new HashMap();
> -        vars.put(ARG_VALUE, // FIXME - consider using 
> component.getLabel() in JSF 1.2
> -                 ((EditableValueHolder) component).getSubmittedValue());
> -        if (maximumSet) {
> -            vars.put(MAXIMUM_VALUE, new Integer(maximum));
> -        } else {
> -            vars.put(MAXIMUM_VALUE, new Integer(Integer.MAX_VALUE));
> +        // Validate our parameters
> +        if ((context == null) || (component == null)) {
> +            throw new NullPointerException(message(context, 
> "common.null"));
>         }
> -        if (minimumSet) {
> -            vars.put(MINIMUM_VALUE, new Integer(minimum));
> -        } else {
> -            vars.put(MINIMUM_VALUE, new Integer(Integer.MIN_VALUE));
> +        if (value == null) {
> +            return;
>         }
> -        vars.put(SUBMITTED_VALUE,
> -                 ((EditableValueHolder) component).getSubmittedValue());
>
> -        // Invoke the appropriate Commons Validator type
> -        if (maximumSet || minimumSet) {
> -            super.validate(context, component, value, "intRange", vars);
> -        } else {
> -            super.validate(context, component, value, "integer", vars);
> +        // Conversion is expected to have occurred already, via an
> +        // explicit or implicit Converter having been applied.
> +        // Throw a validation error if this is not the case
> +        if (!(value instanceof Integer)) {
> +            throw new ValidatorException
> +              (new FacesMessage(FacesMessage.SEVERITY_ERROR,
> +                                message(context, "Integer.unconverted"),
> +                                null));
> +        }
> +
> +        // Perform the requested range checks (if any)
> +        Integer ivalue = (Integer) value;
> +        if (minimumSet) {
> +            if (maximumSet) {
> +                if (!INSTANCE.isInRange(ivalue, minimum, maximum)) {
> +                    throw new ValidatorException
> +                      (new FacesMessage(FacesMessage.SEVERITY_ERROR,
> +                                        message(context, "Common.range",
> +                                                new Object[] { ivalue,
> +                                                               new 
> Integer(minimum),
> +                                                               new 
> Integer(maximum) }),
> +                                        null));
> +                }
> +            } else {
> +                if (!INSTANCE.minValue(ivalue, minimum)) {
> +                    throw new ValidatorException
> +                      (new FacesMessage(FacesMessage.SEVERITY_ERROR,
> +                                        message(context, 
> "Common.minimum",
> +                                                new Object[] { ivalue,
> +                                                               new 
> Integer(minimum) }),
> +                                        null));
> +                }
> +            }
> +        } else if (maximumSet) {
> +            if (!INSTANCE.maxValue(ivalue, maximum)) {
> +                throw new ValidatorException
> +                  (new FacesMessage(FacesMessage.SEVERITY_ERROR,
> +                                    message(context, "Common.maximum",
> +                                            new Object[] { ivalue,
> +                                                           new 
> Integer(maximum) }),
> +                                    null));
> +            }
>         }
>
>     }
>
> Modified: 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/validator/package.html
> URL: 
> http://svn.apache.org/viewvc/shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/validator/package.html?view=diff&rev=479836&r1=479835&r2=479836
> ==============================================================================
> ---  
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/validator/package.html 
> (original)
> +++ 
> shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/validator/package.html 
> Mon Nov 27 17:17:42 2006
> @@ -21,6 +21,8 @@
>
> <p>This package contains a set of JSF validators that use
> the Apache Commons Validator API to perform both
> -client- and server-side validation.</p>
> +client- and server-side validation.  They work in conjunction
> +with a corresponding set of converters to provide feature-rich
> +formatting and parsing support as well.</p>
>
> </body>
>
> Modified: 
> shale/framework/trunk/shale-validator/src/main/resources/META-INF/faces-config.xml
> URL: 
> http://svn.apache.org/viewvc/shale/framework/trunk/shale-validator/src/main/resources/META-INF/faces-config.xml?view=diff&rev=479836&r1=479835&r2=479836
> ==============================================================================
> ---  
> shale/framework/trunk/shale-validator/src/main/resources/META-INF/faces-config.xml 
> (original)
> +++ 
> shale/framework/trunk/shale-validator/src/main/resources/META-INF/faces-config.xml 
> Mon Nov 27 17:17:42 2006
> @@ -57,4 +57,26 @@
> 
> <validator-class>org.apache.shale.validator.CommonsValidator</validator-class>
>   </validator>
>
> +
> +  <!-- ========== Custom Converters ========== -->
> +
> +  <converter>
> +      <converter-id>org.apache.shale.converter.Integer</converter-id>
> +      <converter-class>
> +          org.apache.shale.validator.converter.IntegerConverter
> +      </converter-class>
> +  </converter>
> +
> +
> +  <!-- ========== Custom Validators ========== -->
> +
> +
> +  <validator>
> +      <validator-id>org.apache.shale.validator.Integer</validator-id>
> +      <validator-class>
> +          org.apache.shale.validator.validator.IntegerValidator
> +      </validator-class>
> +  </validator>
> +
> +
> </faces-config>
>
> Modified: 
> shale/framework/trunk/shale-validator/src/main/resources/org/apache/shale/validator/resources/Bundle.properties
> URL: 
> http://svn.apache.org/viewvc/shale/framework/trunk/shale-validator/src/main/resources/org/apache/shale/validator/resources/Bundle.properties?view=diff&rev=479836&r1=479835&r2=479836
> ==============================================================================
> ---  
> shale/framework/trunk/shale-validator/src/main/resources/org/apache/shale/validator/resources/Bundle.properties 
> (original)
> +++ 
> shale/framework/trunk/shale-validator/src/main/resources/org/apache/shale/validator/resources/Bundle.properties 
> Mon Nov 27 17:17:42 2006
> @@ -17,6 +17,21 @@
> #
> # $Id$
>
> +# Common messages
> +Common.maximum={0} exceeds the allowed maximum value of {1}
> +Common.minimum={0} does not equal or exceed the allowed minimum value of 
> {1}
> +Common.null=A required input parameter was null
> +Common.range={0} is not in the required range of {1} through {2}
> +
> +# Integer Converter/Valdiator messages
> +Integer.unconverted=Cannot validate a value that has not been conveted to 
> Integer
> +
> +
> +
> +
> +
> +
> +
> # Validator Support error messages
> commonsValidator.intException=Error initializing commons validator for 
> rule type "{0}" on component id "{1}".
> commonsValidator.loadresource=Loading validation rules file from {0}
>
> Modified: 
> shale/framework/trunk/shale-validator/src/test/java/org/apache/shale/validator/validator/IntegerValidatorTestCase.java
> URL: 
> http://svn.apache.org/viewvc/shale/framework/trunk/shale-validator/src/test/java/org/apache/shale/validator/validator/IntegerValidatorTestCase.java?view=diff&rev=479836&r1=479835&r2=479836
> ==============================================================================
> ---  
> shale/framework/trunk/shale-validator/src/test/java/org/apache/shale/validator/validator/IntegerValidatorTestCase.java 
> (original)
> +++ 
> shale/framework/trunk/shale-validator/src/test/java/org/apache/shale/validator/validator/IntegerValidatorTestCase.java 
> Mon Nov 27 17:17:42 2006
> @@ -137,42 +137,14 @@
>         // NOTE - null and zero-length string are irrelevant inputs, 
> because
>         // JSF will not call validators in that scenario
>
> -        input.setSubmittedValue("a");
>         try {
> -            validator.validate(facesContext, input, null);
> +            validator.validate(facesContext, input, "abc");
>             fail("Should have thrown ValidatorException");
>         } catch (ValidatorException e) {
>             ; // Expected result
> //            System.err.println("a: " + 
> e.getFacesMessage().getSummary());
>         }
>
> -        input.setSubmittedValue("b123");
> -        try {
> -            validator.validate(facesContext, input, null);
> -            fail("Should have thrown ValidatorException");
> -        } catch (ValidatorException e) {
> -            ; // Expected result
> -//            System.err.println("b123: " + 
> e.getFacesMessage().getSummary());
> -        }
> -
> -        input.setSubmittedValue("456c");
> -        try {
> -            validator.validate(facesContext, input, null);
> -            fail("Should have thrown ValidatorException");
> -        } catch (ValidatorException e) {
> -            ; // Expected result
> -//            System.err.println("456c: " + 
> e.getFacesMessage().getSummary());
> -        }
> -
> -        input.setSubmittedValue(" 789 ");
> -        try {
> -            validator.validate(facesContext, input, null);
> -            fail("Should have thrown ValidatorException");
> -        } catch (ValidatorException e) {
> -            ; // Expected result
> -//            System.err.println(" 789 : " + 
> e.getFacesMessage().getSummary());
> -        }
> -
>     }
>
>
> @@ -182,10 +154,9 @@
>      */
>     public void testInvalidMaximum() {
>
> -        input.setSubmittedValue("234");
>         validator.setMaximum(123);
>         try {
> -            validator.validate(facesContext, input, null);
> +            validator.validate(facesContext, input, new Integer(234));
>             fail("Should have thrown ValidatorException");
>         } catch (ValidatorException e) {
>             ; // Expected result
> @@ -201,10 +172,9 @@
>      */
>     public void testInvalidMinimum() {
>
> -        input.setSubmittedValue("123");
>         validator.setMinimum(234);
>         try {
> -            validator.validate(facesContext, input, null);
> +            validator.validate(facesContext, input, new Integer(123));
>             fail("Should have thrown ValidatorException");
>         } catch (ValidatorException e) {
>             ; // Expected result
> @@ -220,33 +190,20 @@
>      */
>     public void testInvalidRange() {
>
> -        input.setSubmittedValue("a");
> -        validator.setMinimum(0);
> -        validator.setMaximum(234);
> -        try {
> -            validator.validate(facesContext, input, null);
> -            fail("Should have thrown ValidatorException");
> -        } catch (ValidatorException e) {
> -            ; // Expected result
> -//            System.err.println("a: " + 
> e.getFacesMessage().getSummary());
> -        }
> -
> -        input.setSubmittedValue("-1");
>         validator.setMinimum(0);
>         validator.setMaximum(234);
>         try {
> -            validator.validate(facesContext, input, null);
> +            validator.validate(facesContext, input, new Integer(-1));
>             fail("Should have thrown ValidatorException");
>         } catch (ValidatorException e) {
>             ; // Expected result
> //            System.err.println("-1: " + 
> e.getFacesMessage().getSummary());
>         }
>
> -        input.setSubmittedValue("235");
>         validator.setMinimum(0);
>         validator.setMaximum(234);
>         try {
> -            validator.validate(facesContext, input, null);
> +            validator.validate(facesContext, input, new Integer(235));
>             fail("Should have thrown ValidatorException");
>         } catch (ValidatorException e) {
>             ; // Expected result
> @@ -264,25 +221,22 @@
>         // NOTE - null and zero-length string are irrelevant inputs, 
> because
>         // JSF will not call validators in that scenario
>
> -        input.setSubmittedValue("0");
>         try {
> -            validator.validate(facesContext, input, null);
> +            validator.validate(facesContext, input, new Integer(0));
>         } catch (ValidatorException e) {
>             fail("Should not have thrown ValidatorException: " +
>                     e.getFacesMessage().getSummary());
>         }
>
> -        input.setSubmittedValue("123");
>         try {
> -            validator.validate(facesContext, input, null);
> +            validator.validate(facesContext, input, new Integer(123));
>         } catch (ValidatorException e) {
>             fail("Should not have thrown ValidatorException: " +
>                     e.getFacesMessage().getSummary());
>         }
>
> -        input.setSubmittedValue("-456");
>         try {
> -            validator.validate(facesContext, input, null);
> +            validator.validate(facesContext, input, new Integer(-456));
>         } catch (ValidatorException e) {
>             fail("Should not have thrown ValidatorException: " +
>                     e.getFacesMessage().getSummary());
> @@ -297,19 +251,17 @@
>      */
>     public void testValidMaximum() {
>
> -        input.setSubmittedValue("123");
>         validator.setMaximum(234);
>         try {
> -            validator.validate(facesContext, input, null);
> +            validator.validate(facesContext, input, new Integer(123));
>         } catch (ValidatorException e) {
>             fail("Should not have thrown ValidatorException: " +
>                     e.getFacesMessage().getSummary());
>         }
>
> -        input.setSubmittedValue("234");
>         validator.setMaximum(234);
>         try {
> -            validator.validate(facesContext, input, null);
> +            validator.validate(facesContext, input, new Integer(234));
>         } catch (ValidatorException e) {
>             fail("Should not have thrown ValidatorException: " +
>                     e.getFacesMessage().getSummary());
> @@ -324,19 +276,17 @@
>      */
>     public void testValidMinimum() {
>
> -        input.setSubmittedValue("0");
>         validator.setMinimum(0);
>         try {
> -            validator.validate(facesContext, input, null);
> +            validator.validate(facesContext, input, new Integer(0));
>         } catch (ValidatorException e) {
>             fail("Should not have thrown ValidatorException: " +
>                     e.getFacesMessage().getSummary());
>         }
>
> -        input.setSubmittedValue("123");
>         validator.setMinimum(0);
>         try {
> -            validator.validate(facesContext, input, null);
> +            validator.validate(facesContext, input, new Integer(123));
>         } catch (ValidatorException e) {
>             fail("Should not have thrown ValidatorException: " +
>                     e.getFacesMessage().getSummary());
> @@ -351,31 +301,28 @@
>      */
>     public void testValidRange() {
>
> -        input.setSubmittedValue("0");
>         validator.setMinimum(0);
>         validator.setMaximum(234);
>         try {
> -            validator.validate(facesContext, input, null);
> +            validator.validate(facesContext, input, new Integer(0));
>         } catch (ValidatorException e) {
>             fail("Should not have thrown ValidatorException: " +
>                     e.getFacesMessage().getSummary());
>         }
>
> -        input.setSubmittedValue("123");
>         validator.setMinimum(0);
>         validator.setMaximum(234);
>         try {
> -            validator.validate(facesContext, input, null);
> +            validator.validate(facesContext, input, new Integer(123));
>         } catch (ValidatorException e) {
>             fail("Should not have thrown ValidatorException: " +
>                     e.getFacesMessage().getSummary());
>         }
>
> -        input.setSubmittedValue("234");
>         validator.setMinimum(0);
>         validator.setMaximum(234);
>         try {
> -            validator.validate(facesContext, input, null);
> +            validator.validate(facesContext, input, new Integer(234));
>         } catch (ValidatorException e) {
>             fail("Should not have thrown ValidatorException: " +
>                     e.getFacesMessage().getSummary());
>
>
>