    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *     http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017
    018package org.apache.commons.configuration2;
    019
    020import java.awt.Color;
    021import java.math.BigDecimal;
    022import java.math.BigInteger;
    023import java.net.URI;
    024import java.net.URL;
    025import java.util.ArrayList;
    026import java.util.Calendar;
    027import java.util.Date;
    028import java.util.Iterator;
    029import java.util.List;
    030import java.util.Locale;
    031import java.util.NoSuchElementException;
    032
    033import org.apache.commons.configuration2.convert.ConversionHandler;
    034import org.apache.commons.configuration2.convert.DefaultConversionHandler;
    035import org.apache.commons.configuration2.ex.ConversionException;
    036import org.apache.commons.lang3.StringUtils;
    037
    038/**
    039 * Decorator providing additional getters for any Configuration. This extended
    040 * Configuration supports more types:
    041 * <ul>
    042 *   <li>{@link java.net.URL}</li>
    043 *   <li>{@link java.util.Locale}</li>
    044 *   <li>{@link java.util.Date}</li>
    045 *   <li>{@link java.util.Calendar}</li>
    046 *   <li>{@link java.awt.Color}</li>
    047 *   <li>{@link java.net.InetAddress}</li>
    048 *   <li>{@code javax.mail.internet.InternetAddress} (requires Javamail in the classpath)</li>
    049 *   <li>{@link java.lang.Enum} (Java 5 enumeration types)</li>
    050 * </ul>
    051 *
    052 * Lists and arrays are available for all types.<br>
    053 * Note that this class is only a thin wrapper over functionality already
    054 * provided by {@link AbstractConfiguration}. Basically, the generic
    055 * {@code get()}, and {@code getCollection()} methods are
    056 * used to actually perform data conversions.
    057 *
    058 * <p><strong>Example</strong></p>
    059 *
    060 * Configuration file {@code config.properties}:
    061 * <pre>
    062 * title.color = #0000FF
    063 * remote.host = 192.168.0.53
    064 * default.locales = fr,en,de
    065 * email.contact = ebourg@apache.org, tester@test.org
    066 * </pre>
    067 *
    068 * Usage:
    069 *
    070 * <pre>
    071 * DataConfiguration config = new DataConfiguration(new PropertiesConfiguration("config.properties"));
    072 *
    073 * // retrieve a property using a specialized getter
    074 * Color color = config.getColor("title.color");
    075 *
    076 * // retrieve a property using a generic getter
    077 * InetAddress host = (InetAddress) config.get(InetAddress.class, "remote.host");
    078 * Locale[] locales = (Locale[]) config.getArray(Locale.class, "default.locales");
    079 * List contacts = config.getList(InternetAddress.class, "email.contact");
    080 * </pre>
    081 *
    082 * <p><strong>Dates</strong></p>
    083 *
    084 * Date objects are expected to be formatted with the pattern {@code yyyy-MM-dd HH:mm:ss}.
    085 * This default format can be changed by specifying another format in the
    086 * getters, or by putting a date format in the configuration under the key
    087 * {@code org.apache.commons.configuration.format.date}. Alternatively, the
    088 * date format can also be specified via the {@code ConversionHandler} used
    089 * by a configuration instance:
    090 *
    091 * <pre>
    092 * DefaultConversionHandler handler = new DefaultConversionHandler();
    093 * handler.setDateFormat("mm/dd/yyyy");
    094 * config.setConversionHandler(handler);
    095 * </pre>
    096 *
    097 * @author <a href="ebourg@apache.org">Emmanuel Bourg</a>
    098 * @since 1.1
    099 */
    100public class DataConfiguration extends AbstractConfiguration
    101{
    102    /** The key of the property storing the user defined date format. */
    103    public static final String DATE_FORMAT_KEY = "org.apache.commons.configuration.format.date";
    104
    105    /** The default format for dates. */
    106    public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
    107
    108    /** Stores temporary date formats. */
    109    private static final ThreadLocal<String> TEMP_DATE_FORMAT = new ThreadLocal<>();
    110
    111    /** Stores the wrapped configuration.*/
    112    private final Configuration configuration;
    113
    114    /** A special conversion handler object used by this configuration. */
    115    private final ConversionHandler dataConversionHandler;
    116
    117    /**
    118     * Creates a new instance of {@code DataConfiguration} and sets the
    119     * wrapped configuration.
    120     *
    121     * @param configuration the wrapped configuration
    122     */
    123    public DataConfiguration(final Configuration configuration)
    124    {
    125        this.configuration = configuration;
    126        dataConversionHandler = new DataConversionHandler();
    127    }
    128
    129    /**
    130     * Return the configuration decorated by this DataConfiguration.
    131     *
    132     * @return the wrapped configuration
    133     */
    134    public Configuration getConfiguration()
    135    {
    136        return configuration;
    137    }
    138
    139    /**
    140     * {@inheritDoc} This implementation returns the special conversion handler
    141     * used by this configuration instance.
    142     */
    143    @Override
    144    public ConversionHandler getConversionHandler()
    145    {
    146        return dataConversionHandler;
    147    }
    148
    149    @Override
    150    protected Object getPropertyInternal(final String key)
    151    {
    152        return configuration.getProperty(key);
    153    }
    154
    155    @Override
    156    protected void addPropertyInternal(final String key, final Object obj)
    157    {
    158        configuration.addProperty(key, obj);
    159    }
    160
    161    @Override
    162    protected void addPropertyDirect(final String key, final Object value)
    163    {
    164        if (configuration instanceof AbstractConfiguration)
    165        {
    166            ((AbstractConfiguration) configuration).addPropertyDirect(key, value);
    167        }
    168        else
    169        {
    170            configuration.addProperty(key, value);
    171        }
    172    }
    173
    174    @Override
    175    protected boolean isEmptyInternal()
    176    {
    177        return configuration.isEmpty();
    178    }
    179
    180    @Override
    181    protected boolean containsKeyInternal(final String key)
    182    {
    183        return configuration.containsKey(key);
    184    }
    185
    186    @Override
    187    protected void clearPropertyDirect(final String key)
    188    {
    189        configuration.clearProperty(key);
    190    }
    191
    192    @Override
    193    protected void setPropertyInternal(final String key, final Object value)
    194    {
    195        configuration.setProperty(key, value);
    196    }
    197
    198    @Override
    199    protected Iterator<String> getKeysInternal()
    200    {
    201        return configuration.getKeys();
    202    }
    203
    204    /**
    205     * Get a list of Boolean objects associated with the given
    206     * configuration key. If the key doesn't map to an existing object
    207     * an empty list is returned.
    208     *
    209     * @param key The configuration key.
    210     * @return The associated Boolean list if the key is found.
    211     *
    212     * @throws ConversionException is thrown if the key maps to an
    213     *         object that is not a list of booleans.
    214     */
    215    public List<Boolean> getBooleanList(final String key)
    216    {
    217        return getBooleanList(key, new ArrayList<Boolean>());
    218    }
    219
    220    /**
    221     * Get a list of Boolean objects associated with the given
    222     * configuration key. If the key doesn't map to an existing object,
    223     * the default value is returned.
    224     *
    225     * @param key The configuration key.
    226     * @param defaultValue The default value.
    227     * @return The associated List of Booleans.
    228     *
    229     * @throws ConversionException is thrown if the key maps to an
    230     *         object that is not a list of booleans.
    231     */
    232    public List<Boolean> getBooleanList(final String key, final List<Boolean> defaultValue)
    233    {
    234         return getList(Boolean.class, key, defaultValue);
    235    }
    236
    237    /**
    238     * Get an array of boolean primitives associated with the given
    239     * configuration key. If the key doesn't map to an existing object
    240     * an empty array is returned.
    241     *
    242     * @param key The configuration key.
    243     * @return The associated boolean array if the key is found.
    244     *
    245     * @throws ConversionException is thrown if the key maps to an
    246     *         object that is not a list of booleans.
    247     */
    248    public boolean[] getBooleanArray(final String key)
    249    {
    250        return (boolean[]) getArray(Boolean.TYPE, key);
    251    }
    252
    253    /**
    254     * Get an array of boolean primitives associated with the given
    255     * configuration key. If the key doesn't map to an existing object,
    256     * the default value is returned.
    257     *
    258     * @param key          The configuration key.
    259     * @param defaultValue The default value.
    260     * @return The associated boolean array if the key is found.
    261     *
    262     * @throws ConversionException is thrown if the key maps to an
    263     *         object that is not a list of booleans.
    264     */
    265    public boolean[] getBooleanArray(final String key, final boolean[] defaultValue)
    266    {
    267        return get(boolean[].class, key, defaultValue);
    268    }
    269
    270    /**
    271     * Get a list of Byte objects associated with the given configuration key.
    272     * If the key doesn't map to an existing object an empty list is returned.
    273     *
    274     * @param key The configuration key.
    275     * @return The associated Byte list if the key is found.
    276     *
    277     * @throws ConversionException is thrown if the key maps to an
    278     *         object that is not a list of bytes.
    279     */
    280    public List<Byte> getByteList(final String key)
    281    {
    282        return getByteList(key, new ArrayList<Byte>());
    283    }
    284
    285    /**
    286     * Get a list of Byte objects associated with the given configuration key.
    287     * If the key doesn't map to an existing object, the default value is
    288     * returned.
    289     *
    290     * @param key The configuration key.
    291     * @param defaultValue The default value.
    292     * @return The associated List of Bytes.
    293     *
    294     * @throws ConversionException is thrown if the key maps to an
    295     *         object that is not a list of bytes.
    296     */
    297    public List<Byte> getByteList(final String key, final List<Byte> defaultValue)
    298    {
    299        return getList(Byte.class, key, defaultValue);
    300    }
    301
    302    /**
    303     * Get an array of byte primitives associated with the given
    304     * configuration key. If the key doesn't map to an existing object
    305     * an empty array is returned.
    306     *
    307     * @param key The configuration key.
    308     * @return The associated byte array if the key is found.
    309     *
    310     * @throws ConversionException is thrown if the key maps to an
    311     *         object that is not a list of bytes.
    312     */
    313    public byte[] getByteArray(final String key)
    314    {
    315        return getByteArray(key, new byte[0]);
    316    }
    317
    318    /**
    319     * Get an array of byte primitives associated with the given
    320     * configuration key. If the key doesn't map to an existing object
    321     * an empty array is returned.
    322     *
    323     * @param key The configuration key.
    324     * @param defaultValue the default value, which will be returned if the property is not found
    325     * @return The associated byte array if the key is found.
    326     *
    327     * @throws ConversionException is thrown if the key maps to an
    328     *         object that is not a list of bytes.
    329     */
    330    public byte[] getByteArray(final String key, final byte[] defaultValue)
    331    {
    332        return get(byte[].class, key, defaultValue);
    333    }
    334
    335    /**
    336     * Get a list of Short objects associated with the given configuration key.
    337     * If the key doesn't map to an existing object an empty list is returned.
    338     *
    339     * @param key The configuration key.
    340     * @return The associated Short list if the key is found.
    341     *
    342     * @throws ConversionException is thrown if the key maps to an
    343     *         object that is not a list of shorts.
    344     */
    345    public List<Short> getShortList(final String key)
    346    {
    347        return getShortList(key, new ArrayList<Short>());
    348    }
    349
    350    /**
    351     * Get a list of Short objects associated with the given configuration key.
    352     * If the key doesn't map to an existing object, the default value is
    353     * returned.
    354     *
    355     * @param key The configuration key.
    356     * @param defaultValue The default value.
    357     * @return The associated List of Shorts.
    358     *
    359     * @throws ConversionException is thrown if the key maps to an
    360     *         object that is not a list of shorts.
    361     */
    362    public List<Short> getShortList(final String key, final List<Short> defaultValue)
    363    {
    364        return getList(Short.class, key, defaultValue);
    365    }
    366
    367    /**
    368     * Get an array of short primitives associated with the given
    369     * configuration key. If the key doesn't map to an existing object
    370     * an empty array is returned.
    371     *
    372     * @param key The configuration key.
    373     * @return The associated short array if the key is found.
    374     *
    375     * @throws ConversionException is thrown if the key maps to an
    376     *         object that is not a list of shorts.
    377     */
    378    public short[] getShortArray(final String key)
    379    {
    380        return getShortArray(key, new short[0]);
    381    }
    382
    383    /**
    384     * Get an array of short primitives associated with the given
    385     * configuration key. If the key doesn't map to an existing object
    386     * an empty array is returned.
    387     *
    388     * @param key The configuration key.
    389     * @param defaultValue the default value, which will be returned if the property is not found
    390     * @return The associated short array if the key is found.
    391     *
    392     * @throws ConversionException is thrown if the key maps to an
    393     *         object that is not a list of shorts.
    394     */
    395    public short[] getShortArray(final String key, final short[] defaultValue)
    396    {
    397        return get(short[].class, key, defaultValue);
    398    }
    399
    400    /**
    401     * Get a list of Integer objects associated with the given
    402     * configuration key. If the key doesn't map to an existing object
    403     * an empty list is returned.
    404     *
    405     * @param key The configuration key.
    406     * @return The associated Integer list if the key is found.
    407     *
    408     * @throws ConversionException is thrown if the key maps to an
    409     *         object that is not a list of integers.
    410     */
    411    public List<Integer> getIntegerList(final String key)
    412    {
    413        return getIntegerList(key, new ArrayList<Integer>());
    414    }
    415
    416    /**
    417     * Get a list of Integer objects associated with the given
    418     * configuration key. If the key doesn't map to an existing object,
    419     * the default value is returned.
    420     *
    421     * @param key The configuration key.
    422     * @param defaultValue The default value.
    423     * @return The associated List of Integers.
    424     *
    425     * @throws ConversionException is thrown if the key maps to an
    426     *         object that is not a list of integers.
    427     */
    428    public List<Integer> getIntegerList(final String key, final List<Integer> defaultValue)
    429    {
    430        return getList(Integer.class, key, defaultValue);
    431    }
    432
    433    /**
    434     * Get an array of int primitives associated with the given
    435     * configuration key. If the key doesn't map to an existing object
    436     * an empty array is returned.
    437     *
    438     * @param key The configuration key.
    439     * @return The associated int array if the key is found.
    440     *
    441     * @throws ConversionException is thrown if the key maps to an
    442     *         object that is not a list of integers.
    443     */
    444    public int[] getIntArray(final String key)
    445    {
    446        return getIntArray(key, new int[0]);
    447    }
    448
    449    /**
    450     * Get an array of int primitives associated with the given
    451     * configuration key. If the key doesn't map to an existing object
    452     * an empty array is returned.
    453     *
    454     * @param key The configuration key.
    455     * @param defaultValue the default value, which will be returned if the property is not found
    456     * @return The associated int array if the key is found.
    457     *
    458     * @throws ConversionException is thrown if the key maps to an
    459     *         object that is not a list of integers.
    460     */
    461    public int[] getIntArray(final String key, final int[] defaultValue)
    462    {
    463        return get(int[].class, key, defaultValue);
    464    }
    465
    466    /**
    467     * Get a list of Long objects associated with the given configuration key.
    468     * If the key doesn't map to an existing object an empty list is returned.
    469     *
    470     * @param key The configuration key.
    471     * @return The associated Long list if the key is found.
    472     *
    473     * @throws ConversionException is thrown if the key maps to an
    474     *         object that is not a list of longs.
    475     */
    476    public List<Long> getLongList(final String key)
    477    {
    478        return getLongList(key, new ArrayList<Long>());
    479    }
    480
    481    /**
    482     * Get a list of Long objects associated with the given configuration key.
    483     * If the key doesn't map to an existing object, the default value is
    484     * returned.
    485     *
    486     * @param key The configuration key.
    487     * @param defaultValue The default value.
    488     * @return The associated List of Longs.
    489     *
    490     * @throws ConversionException is thrown if the key maps to an
    491     *         object that is not a list of longs.
    492     */
    493    public List<Long> getLongList(final String key, final List<Long> defaultValue)
    494    {
    495        return getList(Long.class, key, defaultValue);
    496    }
    497
    498    /**
    499     * Get an array of long primitives associated with the given
    500     * configuration key. If the key doesn't map to an existing object
    501     * an empty array is returned.
    502     *
    503     * @param key The configuration key.
    504     * @return The associated long array if the key is found.
    505     *
    506     * @throws ConversionException is thrown if the key maps to an
    507     *         object that is not a list of longs.
    508     */
    509    public long[] getLongArray(final String key)
    510    {
    511        return getLongArray(key, new long[0]);
    512    }
    513
    514    /**
    515     * Get an array of long primitives associated with the given
    516     * configuration key. If the key doesn't map to an existing object
    517     * an empty array is returned.
    518     *
    519     * @param key The configuration key.
    520     * @param defaultValue the default value, which will be returned if the property is not found
    521     * @return The associated long array if the key is found.
    522     *
    523     * @throws ConversionException is thrown if the key maps to an
    524     *         object that is not a list of longs.
    525     */
    526    public long[] getLongArray(final String key, final long[] defaultValue)
    527    {
    528        return get(long[].class, key, defaultValue);
    529    }
    530
    531    /**
    532     * Get a list of Float objects associated with the given configuration key.
    533     * If the key doesn't map to an existing object an empty list is returned.
    534     *
    535     * @param key The configuration key.
    536     * @return The associated Float list if the key is found.
    537     *
    538     * @throws ConversionException is thrown if the key maps to an
    539     *         object that is not a list of floats.
    540     */
    541    public List<Float> getFloatList(final String key)
    542    {
    543        return getFloatList(key, new ArrayList<Float>());
    544    }
    545
    546    /**
    547     * Get a list of Float objects associated with the given
    548     * configuration key. If the key doesn't map to an existing object,
    549     * the default value is returned.
    550     *
    551     * @param key The configuration key.
    552     * @param defaultValue The default value.
    553     * @return The associated List of Floats.
    554     *
    555     * @throws ConversionException is thrown if the key maps to an
    556     *         object that is not a list of floats.
    557     */
    558    public List<Float> getFloatList(final String key, final List<Float> defaultValue)
    559    {
    560        return getList(Float.class, key, defaultValue);
    561    }
    562
    563    /**
    564     * Get an array of float primitives associated with the given
    565     * configuration key. If the key doesn't map to an existing object
    566     * an empty array is returned.
    567     *
    568     * @param key The configuration key.
    569     * @return The associated float array if the key is found.
    570     *
    571     * @throws ConversionException is thrown if the key maps to an
    572     *         object that is not a list of floats.
    573     */
    574    public float[] getFloatArray(final String key)
    575    {
    576        return getFloatArray(key, new float[0]);
    577    }
    578
    579    /**
    580     * Get an array of float primitives associated with the given
    581     * configuration key. If the key doesn't map to an existing object
    582     * an empty array is returned.
    583     *
    584     * @param key The configuration key.
    585     * @param defaultValue the default value, which will be returned if the property is not found
    586     * @return The associated float array if the key is found.
    587     *
    588     * @throws ConversionException is thrown if the key maps to an
    589     *         object that is not a list of floats.
    590     */
    591    public float[] getFloatArray(final String key, final float[] defaultValue)
    592    {
    593        return get(float[].class, key, defaultValue);
    594    }
    595
    596    /**
    597     * Get a list of Double objects associated with the given
    598     * configuration key. If the key doesn't map to an existing object
    599     * an empty list is returned.
    600     *
    601     * @param key The configuration key.
    602     * @return The associated Double list if the key is found.
    603     *
    604     * @throws ConversionException is thrown if the key maps to an
    605     *         object that is not a list of doubles.
    606     */
    607    public List<Double> getDoubleList(final String key)
    608    {
    609        return getDoubleList(key, new ArrayList<Double>());
    610    }
    611
    612    /**
    613     * Get a list of Double objects associated with the given
    614     * configuration key. If the key doesn't map to an existing object,
    615     * the default value is returned.
    616     *
    617     * @param key The configuration key.
    618     * @param defaultValue The default value.
    619     * @return The associated List of Doubles.
    620     *
    621     * @throws ConversionException is thrown if the key maps to an
    622     *         object that is not a list of doubles.
    623     */
    624    public List<Double> getDoubleList(final String key, final List<Double> defaultValue)
    625    {
    626        return getList(Double.class, key, defaultValue);
    627    }
    628
    629    /**
    630     * Get an array of double primitives associated with the given
    631     * configuration key. If the key doesn't map to an existing object
    632     * an empty array is returned.
    633     *
    634     * @param key The configuration key.
    635     * @return The associated double array if the key is found.
    636     *
    637     * @throws ConversionException is thrown if the key maps to an
    638     *         object that is not a list of doubles.
    639     */
    640    public double[] getDoubleArray(final String key)
    641    {
    642        return getDoubleArray(key, new double[0]);
    643    }
    644
    645    /**
    646     * Get an array of double primitives associated with the given
    647     * configuration key. If the key doesn't map to an existing object
    648     * an empty array is returned.
    649     *
    650     * @param key The configuration key.
    651     * @param defaultValue the default value, which will be returned if the property is not found
    652     * @return The associated double array if the key is found.
    653     *
    654     * @throws ConversionException is thrown if the key maps to an
    655     *         object that is not a list of doubles.
    656     */
    657    public double[] getDoubleArray(final String key, final double[] defaultValue)
    658    {
    659        return get(double[].class, key, defaultValue);
    660    }
    661
    662    /**
    663     * Get a list of BigIntegers associated with the given configuration key.
    664     * If the key doesn't map to an existing object an empty list is returned.
    665     *
    666     * @param key The configuration key.
    667     * @return The associated BigInteger list if the key is found.
    668     *
    669     * @throws ConversionException is thrown if the key maps to an
    670     *         object that is not a list of BigIntegers.
    671     */
    672    public List<BigInteger> getBigIntegerList(final String key)
    673    {
    674        return getBigIntegerList(key, new ArrayList<BigInteger>());
    675    }
    676
    677    /**
    678     * Get a list of BigIntegers associated with the given configuration key.
    679     * If the key doesn't map to an existing object, the default value is
    680     * returned.
    681     *
    682     * @param key The configuration key.
    683     * @param defaultValue The default value.
    684     * @return The associated List of BigIntegers.
    685     *
    686     * @throws ConversionException is thrown if the key maps to an
    687     *         object that is not a list of BigIntegers.
    688     */
    689    public List<BigInteger> getBigIntegerList(final String key, final List<BigInteger> defaultValue)
    690    {
    691        return getList(BigInteger.class, key, defaultValue);
    692    }
    693
    694    /**
    695     * Get an array of BigIntegers associated with the given
    696     * configuration key. If the key doesn't map to an existing object
    697     * an empty array is returned.
    698     *
    699     * @param key The configuration key.
    700     * @return The associated BigInteger array if the key is found.
    701     *
    702     * @throws ConversionException is thrown if the key maps to an
    703     *         object that is not a list of BigIntegers.
    704     */
    705    public BigInteger[] getBigIntegerArray(final String key)
    706    {
    707        return getBigIntegerArray(key, new BigInteger[0]);
    708    }
    709
    710    /**
    711     * Get an array of BigIntegers associated with the given
    712     * configuration key. If the key doesn't map to an existing object
    713     * an empty array is returned.
    714     *
    715     * @param key The configuration key.
    716     * @param defaultValue the default value, which will be returned if the property is not found
    717     * @return The associated BigInteger array if the key is found.
    718     *
    719     * @throws ConversionException is thrown if the key maps to an
    720     *         object that is not a list of BigIntegers.
    721     */
    722    public BigInteger[] getBigIntegerArray(final String key, final BigInteger[] defaultValue)
    723    {
    724        return get(BigInteger[].class, key, defaultValue);
    725    }
    726
    727    /**
    728     * Get a list of BigDecimals associated with the given configuration key.
    729     * If the key doesn't map to an existing object an empty list is returned.
    730     *
    731     * @param key The configuration key.
    732     * @return The associated BigDecimal list if the key is found.
    733     *
    734     * @throws ConversionException is thrown if the key maps to an
    735     *         object that is not a list of BigDecimals.
    736     */
    737    public List<BigDecimal> getBigDecimalList(final String key)
    738    {
    739        return getBigDecimalList(key, new ArrayList<BigDecimal>());
    740    }
    741
    742    /**
    743     * Get a list of BigDecimals associated with the given configuration key.
    744     * If the key doesn't map to an existing object, the default value is
    745     * returned.
    746     *
    747     * @param key The configuration key.
    748     * @param defaultValue The default value.
    749     * @return The associated List of BigDecimals.
    750     *
    751     * @throws ConversionException is thrown if the key maps to an
    752     *         object that is not a list of BigDecimals.
    753     */
    754    public List<BigDecimal> getBigDecimalList(final String key, final List<BigDecimal> defaultValue)
    755    {
    756        return getList(BigDecimal.class, key, defaultValue);
    757    }
    758
    759    /**
    760     * Get an array of BigDecimals associated with the given
    761     * configuration key. If the key doesn't map to an existing object
    762     * an empty array is returned.
    763     *
    764     * @param key The configuration key.
    765     * @return The associated BigDecimal array if the key is found.
    766     *
    767     * @throws ConversionException is thrown if the key maps to an
    768     *         object that is not a list of BigDecimals.
    769     */
    770    public BigDecimal[] getBigDecimalArray(final String key)
    771    {
    772        return getBigDecimalArray(key, new BigDecimal[0]);
    773    }
    774
    775    /**
    776     * Get an array of BigDecimals associated with the given
    777     * configuration key. If the key doesn't map to an existing object
    778     * an empty array is returned.
    779     *
    780     * @param key The configuration key.
    781     * @param defaultValue the default value, which will be returned if the property is not found
    782     * @return The associated BigDecimal array if the key is found.
    783     *
    784     * @throws ConversionException is thrown if the key maps to an
    785     *         object that is not a list of BigDecimals.
    786     */
    787    public BigDecimal[] getBigDecimalArray(final String key, final BigDecimal[] defaultValue)
    788    {
    789        return get(BigDecimal[].class, key, defaultValue);
    790    }
    791
    792    /**
    793     * Get an URI associated with the given configuration key.
    794     *
    795     * @param key The configuration key.
    796     * @return The associated URI.
    797     *
    798     * @throws ConversionException is thrown if the key maps to an
    799     *         object that is not an URI.
    800     */
    801    public URI getURI(final String key)
    802    {
    803        return get(URI.class, key);
    804    }
    805
    806    /**
    807     * Get an URI associated with the given configuration key.
    808     * If the key doesn't map to an existing object, the default value
    809     * is returned.
    810     *
    811     * @param key          The configuration key.
    812     * @param defaultValue The default value.
    813     * @return The associated URI.
    814     *
    815     * @throws ConversionException is thrown if the key maps to an
    816     *         object that is not an URI.
    817     */
    818    public URI getURI(final String key, final URI defaultValue)
    819    {
    820        return get(URI.class, key, defaultValue);
    821    }
    822
    823    /**
    824     * Get an array of URIs associated with the given configuration key.
    825     * If the key doesn't map to an existing object an empty array is returned.
    826     *
    827     * @param key The configuration key.
    828     * @return The associated URI array if the key is found.
    829     *
    830     * @throws ConversionException is thrown if the key maps to an
    831     *         object that is not a list of URIs.
    832     */
    833    public URI[] getURIArray(final String key)
    834    {
    835        return getURIArray(key, new URI[0]);
    836    }
    837
    838    /**
    839     * Get an array of URIs associated with the given configuration key.
    840     * If the key doesn't map to an existing object an empty array is returned.
    841     *
    842     * @param key The configuration key.
    843     * @param defaultValue the default value, which will be returned if the property is not found
    844     * @return The associated URI array if the key is found.
    845     *
    846     * @throws ConversionException is thrown if the key maps to an
    847     *         object that is not a list of URIs.
    848     */
    849    public URI[] getURIArray(final String key, final URI[] defaultValue)
    850    {
    851        return get(URI[].class, key, defaultValue);
    852    }
    853
    854    /**
    855     * Get a list of URIs associated with the given configuration key.
    856     * If the key doesn't map to an existing object an empty list is returned.
    857     *
    858     * @param key The configuration key.
    859     * @return The associated URI list if the key is found.
    860     *
    861     * @throws ConversionException is thrown if the key maps to an
    862     *         object that is not a list of URIs.
    863     */
    864    public List<URI> getURIList(final String key)
    865    {
    866        return getURIList(key, new ArrayList<URI>());
    867    }
    868
    869    /**
    870     * Get a list of URIs associated with the given configuration key.
    871     * If the key doesn't map to an existing object, the default value is
    872     * returned.
    873     *
    874     * @param key The configuration key.
    875     * @param defaultValue The default value.
    876     * @return The associated List of URIs.
    877     *
    878     * @throws ConversionException is thrown if the key maps to an
    879     *         object that is not a list of URIs.
    880     */
    881    public List<URI> getURIList(final String key, final List<URI> defaultValue)
    882    {
    883        return getList(URI.class, key, defaultValue);
    884    }
    885
    886    /**
    887     * Get an URL associated with the given configuration key.
    888     *
    889     * @param key The configuration key.
    890     * @return The associated URL.
    891     *
    892     * @throws ConversionException is thrown if the key maps to an
    893     *         object that is not an URL.
    894     */
    895    public URL getURL(final String key)
    896    {
    897        return get(URL.class, key);
    898    }
    899
    900    /**
    901     * Get an URL associated with the given configuration key.
    902     * If the key doesn't map to an existing object, the default value
    903     * is returned.
    904     *
    905     * @param key          The configuration key.
    906     * @param defaultValue The default value.
    907     * @return The associated URL.
    908     *
    909     * @throws ConversionException is thrown if the key maps to an
    910     *         object that is not an URL.
    911     */
    912    public URL getURL(final String key, final URL defaultValue)
    913    {
    914        return get(URL.class, key, defaultValue);
    915    }
    916
    917    /**
    918     * Get a list of URLs associated with the given configuration key.
    919     * If the key doesn't map to an existing object an empty list is returned.
    920     *
    921     * @param key The configuration key.
    922     * @return The associated URL list if the key is found.
    923     *
    924     * @throws ConversionException is thrown if the key maps to an
    925     *         object that is not a list of URLs.
    926     */
    927    public List<URL> getURLList(final String key)
    928    {
    929        return getURLList(key, new ArrayList<URL>());
    930    }
    931
    932    /**
    933     * Get a list of URLs associated with the given configuration key.
    934     * If the key doesn't map to an existing object, the default value is
    935     * returned.
    936     *
    937     * @param key The configuration key.
    938     * @param defaultValue The default value.
    939     * @return The associated List of URLs.
    940     *
    941     * @throws ConversionException is thrown if the key maps to an
    942     *         object that is not a list of URLs.
    943     */
    944    public List<URL> getURLList(final String key, final List<URL> defaultValue)
    945    {
    946        return getList(URL.class, key, defaultValue);
    947    }
    948
    949    /**
    950     * Get an array of URLs associated with the given configuration key.
    951     * If the key doesn't map to an existing object an empty array is returned.
    952     *
    953     * @param key The configuration key.
    954     * @return The associated URL array if the key is found.
    955     *
    956     * @throws ConversionException is thrown if the key maps to an
    957     *         object that is not a list of URLs.
    958     */
    959    public URL[] getURLArray(final String key)
    960    {
    961        return getURLArray(key, new URL[0]);
    962    }
    963
    964    /**
    965     * Get an array of URLs associated with the given configuration key.
    966     * If the key doesn't map to an existing object an empty array is returned.
    967     *
    968     * @param key The configuration key.
    969     * @param defaultValue the default value, which will be returned if the property is not found
    970     * @return The associated URL array if the key is found.
    971     *
    972     * @throws ConversionException is thrown if the key maps to an
    973     *         object that is not a list of URLs.
    974     */
    975    public URL[] getURLArray(final String key, final URL[] defaultValue)
    976    {
    977        return get(URL[].class, key, defaultValue);
    978    }
    979
    980    /**
    981     * Get a Date associated with the given configuration key. If the property
    982     * is a String, it will be parsed with the format defined by the user in
    983     * the {@link #DATE_FORMAT_KEY} property, or if it's not defined with the
    984     * {@link #DEFAULT_DATE_FORMAT} pattern.
    985     *
    986     * @param key The configuration key.
    987     * @return The associated Date.
    988     *
    989     * @throws ConversionException is thrown if the key maps to an
    990     *         object that is not a Date.
    991     */
    992    public Date getDate(final String key)
    993    {
    994        return get(Date.class, key);
    995    }
    996
    997    /**
    998     * Get a Date associated with the given configuration key. If the property
    999     * is a String, it will be parsed with the specified format pattern.
    1000     *
    1001     * @param key    The configuration key.
    1002     * @param format The non-localized {@link java.text.DateFormat} pattern.
    1003     * @return The associated Date
    1004     *
    1005     * @throws ConversionException is thrown if the key maps to an
    1006     *         object that is not a Date.
    1007     */
    1008    public Date getDate(final String key, final String format)
    1009    {
    1010        final Date value = getDate(key, null, format);
    1011        if (value != null)
    1012        {
    1013            return value;
    1014        }
    1015        else if (isThrowExceptionOnMissing())
    1016        {
    1017            throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");
    1018        }
    1019        else
    1020        {
    1021            return null;
    1022        }
    1023    }
    1024
    1025    /**
    1026     * Get a Date associated with the given configuration key. If the property
    1027     * is a String, it will be parsed with the format defined by the user in
    1028     * the {@link #DATE_FORMAT_KEY} property, or if it's not defined with the
    1029     * {@link #DEFAULT_DATE_FORMAT} pattern. If the key doesn't map to an
    1030     * existing object, the default value is returned.
    1031     *
    1032     * @param key          The configuration key.
    1033     * @param defaultValue The default value.
    1034     * @return The associated Date.
    1035     *
    1036     * @throws ConversionException is thrown if the key maps to an
    1037     *         object that is not a Date.
    1038     */
    1039    public Date getDate(final String key, final Date defaultValue)
    1040    {
    1041        return getDate(key, defaultValue, null);
    1042    }
    1043
    1044    /**
    1045     * Get a Date associated with the given configuration key. If the property
    1046     * is a String, it will be parsed with the specified format pattern.
    1047     * If the key doesn't map to an existing object, the default value
    1048     * is returned.
    1049     *
    1050     * @param key          The configuration key.
    1051     * @param defaultValue The default value.
    1052     * @param format       The non-localized {@link java.text.DateFormat} pattern.
    1053     * @return The associated Date.
    1054     *
    1055     * @throws ConversionException is thrown if the key maps to an
    1056     *         object that is not a Date.
    1057     */
    1058    public Date getDate(final String key, final Date defaultValue, final String format)
    1059    {
    1060        TEMP_DATE_FORMAT.set(format);
    1061        try
    1062        {
    1063            return get(Date.class, key, defaultValue);
    1064        }
    1065        finally
    1066        {
    1067            TEMP_DATE_FORMAT.remove();
    1068        }
    1069    }
    1070
    1071    public List<Date> getDateList(final String key)
    1072    {
    1073        return getDateList(key, new ArrayList<Date>());
    1074    }
    1075
    1076    /**
    1077     * Get a list of Dates associated with the given configuration key.
    1078     * If the property is a list of Strings, they will be parsed with the
    1079     * specified format pattern. If the key doesn't map to an existing object
    1080     * an empty list is returned.
    1081     *
    1082     * @param key    The configuration key.
    1083     * @param format The non-localized {@link java.text.DateFormat} pattern.
    1084     * @return The associated Date list if the key is found.
    1085     *
    1086     * @throws ConversionException is thrown if the key maps to an
    1087     *         object that is not a list of Dates.
    1088     */
    1089    public List<Date> getDateList(final String key, final String format)
    1090    {
    1091        return getDateList(key, new ArrayList<Date>(), format);
    1092    }
    1093
    1094    /**
    1095     * Get a list of Dates associated with the given configuration key.
    1096     * If the property is a list of Strings, they will be parsed with the
    1097     * format defined by the user in the {@link #DATE_FORMAT_KEY} property,
    1098     * or if it's not defined with the {@link #DEFAULT_DATE_FORMAT} pattern.
    1099     * If the key doesn't map to an existing object, the default value is
    1100     * returned.
    1101     *
    1102     * @param key          The configuration key.
    1103     * @param defaultValue The default value.
    1104     * @return The associated Date list if the key is found.
    1105     *
    1106     * @throws ConversionException is thrown if the key maps to an
    1107     *         object that is not a list of Dates.
    1108     */
    1109    public List<Date> getDateList(final String key, final List<Date> defaultValue)
    1110    {
    1111        return getDateList(key, defaultValue, null);
    1112    }
    1113
    1114    /**
    1115     * Get a list of Dates associated with the given configuration key.
    1116     * If the property is a list of Strings, they will be parsed with the
    1117     * specified format pattern. If the key doesn't map to an existing object,
    1118     * the default value is returned.
    1119     *
    1120     * @param key          The configuration key.
    1121     * @param defaultValue The default value.
    1122     * @param format       The non-localized {@link java.text.DateFormat} pattern.
    1123     * @return The associated Date list if the key is found.
    1124     *
    1125     * @throws ConversionException is thrown if the key maps to an
    1126     *         object that is not a list of Dates.
    1127     */
    1128    public List<Date> getDateList(final String key, final List<Date> defaultValue, final String format)
    1129    {
    1130        TEMP_DATE_FORMAT.set(format);
    1131        try
    1132        {
    1133            return getList(Date.class, key, defaultValue);
    1134        }
    1135        finally
    1136        {
    1137            TEMP_DATE_FORMAT.remove();
    1138        }
    1139    }
    1140
    1141    /**
    1142     * Get an array of Dates associated with the given configuration key.
    1143     * If the property is a list of Strings, they will be parsed with the
    1144     * format defined by the user in the {@link #DATE_FORMAT_KEY} property,
    1145     * or if it's not defined with the {@link #DEFAULT_DATE_FORMAT} pattern.
    1146     * If the key doesn't map to an existing object an empty array is returned.
    1147     *
    1148     * @param key The configuration key.
    1149     * @return The associated Date array if the key is found.
    1150     *
    1151     * @throws ConversionException is thrown if the key maps to an
    1152     *         object that is not a list of Dates.
    1153     */
    1154    public Date[] getDateArray(final String key)
    1155    {
    1156        return getDateArray(key, new Date[0]);
    1157    }
    1158
    1159    /**
    1160     * Get an array of Dates associated with the given configuration key.
    1161     * If the property is a list of Strings, they will be parsed with the
    1162     * specified format pattern. If the key doesn't map to an existing object
    1163     * an empty array is returned.
    1164     *
    1165     * @param key    The configuration key.
    1166     * @param format The non-localized {@link java.text.DateFormat} pattern.
    1167     * @return The associated Date array if the key is found.
    1168     *
    1169     * @throws ConversionException is thrown if the key maps to an
    1170     *         object that is not a list of Dates.
    1171     */
    1172    public Date[] getDateArray(final String key, final String format)
    1173    {
    1174        return getDateArray(key, new Date[0], format);
    1175    }
    1176
    1177    /**
    1178     * Get an array of Dates associated with the given configuration key.
    1179     * If the property is a list of Strings, they will be parsed with the
    1180     * format defined by the user in the {@link #DATE_FORMAT_KEY} property,
    1181     * or if it's not defined with the {@link #DEFAULT_DATE_FORMAT} pattern.
    1182     * If the key doesn't map to an existing object an empty array is returned.
    1183     *
    1184     * @param key The configuration key.
    1185     * @param defaultValue the default value, which will be returned if the property is not found
    1186     * @return The associated Date array if the key is found.
    1187     *
    1188     * @throws ConversionException is thrown if the key maps to an
    1189     *         object that is not a list of Dates.
    1190     */
    1191    public Date[] getDateArray(final String key, final Date[] defaultValue)
    1192    {
    1193        return getDateArray(key, defaultValue, null);
    1194    }
    1195
    1196    /**
    1197     * Get an array of Dates associated with the given configuration key.
    1198     * If the property is a list of Strings, they will be parsed with the
    1199     * specified format pattern. If the key doesn't map to an existing object,
    1200     * the default value is returned.
    1201     *
    1202     * @param key          The configuration key.
    1203     * @param defaultValue The default value.
    1204     * @param format       The non-localized {@link java.text.DateFormat} pattern.
    1205     * @return The associated Date array if the key is found.
    1206     *
    1207     * @throws ConversionException is thrown if the key maps to an
    1208     *         object that is not a list of Dates.
    1209     */
    1210    public Date[] getDateArray(final String key, final Date[] defaultValue, final String format)
    1211    {
    1212        TEMP_DATE_FORMAT.set(format);
    1213        try
    1214        {
    1215            return get(Date[].class, key, defaultValue);
    1216        }
    1217        finally
    1218        {
    1219            TEMP_DATE_FORMAT.remove();
    1220        }
    1221    }
    1222
    1223    /**
    1224     * Get a Calendar associated with the given configuration key. If the
    1225     * property is a String, it will be parsed with the format defined by the
    1226     * user in the {@link #DATE_FORMAT_KEY} property, or if it's not defined
    1227     * with the {@link #DEFAULT_DATE_FORMAT} pattern.
    1228     *
    1229     * @param key The configuration key.
    1230     * @return The associated Calendar.
    1231     *
    1232     * @throws ConversionException is thrown if the key maps to an
    1233     *         object that is not a Calendar.
    1234     */
    1235    public Calendar getCalendar(final String key)
    1236    {
    1237        return get(Calendar.class, key);
    1238    }
    1239
    1240    /**
    1241     * Get a Calendar associated with the given configuration key. If the
    1242     * property is a String, it will be parsed with the specified format
    1243     * pattern.
    1244     *
    1245     * @param key    The configuration key.
    1246     * @param format The non-localized {@link java.text.DateFormat} pattern.
    1247     * @return The associated Calendar
    1248     *
    1249     * @throws ConversionException is thrown if the key maps to an
    1250     *         object that is not a Calendar.
    1251     */
    1252    public Calendar getCalendar(final String key, final String format)
    1253    {
    1254        final Calendar value = getCalendar(key, null, format);
    1255        if (value != null)
    1256        {
    1257            return value;
    1258        }
    1259        else if (isThrowExceptionOnMissing())
    1260        {
    1261            throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");
    1262        }
    1263        else
    1264        {
    1265            return null;
    1266        }
    1267    }
    1268
    1269    /**
    1270     * Get a Calendar associated with the given configuration key. If the
    1271     * property is a String, it will be parsed with the format defined by the
    1272     * user in the {@link #DATE_FORMAT_KEY} property, or if it's not defined
    1273     * with the {@link #DEFAULT_DATE_FORMAT} pattern. If the key doesn't map
    1274     * to an existing object, the default value is returned.
    1275     *
    1276     * @param key          The configuration key.
    1277     * @param defaultValue The default value.
    1278     * @return The associated Calendar.
    1279     *
    1280     * @throws ConversionException is thrown if the key maps to an
    1281     *         object that is not a Calendar.
    1282     */
    1283    public Calendar getCalendar(final String key, final Calendar defaultValue)
    1284    {
    1285        return getCalendar(key, defaultValue, null);
    1286    }
    1287
    1288    /**
    1289     * Get a Calendar associated with the given configuration key. If the
    1290     * property is a String, it will be parsed with the specified format
    1291     * pattern. If the key doesn't map to an existing object, the default
    1292     * value is returned.
    1293     *
    1294     * @param key          The configuration key.
    1295     * @param defaultValue The default value.
    1296     * @param format       The non-localized {@link java.text.DateFormat} pattern.
    1297     * @return The associated Calendar.
    1298     *
    1299     * @throws ConversionException is thrown if the key maps to an
    1300     *         object that is not a Calendar.
    1301     */
    1302    public Calendar getCalendar(final String key, final Calendar defaultValue, final String format)
    1303    {
    1304        TEMP_DATE_FORMAT.set(format);
    1305        try
    1306        {
    1307            return get(Calendar.class, key, defaultValue);
    1308        }
    1309        finally
    1310        {
    1311            TEMP_DATE_FORMAT.remove();
    1312        }
    1313    }
    1314
    1315    /**
    1316     * Get a list of Calendars associated with the given configuration key.
    1317     * If the property is a list of Strings, they will be parsed with the
    1318     * format defined by the user in the {@link #DATE_FORMAT_KEY} property,
    1319     * or if it's not defined with the {@link #DEFAULT_DATE_FORMAT} pattern.
    1320     * If the key doesn't map to an existing object an empty list is returned.
    1321     *
    1322     * @param key The configuration key.
    1323     * @return The associated Calendar list if the key is found.
    1324     *
    1325     * @throws ConversionException is thrown if the key maps to an
    1326     *         object that is not a list of Calendars.
    1327     */
    1328    public List<Calendar> getCalendarList(final String key)
    1329    {
    1330        return getCalendarList(key, new ArrayList<Calendar>());
    1331    }
    1332
    1333    /**
    1334     * Get a list of Calendars associated with the given configuration key.
    1335     * If the property is a list of Strings, they will be parsed with the
    1336     * specified format pattern. If the key doesn't map to an existing object
    1337     * an empty list is returned.
    1338     *
    1339     * @param key    The configuration key.
    1340     * @param format The non-localized {@link java.text.DateFormat} pattern.
    1341     * @return The associated Calendar list if the key is found.
    1342     *
    1343     * @throws ConversionException is thrown if the key maps to an
    1344     *         object that is not a list of Calendars.
    1345     */
    1346    public List<Calendar> getCalendarList(final String key, final String format)
    1347    {
    1348        return getCalendarList(key, new ArrayList<Calendar>(), format);
    1349    }
    1350
    1351    /**
    1352     * Get a list of Calendars associated with the given configuration key.
    1353     * If the property is a list of Strings, they will be parsed with the
    1354     * format defined by the user in the {@link #DATE_FORMAT_KEY} property,
    1355     * or if it's not defined with the {@link #DEFAULT_DATE_FORMAT} pattern.
    1356     * If the key doesn't map to an existing object, the default value is
    1357     * returned.
    1358     *
    1359     * @param key The configuration key.
    1360     * @param defaultValue The default value.
    1361     * @return The associated Calendar list if the key is found.
    1362     *
    1363     * @throws ConversionException is thrown if the key maps to an
    1364     *         object that is not a list of Calendars.
    1365     */
    1366    public List<Calendar> getCalendarList(final String key, final List<Calendar> defaultValue)
    1367    {
    1368        return getCalendarList(key, defaultValue, null);
    1369    }
    1370
    1371    /**
    1372     * Get a list of Calendars associated with the given configuration key.
    1373     * If the property is a list of Strings, they will be parsed with the
    1374     * specified format pattern. If the key doesn't map to an existing object,
    1375     * the default value is returned.
    1376     *
    1377     * @param key          The configuration key.
    1378     * @param defaultValue The default value.
    1379     * @param format       The non-localized {@link java.text.DateFormat} pattern.
    1380     * @return The associated Calendar list if the key is found.
    1381     *
    1382     * @throws ConversionException is thrown if the key maps to an
    1383     *         object that is not a list of Calendars.
    1384     */
    1385    public List<Calendar> getCalendarList(final String key, final List<Calendar> defaultValue, final String format)
    1386    {
    1387        TEMP_DATE_FORMAT.set(format);
    1388        try
    1389        {
    1390            return getList(Calendar.class, key, defaultValue);
    1391        }
    1392        finally
    1393        {
    1394            TEMP_DATE_FORMAT.remove();
    1395        }
    1396    }
    1397
    1398    /**
    1399     * Get an array of Calendars associated with the given configuration key.
    1400     * If the property is a list of Strings, they will be parsed with the
    1401     * format defined by the user in the {@link #DATE_FORMAT_KEY} property,
    1402     * or if it's not defined with the {@link #DEFAULT_DATE_FORMAT} pattern.
    1403     * If the key doesn't map to an existing object an empty array is returned.
    1404     *
    1405     * @param key The configuration key.
    1406     * @return The associated Calendar array if the key is found.
    1407     *
    1408     * @throws ConversionException is thrown if the key maps to an
    1409     *         object that is not a list of Calendars.
    1410     */
    1411    public Calendar[] getCalendarArray(final String key)
    1412    {
    1413        return getCalendarArray(key, new Calendar[0]);
    1414    }
    1415
    1416    /**
    1417     * Get an array of Calendars associated with the given configuration key.
    1418     * If the property is a list of Strings, they will be parsed with the
    1419     * specified format pattern. If the key doesn't map to an existing object
    1420     * an empty array is returned.
    1421     *
    1422     * @param key    The configuration key.
    1423     * @param format The non-localized {@link java.text.DateFormat} pattern.
    1424     * @return The associated Calendar array if the key is found.
    1425     *
    1426     * @throws ConversionException is thrown if the key maps to an
    1427     *         object that is not a list of Calendars.
    1428     */
    1429    public Calendar[] getCalendarArray(final String key, final String format)
    1430    {
    1431        return getCalendarArray(key, new Calendar[0], format);
    1432    }
    1433
    1434    /**
    1435     * Get an array of Calendars associated with the given configuration key.
    1436     * If the property is a list of Strings, they will be parsed with the
    1437     * format defined by the user in the {@link #DATE_FORMAT_KEY} property,
    1438     * or if it's not defined with the {@link #DEFAULT_DATE_FORMAT} pattern.
    1439     * If the key doesn't map to an existing object an empty array is returned.
    1440     *
    1441     * @param key The configuration key.
    1442     * @param defaultValue the default value, which will be returned if the property is not found
    1443     * @return The associated Calendar array if the key is found.
    1444     *
    1445     * @throws ConversionException is thrown if the key maps to an
    1446     *         object that is not a list of Calendars.
    1447     */
    1448    public Calendar[] getCalendarArray(final String key, final Calendar[] defaultValue)
    1449    {
    1450        return getCalendarArray(key, defaultValue, null);
    1451    }
    1452
    1453    /**
    1454     * Get an array of Calendars associated with the given configuration key.
    1455     * If the property is a list of Strings, they will be parsed with the
    1456     * specified format pattern. If the key doesn't map to an existing object,
    1457     * the default value is returned.
    1458     *
    1459     * @param key          The configuration key.
    1460     * @param defaultValue The default value.
    1461     * @param format       The non-localized {@link java.text.DateFormat} pattern.
    1462     * @return The associated Calendar array if the key is found.
    1463     *
    1464     * @throws ConversionException is thrown if the key maps to an
    1465     *         object that is not a list of Calendars.
    1466     */
    1467    public Calendar[] getCalendarArray(final String key, final Calendar[] defaultValue, final String format)
    1468    {
    1469        TEMP_DATE_FORMAT.set(format);
    1470        try
    1471        {
    1472            return get(Calendar[].class, key, defaultValue);
    1473        }
    1474        finally
    1475        {
    1476            TEMP_DATE_FORMAT.remove();
    1477        }
    1478    }
    1479
    1480    /**
    1481     * Returns the date format specified by the user in the DATE_FORMAT_KEY
    1482     * property, or the default format otherwise.
    1483     *
    1484     * @return the default date format
    1485     */
    1486    private String getDefaultDateFormat()
    1487    {
    1488        return getString(DATE_FORMAT_KEY, DEFAULT_DATE_FORMAT);
    1489    }
    1490
    1491    /**
    1492     * Get a Locale associated with the given configuration key.
    1493     *
    1494     * @param key The configuration key.
    1495     * @return The associated Locale.
    1496     *
    1497     * @throws ConversionException is thrown if the key maps to an
    1498     *         object that is not a Locale.
    1499     */
    1500    public Locale getLocale(final String key)
    1501    {
    1502        return get(Locale.class, key);
    1503    }
    1504
    1505    /**
    1506     * Get a Locale associated with the given configuration key.
    1507     * If the key doesn't map to an existing object, the default value
    1508     * is returned.
    1509     *
    1510     * @param key          The configuration key.
    1511     * @param defaultValue The default value.
    1512     * @return The associated Locale.
    1513     *
    1514     * @throws ConversionException is thrown if the key maps to an
    1515     *         object that is not a Locale.
    1516     */
    1517    public Locale getLocale(final String key, final Locale defaultValue)
    1518    {
    1519        return get(Locale.class, key, defaultValue);
    1520    }
    1521
    1522    /**
    1523     * Get a list of Locales associated with the given configuration key.
    1524     * If the key doesn't map to an existing object an empty list is returned.
    1525     *
    1526     * @param key The configuration key.
    1527     * @return The associated Locale list if the key is found.
    1528     *
    1529     * @throws ConversionException is thrown if the key maps to an
    1530     *         object that is not a list of Locales.
    1531     */
    1532    public List<Locale> getLocaleList(final String key)
    1533    {
    1534        return getLocaleList(key, new ArrayList<Locale>());
    1535    }
    1536
    1537    /**
    1538     * Get a list of Locales associated with the given configuration key.
    1539     * If the key doesn't map to an existing object, the default value is
    1540     * returned.
    1541     *
    1542     * @param key The configuration key.
    1543     * @param defaultValue The default value.
    1544     * @return The associated List of Locales.
    1545     *
    1546     * @throws ConversionException is thrown if the key maps to an
    1547     *         object that is not a list of Locales.
    1548     */
    1549    public List<Locale> getLocaleList(final String key, final List<Locale> defaultValue)
    1550    {
    1551        return getList(Locale.class, key, defaultValue);
    1552    }
    1553
    1554    /**
    1555     * Get an array of Locales associated with the given
    1556     * configuration key. If the key doesn't map to an existing object
    1557     * an empty array is returned.
    1558     *
    1559     * @param key The configuration key.
    1560     * @return The associated Locale array if the key is found.
    1561     *
    1562     * @throws ConversionException is thrown if the key maps to an
    1563     *         object that is not a list of Locales.
    1564     */
    1565    public Locale[] getLocaleArray(final String key)
    1566    {
    1567        return getLocaleArray(key, new Locale[0]);
    1568    }
    1569
    1570    /**
    1571     * Get an array of Locales associated with the given
    1572     * configuration key. If the key doesn't map to an existing object
    1573     * an empty array is returned.
    1574     *
    1575     * @param key The configuration key.
    1576     * @param defaultValue the default value, which will be returned if the property is not found
    1577     * @return The associated Locale array if the key is found.
    1578     *
    1579     * @throws ConversionException is thrown if the key maps to an
    1580     *         object that is not a list of Locales.
    1581     */
    1582    public Locale[] getLocaleArray(final String key, final Locale[] defaultValue)
    1583    {
    1584        return get(Locale[].class, key, defaultValue);
    1585    }
    1586
    1587    /**
    1588     * Get a Color associated with the given configuration key.
    1589     *
    1590     * @param key The configuration key.
    1591     * @return The associated Color.
    1592     *
    1593     * @throws ConversionException is thrown if the key maps to an
    1594     *         object that is not a Color.
    1595     */
    1596    public Color getColor(final String key)
    1597    {
    1598        return get(Color.class, key);
    1599    }
    1600
    1601    /**
    1602     * Get a Color associated with the given configuration key.
    1603     * If the key doesn't map to an existing object, the default value
    1604     * is returned.
    1605     *
    1606     * @param key          The configuration key.
    1607     * @param defaultValue The default value.
    1608     * @return The associated Color.
    1609     *
    1610     * @throws ConversionException is thrown if the key maps to an
    1611     *         object that is not a Color.
    1612     */
    1613    public Color getColor(final String key, final Color defaultValue)
    1614    {
    1615        return get(Color.class, key, defaultValue);
    1616    }
    1617
    1618    /**
    1619     * Get a list of Colors associated with the given configuration key.
    1620     * If the key doesn't map to an existing object an empty list is returned.
    1621     *
    1622     * @param key The configuration key.
    1623     * @return The associated Color list if the key is found.
    1624     *
    1625     * @throws ConversionException is thrown if the key maps to an
    1626     *         object that is not a list of Colors.
    1627     */
    1628    public List<Color> getColorList(final String key)
    1629    {
    1630        return getColorList(key, new ArrayList<Color>());
    1631    }
    1632
    1633    /**
    1634     * Get a list of Colors associated with the given configuration key.
    1635     * If the key doesn't map to an existing object, the default value is
    1636     * returned.
    1637     *
    1638     * @param key The configuration key.
    1639     * @param defaultValue The default value.
    1640     * @return The associated List of Colors.
    1641     *
    1642     * @throws ConversionException is thrown if the key maps to an
    1643     *         object that is not a list of Colors.
    1644     */
    1645    public List<Color> getColorList(final String key, final List<Color> defaultValue)
    1646    {
    1647        return getList(Color.class, key, defaultValue);
    1648    }
    1649
    1650    /**
    1651     * Get an array of Colors associated with the given
    1652     * configuration key. If the key doesn't map to an existing object
    1653     * an empty array is returned.
    1654     *
    1655     * @param key The configuration key.
    1656     * @return The associated Color array if the key is found.
    1657     *
    1658     * @throws ConversionException is thrown if the key maps to an
    1659     *         object that is not a list of Colors.
    1660     */
    1661    public Color[] getColorArray(final String key)
    1662    {
    1663        return getColorArray(key, new Color[0]);
    1664    }
    1665
    1666    /**
    1667     * Get an array of Colors associated with the given
    1668     * configuration key. If the key doesn't map to an existing object
    1669     * an empty array is returned.
    1670     *
    1671     * @param key The configuration key.
    1672     * @param defaultValue the default value, which will be returned if the property is not found
    1673     * @return The associated Color array if the key is found.
    1674     *
    1675     * @throws ConversionException is thrown if the key maps to an
    1676     *         object that is not a list of Colors.
    1677     */
    1678    public Color[] getColorArray(final String key, final Color[] defaultValue)
    1679    {
    1680        return get(Color[].class, key, defaultValue);
    1681    }
    1682
    1683    /**
    1684     * Returns the original conversion handler set for this configuration. If
    1685     * this is not a {@code DefaultConversionHandler}, result is <b>null</b>.
    1686     *
    1687     * @return the original conversion handler or <b>null</b>
    1688     */
    1689    private DefaultConversionHandler getOriginalConversionHandler()
    1690    {
    1691        final ConversionHandler handler = super.getConversionHandler();
    1692        return (DefaultConversionHandler) ((handler instanceof DefaultConversionHandler) ? handler
    1693                : null);
    1694    }
    1695
    1696    /**
    1697     * A specialized {@code ConversionHandler} implementation which allows
    1698     * overriding the date format pattern. This class takes care that the format
    1699     * pattern can be defined as a property of the wrapped configuration or
    1700     * temporarily passed when calling a conversion method.
    1701     */
    1702    private class DataConversionHandler extends DefaultConversionHandler
    1703    {
    1704        /**
    1705         * {@inheritDoc} This implementation checks for a defined data format in
    1706         * the following order:
    1707         * <ul>
    1708         * <li>If a temporary date format is set for the current call, it is
    1709         * used.</li>
    1710         * <li>If a date format is specified in this configuration using the
    1711         * {@code DATE_FORMAT_KEY} property, it is used.</li>
    1712         * <li>Otherwise, the date format set for the original conversion
    1713         * handler is used if available.</li>
    1714         * </ul>
    1715         */
    1716        @Override
    1717        public String getDateFormat()
    1718        {
    1719            if (StringUtils.isNotEmpty(TEMP_DATE_FORMAT.get()))
    1720            {
    1721                return TEMP_DATE_FORMAT.get();
    1722            }
    1723            if (containsKey(DATE_FORMAT_KEY))
    1724            {
    1725                return getDefaultDateFormat();
    1726            }
    1727
    1728            final DefaultConversionHandler orgHandler =
    1729                    getOriginalConversionHandler();
    1730            return (orgHandler != null) ? orgHandler.getDateFormat() : null;
    1731        }
    1732    }
    1733}