View Javadoc

    1   /*
    2    * $Id: FormSet.java 366933 2006-01-07 22:51:01Z niallp $
    3    * $Rev: 366933 $
    4    * $Date: 2006-01-07 22:51:01 +0000 (Sat, 07 Jan 2006) $
    5    *
    6    * ====================================================================
    7    * Copyright 2001-2006 The Apache Software Foundation
    8    *
    9    * Licensed under the Apache License, Version 2.0 (the "License");
    10   * you may not use this file except in compliance with the License.
    11   * You may obtain a copy of the License at
    12   *
    13   *     http://www.apache.org/licenses/LICENSE-2.0
    14   *
    15   * Unless required by applicable law or agreed to in writing, software
    16   * distributed under the License is distributed on an "AS IS" BASIS,
    17   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    18   * See the License for the specific language governing permissions and
    19   * limitations under the License.
    20   */
    21  package org.apache.commons.validator;
    22
    23  import java.io.Serializable;
    24  import java.util.Collections;
    25  import java.util.HashMap;
    26  import java.util.Iterator;
    27  import java.util.Map;
    28  import org.apache.commons.logging.Log;
    29  import org.apache.commons.logging.LogFactory;
    30
    31  /***
    32   * Holds a set of <code>Form</code>s stored associated with a <code>Locale</code>
    33   * based on the country, language, and variant specified. Instances of this
    34   * class are configured with a &lt;formset&gt; xml element.
    35   */
    36  public class FormSet implements Serializable {
    37
    38      /*** Logging */
    39      private transient Log log = LogFactory.getLog(FormSet.class);
    40
    41      /***
    42       * Whether or not the this <code>FormSet</code> was processed for replacing
    43       * variables in strings with their values.
    44       */
    45      private boolean processed = false;
    46
    47      /*** Language component of <code>Locale</code> (required). */
    48      private String language = null;
    49
    50      /*** Country component of <code>Locale</code> (optional). */
    51      private String country = null;
    52
    53      /*** Variant component of <code>Locale</code> (optional). */
    54      private String variant = null;
    55
    56      /***
    57       * A <code>Map</code> of <code>Form</code>s using the name field of the
    58       * <code>Form</code> as the key.
    59       */
    60      private Map forms = new HashMap();
    61
    62      /***
    63       * A <code>Map</code> of <code>Constant</code>s using the name field of the
    64       * <code>Constant</code> as the key.
    65       */
    66      private Map constants = new HashMap();
    67
    68      /***
    69       * This is the type of <code>FormSet</code>s where no locale is specified.
    70       */
    71      protected final static int GLOBAL_FORMSET = 1;
    72
    73      /***
    74       * This is the type of <code>FormSet</code>s where only language locale is
    75       * specified.
    76       */
    77      protected final static int LANGUAGE_FORMSET = 2;
    78
    79      /***
    80       * This is the type of <code>FormSet</code>s where only language and country
    81       * locale are specified.
    82       */
    83      protected final static int COUNTRY_FORMSET = 3;
    84
    85      /***
    86       * This is the type of <code>FormSet</code>s where full locale has been set.
    87       */
    88      protected final static int VARIANT_FORMSET = 4;
    89
    90      /***
    91       * Flag indicating if this formSet has been merged with its parent (higher
    92       * rank in Locale hierarchy).
    93       */
    94      private boolean merged;
    95
    96      /***
    97       * Has this formSet been merged?
    98       *
    99       * @return   true if it has been merged
    100      * @since    Validator 1.2.0
    101      */
    102     protected boolean isMerged() {
    103         return merged;
    104     }
    105
    106     /***
    107      * Returns the type of <code>FormSet</code>:<code>GLOBAL_FORMSET</code>,
    108      * <code>LANGUAGE_FORMSET</code>,<code>COUNTRY_FORMSET</code> or <code>VARIANT_FORMSET</code>
    109      * .
    110      *
    111      * @return                       The type value
    112      * @since                        Validator 1.2.0
    113      * @throws NullPointerException  if there is inconsistency in the locale
    114      *      definition (not sure about this)
    115      */
    116     protected int getType() {
    117         if (getVariant() != null) {
    118             if (getLanguage() == null || getCountry() == null) {
    119                 throw new NullPointerException(
    120                     "When variant is specified, country and language must be specified.");
    121             }
    122             return VARIANT_FORMSET;
    123         }
    124         else if (getCountry() != null) {
    125             if (getLanguage() == null) {
    126                 throw new NullPointerException(
    127                     "When country is specified, language must be specified.");
    128             }
    129             return COUNTRY_FORMSET;
    130         }
    131         else if (getLanguage() != null) {
    132             return LANGUAGE_FORMSET;
    133         }
    134         else {
    135             return GLOBAL_FORMSET;
    136         }
    137     }
    138
    139     /***
    140      * Merges the given <code>FormSet</code> into this one. If any of <code>depends</code>
    141      * s <code>Forms</code> are not in this <code>FormSet</code> then, include
    142      * them, else merge both <code>Forms</code>. Theoretically we should only
    143      * merge a "parent" formSet.
    144      *
    145      * @param depends  FormSet to be merged
    146      * @since          Validator 1.2.0
    147      */
    148     protected void merge(FormSet depends) {
    149         if (depends != null) {
    150             Map pForms = getForms();
    151             Map dForms = depends.getForms();
    152             for (Iterator it = dForms.keySet().iterator(); it.hasNext(); ) {
    153                 Object key = it.next();
    154                 Form pForm = (Form) pForms.get(key);
    155                 if (pForm != null) {//merge, but principal 'rules', don't overwrite
    156                     // anything
    157                     pForm.merge((Form) dForms.get(key));
    158                 }
    159                 else {//just add
    160                     addForm((Form) dForms.get(key));
    161                 }
    162             }
    163         }
    164         merged = true;
    165     }
    166
    167     /***
    168      * Whether or not the this <code>FormSet</code> was processed for replacing
    169      * variables in strings with their values.
    170      *
    171      * @return   The processed value
    172      */
    173     public boolean isProcessed() {
    174         return processed;
    175     }
    176
    177     /***
    178      * Gets the equivalent of the language component of <code>Locale</code>.
    179      *
    180      * @return   The language value
    181      */
    182     public String getLanguage() {
    183         return language;
    184     }
    185
    186     /***
    187      * Sets the equivalent of the language component of <code>Locale</code>.
    188      *
    189      * @param language  The new language value
    190      */
    191     public void setLanguage(String language) {
    192         this.language = language;
    193     }
    194
    195     /***
    196      * Gets the equivalent of the country component of <code>Locale</code>.
    197      *
    198      * @return   The country value
    199      */
    200     public String getCountry() {
    201         return country;
    202     }
    203
    204     /***
    205      * Sets the equivalent of the country component of <code>Locale</code>.
    206      *
    207      * @param country  The new country value
    208      */
    209     public void setCountry(String country) {
    210         this.country = country;
    211     }
    212
    213     /***
    214      * Gets the equivalent of the variant component of <code>Locale</code>.
    215      *
    216      * @return   The variant value
    217      */
    218     public String getVariant() {
    219         return variant;
    220     }
    221
    222     /***
    223      * Sets the equivalent of the variant component of <code>Locale</code>.
    224      *
    225      * @param variant  The new variant value
    226      */
    227     public void setVariant(String variant) {
    228         this.variant = variant;
    229     }
    230
    231     /***
    232      * Add a <code>Constant</code> to the locale level.
    233      *
    234      * @param name   The constant name
    235      * @param value  The constant value
    236      */
    237     public void addConstant(String name, String value) {
    238
    239         if (constants.containsKey(name)) {
    240             getLog().error("Constant '" + name +  "' already exists in FormSet["
    241                       + this.displayKey() + "] - ignoring.");
    242
    243         } else {
    244             constants.put(name, value);
    245         }
    246
    247     }
    248
    249     /***
    250      * Add a <code>Form</code> to the <code>FormSet</code>.
    251      *
    252      * @param f  The form
    253      */
    254     public void addForm(Form f) {
    255
    256         String formName = f.getName();
    257         if (forms.containsKey(formName)) {
    258             getLog().error("Form '" + formName + "' already exists in FormSet["
    259                       + this.displayKey() + "] - ignoring.");
    260
    261         } else {
    262             forms.put(f.getName(), f);
    263         }
    264
    265     }
    266
    267     /***
    268      * Retrieve a <code>Form</code> based on the form name.
    269      *
    270      * @param formName  The form name
    271      * @return          The form
    272      */
    273     public Form getForm(String formName) {
    274         return (Form) this.forms.get(formName);
    275     }
    276
    277     /***
    278      * A <code>Map</code> of <code>Form</code>s is returned as an unmodifiable
    279      * <code>Map</code> with the key based on the form name.
    280      *
    281      * @return   The forms map
    282      */
    283     public Map getForms() {
    284         return Collections.unmodifiableMap(forms);
    285     }
    286
    287     /***
    288      * Processes all of the <code>Form</code>s.
    289      *
    290      * @param globalConstants  Global constants
    291      */
    292     synchronized void process(Map globalConstants) {
    293         for (Iterator i = forms.values().iterator(); i.hasNext(); ) {
    294             Form f = (Form) i.next();
    295             f.process(globalConstants, constants, forms);
    296         }
    297
    298         processed = true;
    299     }
    300
    301     /***
    302      * Returns a string representation of the object's key.
    303      *
    304      * @return   A string representation of the key
    305      */
    306     public String displayKey() {
    307         StringBuffer results = new StringBuffer();
    308         if (language != null && language.length() > 0) {
    309             results.append("language=");
    310             results.append(language);
    311         }
    312         if (country != null && country.length() > 0) {
    313             if (results.length() > 0) {
    314                results.append(", ");
    315             }
    316             results.append("country=");
    317             results.append(country);
    318         }
    319         if (variant != null && variant.length() > 0) {
    320             if (results.length() > 0) {
    321                results.append(", ");
    322             }
    323             results.append("variant=");
    324             results.append(variant );
    325         }
    326         if (results.length() == 0) {
    327            results.append("default");
    328         }
    329
    330         return results.toString();
    331     }
    332
    333     /***
    334      * Returns a string representation of the object.
    335      *
    336      * @return   A string representation
    337      */
    338     public String toString() {
    339         StringBuffer results = new StringBuffer();
    340
    341         results.append("FormSet: language=");
    342         results.append(language);
    343         results.append("  country=");
    344         results.append(country);
    345         results.append("  variant=");
    346         results.append(variant);
    347         results.append("\n");
    348
    349         for (Iterator i = getForms().values().iterator(); i.hasNext(); ) {
    350             results.append("   ");
    351             results.append(i.next());
    352             results.append("\n");
    353         }
    354
    355         return results.toString();
    356     }
    357
    358     /***
    359      * Accessor method for Log instance.
    360      *
    361      * The Log instance variable is transient and
    362      * accessing it through this method ensures it
    363      * is re-initialized when this instance is
    364      * de-serialized.
    365      *
    366      * @return The Log instance.
    367      */
    368     private Log getLog() {
    369         if (log == null) {
    370             log =  LogFactory.getLog(FormSet.class);
    371         }
    372         return log;
    373     }
    374 }