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