Coverage Report - org.apache.tapestry.valid.BaseValidator
 
Classes in this File Line Coverage Branch Coverage Complexity
BaseValidator
0%
0/44
0%
0/8
1.333
 
 1  
 // Copyright 2004, 2005 The Apache Software Foundation
 2  
 //
 3  
 // Licensed under the Apache License, Version 2.0 (the "License");
 4  
 // you may not use this file except in compliance with the License.
 5  
 // You may obtain a copy of the License at
 6  
 //
 7  
 //     http://www.apache.org/licenses/LICENSE-2.0
 8  
 //
 9  
 // Unless required by applicable law or agreed to in writing, software
 10  
 // distributed under the License is distributed on an "AS IS" BASIS,
 11  
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12  
 // See the License for the specific language governing permissions and
 13  
 // limitations under the License.
 14  
 
 15  
 package org.apache.tapestry.valid;
 16  
 
 17  
 import java.text.MessageFormat;
 18  
 import java.util.HashMap;
 19  
 import java.util.Locale;
 20  
 import java.util.Map;
 21  
 import java.util.ResourceBundle;
 22  
 
 23  
 import org.apache.hivemind.HiveMind;
 24  
 import org.apache.hivemind.Resource;
 25  
 import org.apache.hivemind.impl.DefaultClassResolver;
 26  
 import org.apache.hivemind.util.ClasspathResource;
 27  
 import org.apache.hivemind.util.PropertyUtils;
 28  
 import org.apache.tapestry.IForm;
 29  
 import org.apache.tapestry.IMarkupWriter;
 30  
 import org.apache.tapestry.IRequestCycle;
 31  
 import org.apache.tapestry.IScript;
 32  
 import org.apache.tapestry.PageRenderSupport;
 33  
 import org.apache.tapestry.TapestryUtils;
 34  
 import org.apache.tapestry.engine.IScriptSource;
 35  
 import org.apache.tapestry.form.IFormComponent;
 36  
 
 37  
 /**
 38  
  * Abstract base class for {@link IValidator}. Supports a required and locale property.
 39  
  * 
 40  
  * @author Howard Lewis Ship
 41  
  * @since 1.0.8
 42  
  */
 43  
 
 44  
 public abstract class BaseValidator implements IValidator
 45  
 {
 46  
     /**
 47  
      * Input Symbol used to represent the field being validated.
 48  
      * 
 49  
      * @see #processValidatorScript(String, IRequestCycle, IFormComponent, Map)
 50  
      * @since 2.2
 51  
      */
 52  
 
 53  
     public static final String FIELD_SYMBOL = "field";
 54  
 
 55  
     /**
 56  
      * Input symbol used to represent the validator itself to the script.
 57  
      * 
 58  
      * @see #processValidatorScript(String, IRequestCycle, IFormComponent, Map)
 59  
      * @since 2.2
 60  
      */
 61  
 
 62  
     public static final String VALIDATOR_SYMBOL = "validator";
 63  
 
 64  
     /**
 65  
      * Input symbol used to represent the {@link IForm}containing the field to the script.
 66  
      * 
 67  
      * @see #processValidatorScript(String, IRequestCycle, IFormComponent, Map)
 68  
      * @since 2.2
 69  
      */
 70  
 
 71  
     public static final String FORM_SYMBOL = "form";
 72  
 
 73  
     /**
 74  
      * Output symbol set by the script asthe name of the validator JavaScript function. The function
 75  
      * implemented must return true or false (true if the field is valid, false otherwise). After
 76  
      * the script is executed, the function is added to the {@link IForm}as a
 77  
      * {@link org.apache.tapestry.form.FormEventType#SUBMIT}.
 78  
      * 
 79  
      * @see #processValidatorScript(String, IRequestCycle, IFormComponent, Map)
 80  
      * @since 2.2
 81  
      */
 82  
 
 83  
     public static final String FUNCTION_SYMBOL = "function";
 84  
 
 85  
     private boolean _required;
 86  
 
 87  
     /** @since 3.0 */
 88  
 
 89  
     private String _requiredMessage;
 90  
 
 91  
     /**
 92  
      * @since 2.2
 93  
      */
 94  
 
 95  0
     private boolean _clientScriptingEnabled = false;
 96  
     
 97  
     /**
 98  
      * @since 4.1
 99  
      */
 100  
     private IScriptSource _scriptSource;
 101  
     
 102  
     /**
 103  
      * Standard constructor. Leaves locale as system default and required as false.
 104  
      */
 105  
 
 106  
     public BaseValidator()
 107  0
     {
 108  0
     }
 109  
 
 110  
     /**
 111  
      * Allow the validator to be initialized with a property initialization string.
 112  
      * 
 113  
      * @since 4.0
 114  
      */
 115  
     public BaseValidator(String initializer)
 116  0
     {
 117  0
         PropertyUtils.configureProperties(this, initializer);
 118  0
     }
 119  
 
 120  
     protected BaseValidator(boolean required)
 121  0
     {
 122  0
         _required = required;
 123  0
     }
 124  
     
 125  
     public boolean isRequired()
 126  
     {
 127  0
         return _required;
 128  
     }
 129  
 
 130  
     public void setRequired(boolean required)
 131  
     {
 132  0
         _required = required;
 133  0
     }
 134  
     
 135  
     public void setScriptSource(IScriptSource scriptSource)
 136  
     {
 137  0
         _scriptSource = scriptSource;
 138  0
     }
 139  
     
 140  
     /**
 141  
      * Gets a pattern, either as the default value, or as a localized key. If override is null, then
 142  
      * the key from the <code>org.apache.tapestry.valid.ValidationStrings</code>
 143  
      * {@link ResourceBundle}(in the specified locale) is used. The pattern can then be used with
 144  
      * {@link #formatString(String, Object[])}.
 145  
      * <p>
 146  
      * Why do we not just lump these strings into TapestryStrings.properties? because
 147  
      * TapestryStrings.properties is localized to the server's locale, which is fine for the
 148  
      * logging, debugging and error messages it contains. For field validation, whose errors are
 149  
      * visible to the end user normally, we want to localize to the page's locale.
 150  
      * 
 151  
      * @param override
 152  
      *            The override value for the localized string from the bundle.
 153  
      * @param key
 154  
      *            used to lookup pattern from bundle, if override is null.
 155  
      * @param locale
 156  
      *            used to get right localization of bundle.
 157  
      * @since 3.0
 158  
      */
 159  
 
 160  
     protected String getPattern(String override, String key, Locale locale)
 161  
     {
 162  0
         if (override != null)
 163  0
             return override;
 164  
 
 165  0
         ResourceBundle strings = ResourceBundle.getBundle(
 166  
                 "org.apache.tapestry.valid.ValidationStrings",
 167  
                 locale);
 168  
 
 169  0
         return strings.getString(key);
 170  
     }
 171  
 
 172  
     /**
 173  
      * Gets a string from the standard resource bundle. The string in the bundle is treated as a
 174  
      * pattern for {@link MessageFormat#format(java.lang.String, java.lang.Object[])}.
 175  
      * 
 176  
      * @param pattern
 177  
      *            string the input pattern to be used with
 178  
      *            {@link MessageFormat#format(java.lang.String, java.lang.Object[])}. It may
 179  
      *            contain replaceable parameters, {0}, {1}, etc.
 180  
      * @param args
 181  
      *            the arguments used to fill replaceable parameters {0}, {1}, etc.
 182  
      * @since 3.0
 183  
      */
 184  
 
 185  
     protected String formatString(String pattern, Object[] args)
 186  
     {
 187  0
         return MessageFormat.format(pattern, args);
 188  
     }
 189  
 
 190  
     /**
 191  
      * Convienience method for invoking {@link #formatString(String, Object[])}.
 192  
      * 
 193  
      * @since 3.0
 194  
      */
 195  
 
 196  
     protected String formatString(String pattern, Object arg)
 197  
     {
 198  0
         return formatString(pattern, new Object[]
 199  
         { arg });
 200  
     }
 201  
 
 202  
     /**
 203  
      * Convienience method for invoking {@link #formatString(String, Object[])}.
 204  
      * 
 205  
      * @since 3.0
 206  
      */
 207  
 
 208  
     protected String formatString(String pattern, Object arg1, Object arg2)
 209  
     {
 210  0
         return formatString(pattern, new Object[]
 211  
         { arg1, arg2 });
 212  
     }
 213  
 
 214  
     /**
 215  
      * Invoked to check if the value is null. If the value is null (or empty), but the required flag
 216  
      * is set, then this method throws a {@link ValidatorException}. Otherwise, returns true if the
 217  
      * value is null.
 218  
      */
 219  
 
 220  
     protected boolean checkRequired(IFormComponent field, String value) throws ValidatorException
 221  
     {
 222  0
         boolean isEmpty = HiveMind.isBlank(value);
 223  
 
 224  0
         if (_required && isEmpty)
 225  0
             throw new ValidatorException(buildRequiredMessage(field), ValidationConstraint.REQUIRED);
 226  
 
 227  0
         return isEmpty;
 228  
     }
 229  
 
 230  
     /**
 231  
      * Builds an error message indicating a value for a required field was not supplied.
 232  
      * 
 233  
      * @since 3.0
 234  
      */
 235  
 
 236  
     protected String buildRequiredMessage(IFormComponent field)
 237  
     {
 238  0
         String pattern = getPattern(_requiredMessage, "field-is-required", field.getPage()
 239  
                 .getLocale());
 240  
 
 241  0
         return formatString(pattern, field.getDisplayName());
 242  
     }
 243  
 
 244  
     /**
 245  
      * This implementation does nothing. Subclasses may supply their own implementation.
 246  
      * 
 247  
      * @since 2.2
 248  
      */
 249  
 
 250  
     public void renderValidatorContribution(IFormComponent field, IMarkupWriter writer,
 251  
             IRequestCycle cycle)
 252  
     {
 253  0
     }
 254  
 
 255  
     /**
 256  
      * Invoked (from sub-class implementations of
 257  
      * {@link #renderValidatorContribution(IFormComponent, IMarkupWriter, IRequestCycle)}to process
 258  
      * a standard validation script. This expects that:
 259  
      * <ul>
 260  
      * <li>The {@link IFormComponent}is (ultimately) wrapped by a {@link Body}
 261  
      * <li>The script generates a symbol named "function" (as per {@link #FUNCTION_SYMBOL})
 262  
      * </ul>
 263  
      * 
 264  
      * @param scriptPath
 265  
      *            the resource path of the script to execute
 266  
      * @param cycle
 267  
      *            The active request cycle
 268  
      * @param field
 269  
      *            The field to be validated
 270  
      * @param symbols
 271  
      *            a set of input symbols needed by the script. These symbols are augmented with
 272  
      *            symbols for the field, form and validator. symbols may be null, but will be
 273  
      *            modified if not null.
 274  
      * @throws ApplicationRuntimeException
 275  
      *             if there's an error processing the script.
 276  
      * @since 2.2
 277  
      */
 278  
 
 279  
     protected void processValidatorScript(String scriptPath, IRequestCycle cycle,
 280  
             IFormComponent field, Map symbols)
 281  
     {
 282  0
         IForm form = field.getForm();
 283  
         
 284  0
         Map finalSymbols = (symbols == null) ? new HashMap() : symbols;
 285  
         
 286  0
         finalSymbols.put(FIELD_SYMBOL, field);
 287  0
         finalSymbols.put(FORM_SYMBOL, form);
 288  0
         finalSymbols.put(VALIDATOR_SYMBOL, this);
 289  
         
 290  0
         Resource location = new ClasspathResource(new DefaultClassResolver(), scriptPath);
 291  
         
 292  0
         IScript script = _scriptSource.getScript(location);
 293  
 
 294  
         // If there's an error, report it against the field (this validator object doesn't
 295  
         // have a location).
 296  
 
 297  0
         PageRenderSupport pageRenderSupport = TapestryUtils.getPageRenderSupport(cycle, field);
 298  
 
 299  0
         script.execute(field, cycle, pageRenderSupport, finalSymbols);
 300  0
     }
 301  
 
 302  
     /**
 303  
      * Returns true if client scripting is enabled. Some validators are capable of generating
 304  
      * client-side scripting to perform validation when the form is submitted. By default, this flag
 305  
      * is false and subclasses should check it (in
 306  
      * {@link #renderValidatorContribution(IFormComponent, IMarkupWriter, IRequestCycle)}) before
 307  
      * generating client side script.
 308  
      * 
 309  
      * @since 2.2
 310  
      */
 311  
 
 312  
     public boolean isClientScriptingEnabled()
 313  
     {
 314  0
         return _clientScriptingEnabled;
 315  
     }
 316  
 
 317  
     public void setClientScriptingEnabled(boolean clientScriptingEnabled)
 318  
     {
 319  0
         _clientScriptingEnabled = clientScriptingEnabled;
 320  0
     }
 321  
 
 322  
     public String getRequiredMessage()
 323  
     {
 324  0
         return _requiredMessage;
 325  
     }
 326  
 
 327  
     /**
 328  
      * Overrides the <code>field-is-required</code> bundle key. Parameter {0} is the display name
 329  
      * of the field.
 330  
      * 
 331  
      * @since 3.0
 332  
      */
 333  
 
 334  
     public void setRequiredMessage(String string)
 335  
     {
 336  0
         _requiredMessage = string;
 337  0
     }
 338  
 
 339  
 }