2009/05/20 - Apache Shale has been retired.

For more information, please explore the Attic.

Coverage Report - org.apache.shale.validator.validator.AbstractValidator
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractValidator
100%
3/3
N/A
3.222
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to you under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  *
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 
 18  
 package org.apache.shale.validator.validator;
 19  
 
 20  
 import java.lang.reflect.InvocationTargetException;
 21  
 import java.lang.reflect.Method;
 22  
 import java.text.MessageFormat;
 23  
 import java.util.Locale;
 24  
 import java.util.Map;
 25  
 
 26  
 import javax.faces.application.FacesMessage;
 27  
 import javax.faces.component.UIComponent;
 28  
 import javax.faces.context.FacesContext;
 29  
 import javax.faces.validator.Validator;
 30  
 import javax.faces.validator.ValidatorException;
 31  
 
 32  
 import org.apache.commons.validator.Arg;
 33  
 import org.apache.commons.validator.ValidatorResources;
 34  
 import org.apache.shale.util.ConverterHelper;
 35  
 import org.apache.shale.validator.Globals;
 36  
 import org.apache.shale.validator.util.AbstractUtilities;
 37  
 import org.apache.shale.validator.util.ShaleValidatorAction;
 38  
 
 39  
 /**
 40  
  * <p>Abstract base class for validators that use Apache Commons Validator
 41  
  * as their foundation.</p>
 42  
  */
 43  40
 public abstract class AbstractValidator extends AbstractUtilities
 44  
   implements Validator {
 45  
     
 46  
 
 47  
     // ------------------------------------------------------------ Constructors
 48  
 
 49  
 
 50  
     // ------------------------------------------------------ Manifest Constants
 51  
 
 52  
 
 53  
     /**
 54  
      * <p>Variable name in a <code>vars</code> map representing the argument
 55  
      * that was being evaluated, and should be included in any error message.
 56  
      * Typically, this will be either the value itself or a user-friendly
 57  
      * (localized) field label.</p>
 58  
      */
 59  
     protected static final String ARG_VALUE =
 60  
             "arg";
 61  
 
 62  
 
 63  
     /**
 64  
      * <p>Variable name in a <code>vars</code> map representing the maximum
 65  
      * value that should be accepted by this <code>Validator</code>.</p>
 66  
      */
 67  
     protected static final String MAXIMUM_VALUE =
 68  
             "max";
 69  
 
 70  
 
 71  
     /**
 72  
      * <p>Variable name in a <code>vars</code> map representing the minimum
 73  
      * value that should be accepted by this <code>Validator</code>.</p>
 74  
      */
 75  
     protected static final String MINIMUM_VALUE =
 76  
             "min";
 77  
 
 78  
 
 79  
     /**
 80  
      * <p>Variable name in a <code>vars</code> map representing the submitted
 81  
      * value that should be validated by this <code>Validator</code>.</p>
 82  
      */
 83  
     protected static final String SUBMITTED_VALUE =
 84  
             "submittedValue";
 85  
 
 86  
 
 87  
     // -------------------------------------------------------- Static Variables
 88  
 
 89  
 
 90  
     /**
 91  
      * <p>Converter helper instance we can use in the <code>convert()</code>
 92  
      * method implementation.</p>
 93  
      */
 94  1
     protected static final ConverterHelper helper = new ConverterHelper();
 95  
 
 96  
 
 97  
 
 98  
     // -------------------------------------------------------------- Properties
 99  
 
 100  
 
 101  40
     private boolean client = true;
 102  
 
 103  
 
 104  
     /**
 105  
      * <p>Return a flag describing whether this validator should be enforced
 106  
      * on the client side or not.  Default is <code>true</code>.</p>
 107  
      */
 108  
     public boolean isClient() {
 109  
         return this.client;
 110  
     }
 111  
 
 112  
 
 113  
     /**
 114  
      * <p>Set a flag describing whether this validator should be enforced
 115  
      * on the client side or not.</p>
 116  
      *
 117  
      * @param client The new client enforcement flag
 118  
      */
 119  
     public void setClient(boolean client) {
 120  
         this.client = client;
 121  
     }
 122  
 
 123  
 
 124  
     // ------------------------------------------------------- Validator Methods
 125  
 
 126  
 
 127  
     /**
 128  
      * <p>Perform the correctness checks implemented by this
 129  
      * {@link Validator} against the specified {@link UIComponent}.
 130  
      * If any violations are found, a {@link ValidatorException}
 131  
      * will be thrown containing the {@link javax.faces.application.FacesMessage}
 132  
      * describing the failure.</p>
 133  
      *
 134  
      * <p><strong>IMPLEMENTATION NOTE</strong>:  Unlike earlier implementations
 135  
      * of Shale Validator integration, validators that subclass this class do
 136  
      * not support the option to skip server side validation.</p>
 137  
      *
 138  
      * @param context <code>FacesContext</code> for the current request
 139  
      * @param component <code>UIComponent</code> we are checking for correctness
 140  
      * @param value The value to validate
 141  
      *
 142  
      * @throws ValidatorException if validation fails
 143  
      * @throws NullPointerException if <code>context</code>
 144  
      *  or <code>component</code> is <code>null</code>
 145  
      */
 146  
     public abstract void validate(FacesContext context,
 147  
                                   UIComponent  component,
 148  
                                   Object       value) throws ValidatorException;
 149  
 
 150  
 
 151  
     // ----------------------------------------------------- StateHolder Methods
 152  
 
 153  
 
 154  
     /** {@inheritDoc} */
 155  
     public void restoreState(FacesContext context, Object state) {
 156  
         Object[] values = (Object[]) state;
 157  
         super.restoreState(context, values[0]);
 158  
         this.client = Boolean.TRUE.equals((Boolean) values[1]);
 159  
     }
 160  
 
 161  
 
 162  
     /** {@inheritDoc} */
 163  
     public Object saveState(FacesContext context) {
 164  
         Object[] values = new Object[2];
 165  
         values[0] = super.saveState(context);
 166  
         values[1] = this.client ? Boolean.TRUE : Boolean.FALSE;
 167  
         return values;
 168  
     }
 169  
 
 170  
 
 171  
     // ---------------------------------------------------------- Object Methods
 172  
 
 173  
 
 174  
     // ------------------------------------------------------- Protected Methods
 175  
 
 176  
 
 177  
     /**
 178  
      * <p>Return an array of <code>ShaleValidatorAction</code>s to execute
 179  
      * for a given validation, starting with the configured dependent
 180  
      * actions, and ending with the action corresponding to the specified
 181  
      * action type.  If there is no defined action with the specified
 182  
      * type, return <code>null</code>.</p>
 183  
      *
 184  
      * @param context <code>FacesContext</code> for the current request
 185  
      * @param type Type of the validator action for which to return actions
 186  
      */
 187  
     protected ShaleValidatorAction[] actions(FacesContext context, String type) {
 188  
 
 189  
         Map actions = (Map) context.getExternalContext().
 190  
           getApplicationMap().get(Globals.VALIDATOR_ACTIONS);
 191  
         return (ShaleValidatorAction[]) actions.get(type);
 192  
 
 193  
     }
 194  
 
 195  
 
 196  
     /**
 197  
      * <p>Use the registered converters to convert the specified value
 198  
      * to the specified type.</p>
 199  
      *
 200  
      * @param context <code>FacesContext</code> for the current request
 201  
      * @param value Value to be converted
 202  
      * @param type Type to which the value should be converted
 203  
      */
 204  
     protected Object convert(FacesContext context, Object value, Class type) {
 205  
 
 206  
         // Is the specified value null?  If so, return it unchanged
 207  
         if (value == null) {
 208  
             return null;
 209  
         }
 210  
 
 211  
         // Is the specified value of the correct type already?
 212  
         // If so, return it unchanged
 213  
         if (type.isInstance(value)) {
 214  
             return value;
 215  
         }
 216  
 
 217  
         // Is the target type String?  If so, use the asString() conversion
 218  
         if (type == String.class) {
 219  
             if (value instanceof String) {
 220  
                 return value;
 221  
             } else {
 222  
                 return helper.asString(context, value.getClass(), value);
 223  
             }
 224  
         }
 225  
 
 226  
         // Is the source type String?  If so, use the asObject() conversion
 227  
         if (value instanceof String) {
 228  
             return helper.asObject(context, type, (String) value);
 229  
         }
 230  
 
 231  
         // Fall back to converting to String, then to the requested type
 232  
         String string = helper.asString(context, value.getClass(), value);
 233  
         return helper.asObject(context, type, string);
 234  
 
 235  
     }
 236  
 
 237  
 
 238  
     /**
 239  
      * <p>Return the <code>ValidatorResources</code> that describe the
 240  
      * validation rules to be enforced by this application.</p>
 241  
      *
 242  
      * @param context <code>FacesContext</code> for the current request
 243  
      */
 244  
     protected ValidatorResources resources(FacesContext context) {
 245  
 
 246  
         return (ValidatorResources) context.getExternalContext().
 247  
           getApplicationMap().get(Globals.VALIDATOR_RESOURCES);
 248  
 
 249  
     }
 250  
 
 251  
 
 252  
     /**
 253  
      * <p>Perform a validation using the specified Commons Validator type.</p>
 254  
      *
 255  
      * @param context <code>FacesContext</code> for the current request
 256  
      * @param component <code>UIComponent</code> whose value is being validated
 257  
      * @param value The value being validated
 258  
      * @param type Type of validation to be performed
 259  
      * @param vars Mutable map of values to be passed in to the validation
 260  
      *
 261  
      * @exception ValidatorException if a validation error occurs
 262  
      */
 263  
     protected void validate(FacesContext context, UIComponent component,
 264  
                             Object value, String type, Map vars)
 265  
       throws ValidatorException {
 266  
 
 267  
         // Look up the actions we must perform
 268  
         ShaleValidatorAction[] actions = actions(context, type);
 269  
         if (actions == null) {
 270  
             throw new IllegalArgumentException("No validator for type '"
 271  
                                                + type + "' has been configured");
 272  
         }
 273  
 
 274  
         // Perform the actions in order, throwing a ValidatorException
 275  
         // on the first one that fails (per the standard Validator contract)
 276  
         for (int i = 0; i < actions.length; i++) {
 277  
             Object instance = actions[i].getInstance();
 278  
             Method method = actions[i].getMethod();
 279  
             Class[] signature = actions[i].getSignature();
 280  
             Arg[] args = actions[i].getParameterArgs();
 281  
             Object[] parameters = new Object[signature.length];
 282  
             for (int j = 0; j < parameters.length; j++) {
 283  
                 parameters[j] = convert(context, vars.get(args[j].getKey()), signature[j]);
 284  
             }
 285  
             Boolean result = null;
 286  
             try {
 287  
                 result = (Boolean) method.invoke(instance, parameters);
 288  
             } catch (IllegalAccessException e) {
 289  
                 ;
 290  
             } catch (InvocationTargetException e) {
 291  
                 ;
 292  
             }
 293  
             if (!result.booleanValue()) {
 294  
                 String error = getMessage();
 295  
                 if (error == null) {
 296  
                     error = message(context, actions[i].getMessageKey());
 297  
                 }
 298  
                 args = actions[i].getMessageArgs();
 299  
                 parameters = new Object[args.length];
 300  
                 for (int j = 0; j < parameters.length; j++) {
 301  
                     parameters[j] = vars.get(args[j].getKey());
 302  
                 }
 303  
                 Locale locale = context.getViewRoot().getLocale();
 304  
                 String formatted = new MessageFormat(error, locale).format(parameters);
 305  
                 FacesMessage message =
 306  
                   new FacesMessage(FacesMessage.SEVERITY_ERROR, formatted, null);
 307  
                 throw new ValidatorException(message);
 308  
             }
 309  
         }
 310  
 
 311  
     }
 312  
     
 313  
 
 314  
 }