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