View Javadoc

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