Coverage report

  %line %branch
org.apache.commons.validator.ValidatorResources$1
9% 
50% 

 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  
 package org.apache.commons.validator;
 18  
 
 19  
 import java.io.IOException;
 20  
 import java.io.InputStream;
 21  
 import java.io.Serializable;
 22  
 import java.net.URL;
 23  
 import java.util.Collections;
 24  
 import java.util.Iterator;
 25  
 import java.util.Locale;
 26  
 import java.util.Map;
 27  
 
 28  
 import org.apache.commons.collections.FastHashMap;
 29  
 import org.apache.commons.digester.Digester;
 30  
 import org.apache.commons.digester.Rule;
 31  
 import org.apache.commons.digester.xmlrules.DigesterLoader;
 32  
 import org.apache.commons.logging.Log;
 33  
 import org.apache.commons.logging.LogFactory;
 34  
 import org.xml.sax.SAXException;
 35  
 import org.xml.sax.Attributes;
 36  
 
 37  
 /**
 38  
  * <p>
 39  
  * General purpose class for storing <code>FormSet</code> objects based
 40  
  * on their associated <code>Locale</code>.  Instances of this class are usually
 41  
  * configured through a validation.xml file that is parsed in a constructor.
 42  
  * </p>
 43  
  *
 44  
  * <p><strong>Note</strong> - Classes that extend this class
 45  
  * must be Serializable so that instances may be used in distributable
 46  
  * application server environments.</p>
 47  
  *
 48  
  * <p>
 49  
  * The use of FastHashMap is deprecated and will be replaced in a future
 50  
  * release.
 51  
  * </p>
 52  
  *
 53  
  * @version $Revision: 478473 $ $Date: 2006-11-23 05:42:30 +0000 (Thu, 23 Nov 2006) $
 54  
  */
 55  
 public class ValidatorResources implements Serializable {
 56  
 
 57  
     /** Name of the digester validator rules file */
 58  
     private static final String VALIDATOR_RULES = "digester-rules.xml";
 59  
 
 60  
     /**
 61  
      * The set of public identifiers, and corresponding resource names, for
 62  
      * the versions of the configuration file DTDs that we know about.  There
 63  
      * <strong>MUST</strong> be an even number of Strings in this list!
 64  
      */
 65  
     private static final String REGISTRATIONS[] = {
 66  
         "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.0//EN",
 67  
         "/org/apache/commons/validator/resources/validator_1_0.dtd",
 68  
         "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.0.1//EN",
 69  
         "/org/apache/commons/validator/resources/validator_1_0_1.dtd",
 70  
         "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1//EN",
 71  
         "/org/apache/commons/validator/resources/validator_1_1.dtd",
 72  
         "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1.3//EN",
 73  
         "/org/apache/commons/validator/resources/validator_1_1_3.dtd",
 74  
         "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.2.0//EN",
 75  
         "/org/apache/commons/validator/resources/validator_1_2_0.dtd",
 76  
         "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.3.0//EN",
 77  
         "/org/apache/commons/validator/resources/validator_1_3_0.dtd"
 78  
     };
 79  
 
 80  
     private transient Log log = LogFactory.getLog(ValidatorResources.class);
 81  
 
 82  
     /**
 83  
      * <code>Map</code> of <code>FormSet</code>s stored under
 84  
      * a <code>Locale</code> key.
 85  
      * @deprecated Subclasses should use getFormSets() instead.
 86  
      */
 87  
     protected FastHashMap hFormSets = new FastHashMap();
 88  
 
 89  
     /**
 90  
      * <code>Map</code> of global constant values with
 91  
      * the name of the constant as the key.
 92  
      * @deprecated Subclasses should use getConstants() instead.
 93  
      */
 94  
     protected FastHashMap hConstants = new FastHashMap();
 95  
 
 96  
     /**
 97  
      * <code>Map</code> of <code>ValidatorAction</code>s with
 98  
      * the name of the <code>ValidatorAction</code> as the key.
 99  
      * @deprecated Subclasses should use getActions() instead.
 100  
      */
 101  
     protected FastHashMap hActions = new FastHashMap();
 102  
 
 103  
     /**
 104  
      * The default locale on our server.
 105  
      */
 106  
     protected static Locale defaultLocale = Locale.getDefault();
 107  
 
 108  
     /**
 109  
      * Create an empty ValidatorResources object.
 110  
      */
 111  
     public ValidatorResources() {
 112  
         super();
 113  
     }
 114  
     
 115  
     /**
 116  
      * This is the default <code>FormSet</code> (without locale). (We probably don't need
 117  
      * the defaultLocale anymore.)
 118  
      */
 119  
     protected FormSet defaultFormSet;
 120  
     
 121  
     /**
 122  
      * Create a ValidatorResources object from an InputStream.
 123  
      *
 124  
      * @param in InputStream to a validation.xml configuration file.  It's the client's
 125  
      * responsibility to close this stream.
 126  
      * @throws IOException
 127  
      * @throws SAXException if the validation XML files are not valid or well
 128  
      * formed.
 129  
      * @throws IOException  if an I/O error occurs processing the XML files
 130  
      * @since Validator 1.1
 131  
      */
 132  
     public ValidatorResources(InputStream in) throws IOException, SAXException {
 133  
         this(new InputStream[]{in});
 134  
     }
 135  
 
 136  
     /**
 137  
      * Create a ValidatorResources object from an InputStream.
 138  
      *
 139  
      * @param streams An array of InputStreams to several validation.xml
 140  
      * configuration files that will be read in order and merged into this object.
 141  
      * It's the client's responsibility to close these streams.
 142  
      * @throws IOException
 143  
      * @throws SAXException if the validation XML files are not valid or well
 144  
      * formed.
 145  
      * @throws IOException  if an I/O error occurs processing the XML files
 146  
      * @since Validator 1.1
 147  
      */
 148  
     public ValidatorResources(InputStream[] streams)
 149  
             throws IOException, SAXException {
 150  
 
 151  
         super();
 152  
 
 153  
         Digester digester = initDigester();
 154  
         for (int i = 0; i < streams.length; i++) {
 155  
             digester.push(this);
 156  
             digester.parse(streams[i]);
 157  
         }
 158  
 
 159  
         this.process();
 160  
     }
 161  
     
 162  
     /**
 163  
      * Create a ValidatorResources object from an uri
 164  
      *
 165  
      * @param uri The location of a validation.xml configuration file. 
 166  
      * @throws IOException
 167  
      * @throws SAXException if the validation XML files are not valid or well
 168  
      * formed.
 169  
      * @throws IOException  if an I/O error occurs processing the XML files
 170  
      * @since Validator 1.2
 171  
      */
 172  
     public ValidatorResources(String uri) throws IOException, SAXException {
 173  
         this(new String[]{uri});
 174  
     }
 175  
 
 176  
     /**
 177  
      * Create a ValidatorResources object from several uris
 178  
      *
 179  
      * @param uris An array of uris to several validation.xml
 180  
      * configuration files that will be read in order and merged into this object.
 181  
      * @throws IOException
 182  
      * @throws SAXException if the validation XML files are not valid or well
 183  
      * formed.
 184  
      * @throws IOException  if an I/O error occurs processing the XML files
 185  
      * @since Validator 1.2
 186  
      */
 187  
     public ValidatorResources(String[] uris)
 188  
             throws IOException, SAXException {
 189  
 
 190  
         super();
 191  
 
 192  
         Digester digester = initDigester();
 193  
         for (int i = 0; i < uris.length; i++) {
 194  
             digester.push(this);
 195  
             digester.parse(uris[i]);
 196  
         }
 197  
 
 198  
         this.process();
 199  
     }    
 200  
 
 201  
     /**
 202  
      * Create a ValidatorResources object from a URL.
 203  
      *
 204  
      * @param url The URL for the validation.xml
 205  
      * configuration file that will be read into this object.
 206  
      * @throws IOException
 207  
      * @throws SAXException if the validation XML file are not valid or well
 208  
      * formed.
 209  
      * @throws IOException  if an I/O error occurs processing the XML files
 210  
      * @since Validator 1.3.1
 211  
      */
 212  
     public ValidatorResources(URL url)
 213  
             throws IOException, SAXException {
 214  
         this(new URL[]{url});
 215  
     }
 216  
 
 217  
     /**
 218  
      * Create a ValidatorResources object from several URL.
 219  
      *
 220  
      * @param urls An array of URL to several validation.xml
 221  
      * configuration files that will be read in order and merged into this object.
 222  
      * @throws IOException
 223  
      * @throws SAXException if the validation XML files are not valid or well
 224  
      * formed.
 225  
      * @throws IOException  if an I/O error occurs processing the XML files
 226  
      * @since Validator 1.3.1
 227  
      */
 228  
     public ValidatorResources(URL[] urls)
 229  
             throws IOException, SAXException {
 230  
 
 231  
         super();
 232  
 
 233  
         Digester digester = initDigester();
 234  
         for (int i = 0; i < urls.length; i++) {
 235  
             digester.push(this);
 236  
             InputStream stream = null;
 237  
             try {
 238  
                 stream = urls[i].openStream();
 239  
                 org.xml.sax.InputSource source = 
 240  
                      new org.xml.sax.InputSource(urls[i].toExternalForm());
 241  
                 source.setByteStream(stream);
 242  
                 digester.parse(source);
 243  
             } finally {
 244  
                 if (stream != null) {
 245  
                     try {
 246  
                         stream.close();
 247  
                     } catch (IOException e) {
 248  
                         // ignore problem closing
 249  
                     }
 250  
                 }
 251  
             } 
 252  
         }
 253  
 
 254  
         this.process();
 255  
     }
 256  
 
 257  
     /**
 258  
      *  Initialize the digester.
 259  
      */
 260  
     private Digester initDigester() {
 261  
         URL rulesUrl = this.getClass().getResource(VALIDATOR_RULES);
 262  
         if (rulesUrl == null) {
 263  
             // Fix for Issue# VALIDATOR-195
 264  
             rulesUrl = ValidatorResources.class.getResource(VALIDATOR_RULES);
 265  
         }
 266  
         if (getLog().isDebugEnabled()) {
 267  
             getLog().debug("Loading rules from '" + rulesUrl + "'");
 268  
         }
 269  
         Digester digester = DigesterLoader.createDigester(rulesUrl);
 270  
         digester.setNamespaceAware(true);
 271  
         digester.setValidating(true);
 272  
         digester.setUseContextClassLoader(true);
 273  
 
 274  
         // Add rules for arg0-arg3 elements
 275  
         addOldArgRules(digester);
 276  
 
 277  
         // register DTDs
 278  
         for (int i = 0; i < REGISTRATIONS.length; i += 2) {
 279  
             URL url = this.getClass().getResource(REGISTRATIONS[i + 1]);
 280  
             if (url != null) {
 281  
                 digester.register(REGISTRATIONS[i], url.toString());
 282  
             }
 283  
         }
 284  
         return digester;
 285  
     }
 286  
 
 287  
     private static final String ARGS_PATTERN 
 288  
                = "form-validation/formset/form/field/arg";
 289  
 
 290  
     /**
 291  
      * Create a <code>Rule</code> to handle <code>arg0-arg3</code>
 292  
      * elements. This will allow validation.xml files that use the
 293  
      * versions of the DTD prior to Validator 1.2.0 to continue
 294  
      * working.
 295  
      */
 296  
     private void addOldArgRules(Digester digester) {
 297  
 
 298  
         // Create a new rule to process args elements
 299  
         Rule rule = new Rule() {
 300  98
             public void begin(String namespace, String name, 
 301  
                                Attributes attributes) throws Exception {
 302  
                 // Create the Arg
 303  0
                 Arg arg = new Arg();
 304  0
                 arg.setKey(attributes.getValue("key"));
 305  0
                 arg.setName(attributes.getValue("name"));
 306  0
                 if ("false".equalsIgnoreCase(attributes.getValue("resource"))) {
 307  0
                     arg.setResource(false);
 308  
                 }
 309  
                 try {
 310  0
                     arg.setPosition(Integer.parseInt(name.substring(3)));
 311  0
                 } catch (Exception ex) {
 312  0
                     getLog().error("Error parsing Arg position: " 
 313  
                                + name + " " + arg + " " + ex);
 314  
                 }
 315  
 
 316  
                 // Add the arg to the parent field
 317  0
                 ((Field)getDigester().peek(0)).addArg(arg);
 318  0
             }
 319  
         };
 320  
 
 321  
         // Add the rule for each of the arg elements
 322  
         digester.addRule(ARGS_PATTERN + "0", rule);
 323  
         digester.addRule(ARGS_PATTERN + "1", rule);
 324  
         digester.addRule(ARGS_PATTERN + "2", rule);
 325  
         digester.addRule(ARGS_PATTERN + "3", rule);
 326  
 
 327  
     }
 328  
 
 329  
     /**
 330  
      * Add a <code>FormSet</code> to this <code>ValidatorResources</code>
 331  
      * object.  It will be associated with the <code>Locale</code> of the
 332  
      * <code>FormSet</code>.
 333  
      * @param fs The form set to add.
 334  
      * @since Validator 1.1
 335  
      */
 336  
     public void addFormSet(FormSet fs) {
 337  
         String key = this.buildKey(fs);
 338  
         if (key.length() == 0) {// there can only be one default formset
 339  
             if (getLog().isWarnEnabled() && defaultFormSet != null) {
 340  
                 // warn the user he might not get the expected results
 341  
                 getLog().warn("Overriding default FormSet definition.");
 342  
             }
 343  
             defaultFormSet = fs;
 344  
         } else {
 345  
             FormSet formset = (FormSet) hFormSets.get(key);
 346  
             if (formset == null) {// it hasn't been included yet
 347  
                 if (getLog().isDebugEnabled()) {
 348  
                     getLog().debug("Adding FormSet '" + fs.toString() + "'.");
 349  
                 }
 350  
             } else if (getLog().isWarnEnabled()) {// warn the user he might not
 351  
                                                 // get the expected results
 352  
                 getLog()
 353  
                         .warn("Overriding FormSet definition. Duplicate for locale: "
 354  
                                 + key);
 355  
             }
 356  
             hFormSets.put(key, fs);
 357  
         }
 358  
     }
 359  
 
 360  
     /**
 361  
      * Add a global constant to the resource.
 362  
      * @param name The constant name.
 363  
      * @param value The constant value.
 364  
      */
 365  
     public void addConstant(String name, String value) {
 366  
         if (getLog().isDebugEnabled()) {
 367  
             getLog().debug("Adding Global Constant: " + name + "," + value);
 368  
         }
 369  
 
 370  
         this.hConstants.put(name, value);
 371  
     }
 372  
 
 373  
     /**
 374  
      * Add a <code>ValidatorAction</code> to the resource.  It also creates an
 375  
      * instance of the class based on the <code>ValidatorAction</code>s
 376  
      * classname and retrieves the <code>Method</code> instance and sets them
 377  
      * in the <code>ValidatorAction</code>.
 378  
      * @param va The validator action.
 379  
      */
 380  
     public void addValidatorAction(ValidatorAction va) {
 381  
         va.init();
 382  
 
 383  
         this.hActions.put(va.getName(), va);
 384  
 
 385  
         if (getLog().isDebugEnabled()) {
 386  
             getLog().debug("Add ValidatorAction: " + va.getName() + "," + va.getClassname());
 387  
         }
 388  
     }
 389  
 
 390  
     /**
 391  
      * Get a <code>ValidatorAction</code> based on it's name.
 392  
      * @param key The validator action key.
 393  
      * @return The validator action.
 394  
      */
 395  
     public ValidatorAction getValidatorAction(String key) {
 396  
         return (ValidatorAction) hActions.get(key);
 397  
     }
 398  
 
 399  
     /**
 400  
      * Get an unmodifiable <code>Map</code> of the <code>ValidatorAction</code>s.
 401  
      * @return Map of validator actions.
 402  
      */
 403  
     public Map getValidatorActions() {
 404  
         return Collections.unmodifiableMap(hActions);
 405  
     }
 406  
 
 407  
     /**
 408  
      * Builds a key to store the <code>FormSet</code> under based on it's
 409  
      * language, country, and variant values.
 410  
      * @param fs The Form Set.
 411  
      * @return generated key for a formset.
 412  
      */
 413  
     protected String buildKey(FormSet fs) {
 414  
         return
 415  
                 this.buildLocale(fs.getLanguage(), fs.getCountry(), fs.getVariant());
 416  
     }
 417  
 
 418  
     /**
 419  
      * Assembles a Locale code from the given parts.
 420  
      */
 421  
     private String buildLocale(String lang, String country, String variant) {
 422  
         String key = ((lang != null && lang.length() > 0) ? lang : "");
 423  
         key += ((country != null && country.length() > 0) ? "_" + country : "");
 424  
         key += ((variant != null && variant.length() > 0) ? "_" + variant : "");
 425  
         return key;
 426  
     }
 427  
 
 428  
     /**
 429  
      * <p>Gets a <code>Form</code> based on the name of the form and the
 430  
      * <code>Locale</code> that most closely matches the <code>Locale</code>
 431  
      * passed in.  The order of <code>Locale</code> matching is:</p>
 432  
      * <ol>
 433  
      *    <li>language + country + variant</li>
 434  
      *    <li>language + country</li>
 435  
      *    <li>language</li>
 436  
      *    <li>default locale</li>
 437  
      * </ol>
 438  
      * @param locale The Locale.
 439  
      * @param formKey The key for the Form.
 440  
      * @return The validator Form.
 441  
      * @since Validator 1.1
 442  
      */
 443  
     public Form getForm(Locale locale, String formKey) {
 444  
         return this.getForm(locale.getLanguage(), locale.getCountry(), locale
 445  
                 .getVariant(), formKey);
 446  
     }
 447  
 
 448  
     /**
 449  
      * <p>Gets a <code>Form</code> based on the name of the form and the
 450  
      * <code>Locale</code> that most closely matches the <code>Locale</code>
 451  
      * passed in.  The order of <code>Locale</code> matching is:</p>
 452  
      * <ol>
 453  
      *    <li>language + country + variant</li>
 454  
      *    <li>language + country</li>
 455  
      *    <li>language</li>
 456  
      *    <li>default locale</li>
 457  
      * </ol>
 458  
      * @param language The locale's language.
 459  
      * @param country The locale's country.
 460  
      * @param variant The locale's language variant.
 461  
      * @param formKey The key for the Form.
 462  
      * @return The validator Form.
 463  
      * @since Validator 1.1
 464  
      */
 465  
     public Form getForm(String language, String country, String variant,
 466  
             String formKey) {
 467  
 
 468  
         Form form = null;
 469  
 
 470  
         // Try language/country/variant
 471  
         String key = this.buildLocale(language, country, variant);
 472  
         if (key.length() > 0) {
 473  
             FormSet formSet = (FormSet)hFormSets.get(key);
 474  
             if (formSet != null) {
 475  
                 form = formSet.getForm(formKey);
 476  
             }
 477  
         }
 478  
         String localeKey  = key;
 479  
 
 480  
 
 481  
         // Try language/country
 482  
         if (form == null) {
 483  
             key = buildLocale(language, country, null);
 484  
             if (key.length() > 0) {
 485  
                 FormSet formSet = (FormSet)hFormSets.get(key);
 486  
                 if (formSet != null) {
 487  
                     form = formSet.getForm(formKey);
 488  
                 }
 489  
             }
 490  
         }
 491  
 
 492  
         // Try language
 493  
         if (form == null) {
 494  
             key = buildLocale(language, null, class="keyword">null);
 495  
             if (key.length() > 0) {
 496  
                 FormSet formSet = (FormSet)hFormSets.get(key);
 497  
                 if (formSet != null) {
 498  
                     form = formSet.getForm(formKey);
 499  
                 }
 500  
             }
 501  
         }
 502  
 
 503  
         // Try default formset
 504  
         if (form == null) {
 505  
             form = defaultFormSet.getForm(formKey);
 506  
             key = "default";
 507  
         }
 508  
 
 509  
         if (form == null) {
 510  
             if (getLog().isWarnEnabled()) {
 511  
                 getLog().warn("Form '" + formKey + "' not found for locale '" +
 512  
                          localeKey + "'");
 513  
             }
 514  
         } else {
 515  
             if (getLog().isDebugEnabled()) {
 516  
                 getLog().debug("Form '" + formKey + "' found in formset '" +
 517  
                           key + "' for locale '" + localeKey + "'");
 518  
             }
 519  
         }
 520  
 
 521  
         return form;
 522  
 
 523  
     }
 524  
 
 525  
     /**
 526  
      * Process the <code>ValidatorResources</code> object. Currently sets the
 527  
      * <code>FastHashMap</code> s to the 'fast' mode and call the processes
 528  
      * all other resources. <strong>Note </strong>: The framework calls this
 529  
      * automatically when ValidatorResources is created from an XML file. If you
 530  
      * create an instance of this class by hand you <strong>must </strong> call
 531  
      * this method when finished.
 532  
      */
 533  
     public void process() {
 534  
         hFormSets.setFast(true);
 535  
         hConstants.setFast(true);
 536  
         hActions.setFast(true);
 537  
 
 538  
         this.processForms();
 539  
     }
 540  
     
 541  
     /**
 542  
      * <p>Process the <code>Form</code> objects.  This clones the <code>Field</code>s
 543  
      * that don't exist in a <code>FormSet</code> compared to its parent
 544  
      * <code>FormSet</code>.</p>
 545  
      */
 546  
     private void processForms() {
 547  
         if (defaultFormSet == null) {// it isn't mandatory to have a
 548  
             // default formset
 549  
             defaultFormSet = new FormSet();
 550  
         }
 551  
         defaultFormSet.process(hConstants);
 552  
         // Loop through FormSets and merge if necessary
 553  
         for (Iterator i = hFormSets.keySet().iterator(); i.hasNext();) {
 554  
             String key = (String) i.next();
 555  
             FormSet fs = (FormSet) hFormSets.get(key);
 556  
             fs.merge(getParent(fs));
 557  
         }
 558  
 
 559  
         // Process Fully Constructed FormSets
 560  
         for (Iterator i = hFormSets.values().iterator(); i.hasNext();) {
 561  
             FormSet fs = (FormSet) i.next();
 562  
             if (!fs.isProcessed()) {
 563  
                 fs.process(hConstants);
 564  
             }
 565  
         }
 566  
     }
 567  
 
 568  
     /**
 569  
      * Finds the given formSet's parent. ex: A formSet with locale en_UK_TEST1
 570  
      * has a direct parent in the formSet with locale en_UK. If it doesn't
 571  
      * exist, find the formSet with locale en, if no found get the
 572  
      * defaultFormSet.
 573  
      * 
 574  
      * @param fs
 575  
      *            the formSet we want to get the parent from
 576  
      * @return fs's parent
 577  
      */
 578  
     private FormSet getParent(FormSet fs) {
 579  
 
 580  
         FormSet parent = null;
 581  
         if (fs.getType() == FormSet.LANGUAGE_FORMSET) {
 582  
             parent = defaultFormSet;
 583  
         } else if (fs.getType() == FormSet.COUNTRY_FORMSET) {
 584  
             parent = (FormSet) hFormSets.get(buildLocale(fs.getLanguage(),
 585  
                     null, class="keyword">null));
 586  
             if (parent == null) {
 587  
                 parent = defaultFormSet;
 588  
             }
 589  
         } else if (fs.getType() == FormSet.VARIANT_FORMSET) {
 590  
             parent = (FormSet) hFormSets.get(buildLocale(fs.getLanguage(), fs
 591  
                     .getCountry(), null));
 592  
             if (parent == null) {
 593  
                 parent = (FormSet) hFormSets.get(buildLocale(fs.getLanguage(),
 594  
                         null, class="keyword">null));
 595  
                 if (parent == null) {
 596  
                     parent = defaultFormSet;
 597  
                 }
 598  
             }
 599  
         }
 600  
         return parent;
 601  
     }
 602  
 
 603  
     /**
 604  
      * <p>Gets a <code>FormSet</code> based on the language, country
 605  
      *    and variant.</p>
 606  
      * @param language The locale's language.
 607  
      * @param country The locale's country.
 608  
      * @param variant The locale's language variant.
 609  
      * @return The FormSet for a locale.
 610  
      * @since Validator 1.2
 611  
      */
 612  
     FormSet getFormSet(String language, String country, String variant) {
 613  
 
 614  
         String key = buildLocale(language, country, variant);
 615  
 
 616  
         if (key.length() == 0) {
 617  
             return defaultFormSet;
 618  
         }
 619  
 
 620  
         return (FormSet)hFormSets.get(key);
 621  
     }
 622  
 
 623  
     /**
 624  
      * Returns a Map of String locale keys to Lists of their FormSets.
 625  
      * @return Map of Form sets
 626  
      * @since Validator 1.2.0
 627  
      */
 628  
     protected Map getFormSets() {
 629  
         return hFormSets;
 630  
     }
 631  
 
 632  
     /**
 633  
      * Returns a Map of String constant names to their String values.
 634  
      * @return Map of Constants
 635  
      * @since Validator 1.2.0
 636  
      */
 637  
     protected Map getConstants() {
 638  
         return hConstants;
 639  
     }
 640  
 
 641  
     /**
 642  
      * Returns a Map of String ValidatorAction names to their ValidatorAction.
 643  
      * @return Map of Validator Actions
 644  
      * @since Validator 1.2.0
 645  
      */
 646  
     protected Map getActions() {
 647  
         return hActions;
 648  
     }
 649  
 
 650  
     /**
 651  
      * Accessor method for Log instance.
 652  
      *
 653  
      * The Log instance variable is transient and
 654  
      * accessing it through this method ensures it
 655  
      * is re-initialized when this instance is
 656  
      * de-serialized.
 657  
      *
 658  
      * @return The Log instance.
 659  
      */
 660  
     private Log getLog() {
 661  
         if (log == null) {
 662  
             log =  LogFactory.getLog(ValidatorResources.class);
 663  
         }
 664  
         return log;
 665  
     }
 666  
 
 667  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.