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 *     https://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 */
017package org.apache.commons.configuration2;
018
019import java.math.BigDecimal;
020import java.math.BigInteger;
021import java.time.Duration;
022import java.util.Collection;
023import java.util.ConcurrentModificationException;
024import java.util.Iterator;
025import java.util.LinkedHashSet;
026import java.util.List;
027import java.util.Map;
028import java.util.NoSuchElementException;
029import java.util.Objects;
030import java.util.Properties;
031import java.util.Set;
032import java.util.function.BiConsumer;
033
034import org.apache.commons.configuration2.convert.PropertyConverter;
035import org.apache.commons.configuration2.ex.ConversionException;
036import org.apache.commons.lang3.tuple.ImmutablePair;
037
038/**
039 * <p>
040 * The main interface for accessing configuration data in a read-only fashion.
041 * </p>
042 * <p>
043 * The major part of the methods defined in this interface deals with accessing properties of various data types. There
044 * is a generic {@code getProperty()} method, which returns the value of the queried property in its raw data type.
045 * Other getter methods try to convert this raw data type into a specific data type. If this fails, a
046 * {@code ConversionException} will be thrown.
047 * </p>
048 * <p>
049 * For most of the property getter methods an overloaded version exists that allows to specify a default value, which
050 * will be returned if the queried property cannot be found in the configuration. The behavior of the methods that do
051 * not take a default value in case of a missing property is not defined by this interface and depends on a concrete
052 * implementation. E.g. the {@link AbstractConfiguration} class, which is the base class of most configuration
053 * implementations provided by this package, per default returns <strong>null</strong> if a property is not found, but provides
054 * the {@link AbstractConfiguration#setThrowExceptionOnMissing(boolean) setThrowExceptionOnMissing()} method, with which
055 * it can be configured to throw a {@code NoSuchElementException} exception in that case. (Note that getter methods for
056 * primitive types in {@code AbstractConfiguration} always throw an exception for missing properties because there is no
057 * way of overloading the return value.)
058 * </p>
059 *
060 * @since 2.0
061 */
062public interface ImmutableConfiguration {
063
064    /**
065     * Checks if the configuration contains the specified key.
066     *
067     * @param key the key whose presence in this configuration is to be tested
068     * @return {@code true} if the configuration contains a value for this key, {@code false} otherwise
069     */
070    boolean containsKey(String key);
071
072    /**
073     * Tests whether this configuration contains one or more matches to this value. This operation stops at first
074     * match but may be more expensive than the {@link #containsKey containsKey} method.
075     *
076     * @param value value whose presence in this configuration is to be tested
077     * @return {@code true} if this configuration maps one or more keys to the specified value, false otherwise.
078     * @since 2.11.0
079     */
080    default boolean containsValue(final Object value) {
081        final Iterator<String> keys = getKeys();
082        while (keys.hasNext()) {
083            if (Objects.equals(value, getProperty(keys.next()))) {
084                return true;
085            }
086        }
087        return false;
088    }
089
090    /**
091     * Returns a {@link Set} view of the mappings contained in this configuration.
092     *
093     * @return a set view of the mappings contained in this configuration.
094     * @since 2.13.0
095     */
096    default Set<Map.Entry<String, Object>> entrySet() {
097        final LinkedHashSet<Map.Entry<String, Object>> set = new LinkedHashSet<>(size());
098        getKeys().forEachRemaining(k -> set.add(ImmutablePair.of(k, getProperty(k))));
099        return set;
100    }
101
102    /**
103     * Performs the given action for each entry in this configuration until all entries have been processed or the action throws an exception. Unless otherwise
104     * specified by the implementing class, actions are performed in the order of entry set iteration (if an iteration order is specified.) Exceptions thrown by
105     * the action are relayed to the caller.
106     *
107     * <pre> {@code
108     * for (Map.Entry<K, V> entry : map.entrySet())
109     *     action.accept(entry.getKey(), entry.getValue());
110     * }</pre>
111     * <p>
112     * The default implementation makes no guarantees about synchronization or atomicity properties of this method. Any implementation providing atomicity
113     * guarantees must override this method and document its concurrency properties.
114     * </p>
115     *
116     * @param action The action to be performed for each entry.
117     * @throws NullPointerException            if the specified action is null.
118     * @throws ConcurrentModificationException if an entry is found to be removed during iteration.
119     * @since 2.13.0
120     */
121    default void forEach(final BiConsumer<String, Object> action) {
122        Objects.requireNonNull(action);
123        for (final Map.Entry<String, Object> entry : entrySet()) {
124            String k;
125            Object v;
126            try {
127                k = entry.getKey();
128                v = entry.getValue();
129            } catch (final IllegalStateException e) {
130                // this usually means the entry is no longer in the map.
131                throw new ConcurrentModificationException(e);
132            }
133            action.accept(k, v);
134        }
135    }
136
137    /**
138     * Gets an object of the specified type associated with the given configuration key. If the key doesn't map to an
139     * existing object, the method returns null unless {@link AbstractConfiguration#isThrowExceptionOnMissing()} is set to
140     * {@code true}.
141     *
142     * @param <T> the target type of the value
143     * @param cls the target class of the value
144     * @param key the key of the value
145     * @return the value of the requested type for the key
146     * @throws java.util.NoSuchElementException if the key doesn't map to an existing object and
147     *         {@code throwExceptionOnMissing=true}
148     * @throws org.apache.commons.configuration2.ex.ConversionException if the value is not compatible with the requested
149     *         type
150     * @since 2.0
151     */
152    <T> T get(Class<T> cls, String key);
153
154    /**
155     * Gets an object of the specified type associated with the given configuration key using a default value. If the key
156     * doesn't map to an existing object, the default value is returned.
157     *
158     * @param <T> the target type of the value
159     * @param cls the target class of the value
160     * @param key the key of the value
161     * @param defaultValue the default value
162     * @return the value of the requested type for the key
163     * @throws org.apache.commons.configuration2.ex.ConversionException if the value is not compatible with the requested
164     *         type
165     *
166     * @since 2.0
167     */
168    <T> T get(Class<T> cls, String key, T defaultValue);
169
170    /**
171     * Gets an array of typed objects associated with the given configuration key. If the key doesn't map to an existing
172     * object, an empty list is returned.
173     *
174     * @param cls the type expected for the elements of the array
175     * @param key The configuration key.
176     * @return The associated array if the key is found, and the value compatible with the type specified.
177     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not
178     *         compatible with a list of the specified class.
179     *
180     * @since 2.0
181     */
182    Object getArray(Class<?> cls, String key);
183
184    /**
185     * Gets an array of typed objects associated with the given configuration key. If the key doesn't map to an existing
186     * object, the default value is returned.
187     *
188     * @param cls the type expected for the elements of the array
189     * @param key the configuration key.
190     * @param defaultValue the default value
191     * @return The associated array if the key is found, and the value compatible with the type specified.
192     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not
193     *         compatible with an array of the specified class.
194     * @throws IllegalArgumentException if the default value is not an array of the specified type
195     * @since 2.0
196     * @deprecated This method should not be used any more because its signature does not allow type-safe invocations; use
197     *             {@link #get(Class, String, Object)} instead which offers the same functionality; for instance, to query
198     *             for an array of ints use {@code int[] result = config.get(int[].class, "myArrayKey", someDefault);}.
199     */
200    @Deprecated
201    Object getArray(Class<?> cls, String key, Object defaultValue);
202
203    /**
204     * Gets a {@link BigDecimal} associated with the given configuration key.
205     *
206     * @param key The configuration key.
207     * @return The associated BigDecimal if key is found and has valid format
208     */
209    BigDecimal getBigDecimal(String key);
210
211    /**
212     * Gets a {@link BigDecimal} associated with the given configuration key. If the key doesn't map to an existing object,
213     * the default value is returned.
214     *
215     * @param key The configuration key.
216     * @param defaultValue The default value.
217     * @return The associated BigDecimal if key is found and has valid format, default value otherwise.
218     */
219    BigDecimal getBigDecimal(String key, BigDecimal defaultValue);
220
221    /**
222     * Gets a {@link BigInteger} associated with the given configuration key.
223     *
224     * @param key The configuration key.
225     * @return The associated BigInteger if key is found and has valid format
226     */
227    BigInteger getBigInteger(String key);
228
229    /**
230     * Gets a {@link BigInteger} associated with the given configuration key. If the key doesn't map to an existing object,
231     * the default value is returned.
232     *
233     * @param key The configuration key.
234     * @param defaultValue The default value.
235     * @return The associated BigInteger if key is found and has valid format, default value otherwise.
236     */
237    BigInteger getBigInteger(String key, BigInteger defaultValue);
238
239    /**
240     * Gets a boolean associated with the given configuration key.
241     *
242     * @param key The configuration key.
243     * @return The associated boolean.
244     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
245     *         Boolean.
246     */
247    boolean getBoolean(String key);
248
249    /**
250     * Gets a boolean associated with the given configuration key. If the key doesn't map to an existing object, the default
251     * value is returned.
252     *
253     * @param key The configuration key.
254     * @param defaultValue The default value.
255     * @return The associated boolean.
256     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
257     *         Boolean.
258     */
259    boolean getBoolean(String key, boolean defaultValue);
260
261    /**
262     * Gets a {@link Boolean} associated with the given configuration key.
263     *
264     * @param key The configuration key.
265     * @param defaultValue The default value.
266     * @return The associated boolean if key is found and has valid format, default value otherwise.
267     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
268     *         Boolean.
269     */
270    Boolean getBoolean(String key, Boolean defaultValue);
271
272    /**
273     * Gets a byte associated with the given configuration key.
274     *
275     * @param key The configuration key.
276     * @return The associated byte.
277     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
278     *         Byte.
279     */
280    byte getByte(String key);
281
282    /**
283     * Gets a byte associated with the given configuration key. If the key doesn't map to an existing object, the default
284     * value is returned.
285     *
286     * @param key The configuration key.
287     * @param defaultValue The default value.
288     * @return The associated byte.
289     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
290     *         Byte.
291     */
292    byte getByte(String key, byte defaultValue);
293
294    /**
295     * Gets a {@link Byte} associated with the given configuration key.
296     *
297     * @param key The configuration key.
298     * @param defaultValue The default value.
299     * @return The associated byte if key is found and has valid format, default value otherwise.
300     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
301     *         Byte.
302     */
303    Byte getByte(String key, Byte defaultValue);
304
305    /**
306     * Gets a collection of typed objects associated with the given configuration key. This method works like
307     * {@link #getCollection(Class, String, Collection, Collection)} passing in <strong>null</strong> as default value.
308     *
309     * @param <T> the element type of the result list
310     * @param cls the element class of the result list
311     * @param key the configuration key
312     * @param target the target collection (may be <strong>null</strong>)
313     * @return the collection to which data was added
314     * @throws org.apache.commons.configuration2.ex.ConversionException if the conversion is not possible
315     * @since 2.0
316     */
317    <T> Collection<T> getCollection(Class<T> cls, String key, Collection<T> target);
318
319    /**
320     * Gets a collection of typed objects associated with the given configuration key using the values in the specified
321     * default collection if the key does not map to an existing object. This method is similar to {@code getList()},
322     * however, it allows specifying a target collection. Results are added to this collection. This is useful if the data
323     * retrieved should be added to a specific kind of collection, for example a set to remove duplicates. The return value is as
324     * follows:
325     * <ul>
326     * <li>If the key does not map to an existing object and the default value is <strong>null</strong>, the method returns
327     * <strong>null</strong>.</li>
328     * <li>If the target collection is not <strong>null</strong> and data has been added (either from the resolved property value or
329     * from the default collection), the target collection is returned.</li>
330     * <li>If the target collection is <strong>null</strong> and data has been added (either from the resolved property value or from
331     * the default collection), return value is the target collection created by this method.</li>
332     * </ul>
333     *
334     * @param <T> the element type of the result list
335     * @param cls the element class of the result list
336     * @param key the configuration key
337     * @param target the target collection (may be <strong>null</strong>)
338     * @param defaultValue the default value (may be <strong>null</strong>)
339     * @return the collection to which data was added
340     * @throws org.apache.commons.configuration2.ex.ConversionException if the conversion is not possible
341     * @since 2.0
342     */
343    <T> Collection<T> getCollection(Class<T> cls, String key, Collection<T> target, Collection<T> defaultValue);
344
345    /**
346     * Gets a double associated with the given configuration key.
347     *
348     * @param key The configuration key.
349     * @return The associated double.
350     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
351     *         Double.
352     */
353    double getDouble(String key);
354
355    /**
356     * Gets a double associated with the given configuration key. If the key doesn't map to an existing object, the default
357     * value is returned.
358     *
359     * @param key The configuration key.
360     * @param defaultValue The default value.
361     * @return The associated double.
362     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
363     *         Double.
364     */
365    double getDouble(String key, double defaultValue);
366
367    /**
368     * Gets a {@link Double} associated with the given configuration key.
369     *
370     * @param key The configuration key.
371     * @param defaultValue The default value.
372     * @return The associated double if key is found and has valid format, default value otherwise.
373     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
374     *         Double.
375     */
376    Double getDouble(String key, Double defaultValue);
377
378    /**
379     * Gets a {@link Duration} associated with the given configuration key.
380     *
381     * @param key The configuration key.
382     * @return The associated Duration if key is found and has valid format, default value otherwise.
383     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
384     *         Duration.
385     * @since 2.8.0
386     */
387    default Duration getDuration(final String key) {
388        final String string = getString(key);
389        if (string == null) {
390            throw new NoSuchElementException(key);
391        }
392        return PropertyConverter.toDuration(string);
393    }
394
395    /**
396     * Gets a {@link Duration} associated with the given configuration key.
397     *
398     * @param key The configuration key.
399     * @param defaultValue The default value.
400     * @return The associated Duration if key is found and has valid format, default value otherwise.
401     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
402     *         Duration.
403     * @since 2.8.0
404     */
405    default Duration getDuration(final String key, final Duration defaultValue) {
406        final Object value = getProperty(key);
407        return value == null ? defaultValue : PropertyConverter.toDuration(value);
408    }
409
410    /**
411     * Gets the value of a string property that is stored in encoded form in this configuration using a default
412     * {@code ConfigurationDecoder}. This method works like the method with the same name, but it uses a default
413     * {@code ConfigurationDecoder} associated with this configuration. It depends on a specific implementation how this
414     * default decoder is obtained.
415     *
416     * @param key the configuration key
417     * @return the plain string value of the specified encoded property
418     */
419    String getEncodedString(String key);
420
421    /**
422     * Gets the value of a string property that is stored in encoded form in this configuration. This method obtains the
423     * value of the string property identified by the given key. This value is then passed to the provided
424     * {@code ConfigurationDecoder}. The value returned by the {@code ConfigurationDecoder} is passed to the caller. If the
425     * key is not associated with a value, the decoder is not invoked; depending on this configuration's settings either
426     * <strong>null</strong> is returned or an exception is thrown.
427     *
428     * @param key the configuration key
429     * @param decoder the {@code ConfigurationDecoder} (must not be <strong>null</strong>)
430     * @return the plain string value of the specified encoded property
431     * @throws IllegalArgumentException if a <strong>null</strong> decoder is passed
432     */
433    String getEncodedString(String key, ConfigurationDecoder decoder);
434
435    /**
436     * Gets an enum associated with the given configuration key.
437     *
438     * @param <T> The enum type whose constant is to be returned.
439     * @param enumType the {@code Class} object of the enum type from which to return a constant
440     * @param key The configuration key.
441     * @return The associated enum.
442     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
443     *         String.
444     * @since 2.8.0
445     */
446    default <T extends Enum<T>> T getEnum(final String key, final Class<T> enumType) {
447        try {
448            return Enum.valueOf(enumType, getString(key));
449        } catch (final IllegalArgumentException e) {
450            throw new ConversionException(e);
451        }
452    }
453
454    /**
455     * Gets the enum associated with the given configuration key. If the key doesn't map to an existing object, the default
456     * value is returned.
457     *
458     * @param <T> The enum type whose constant is to be returned.
459     * @param key The configuration key.
460     * @param enumType the {@code Class} object of the enum type from which to return a constant
461     * @param defaultValue The default value.
462     * @return The associated enum if key is found and has valid format, default value otherwise.
463     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
464     *         Enum.
465     * @since 2.8.0
466     */
467    default <T extends Enum<T>> T getEnum(final String key, final Class<T> enumType, final T defaultValue) {
468        final String strValue = getString(key, null);
469        if (strValue == null) {
470            return defaultValue;
471        }
472        try {
473            return Enum.valueOf(enumType, strValue);
474        } catch (final IllegalArgumentException e) {
475            throw new ConversionException(e);
476        }
477    }
478
479    /**
480     * Gets a float associated with the given configuration key.
481     *
482     * @param key The configuration key.
483     * @return The associated float.
484     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
485     *         Float.
486     */
487    float getFloat(String key);
488
489    /**
490     * Gets a float associated with the given configuration key. If the key doesn't map to an existing object, the default
491     * value is returned.
492     *
493     * @param key The configuration key.
494     * @param defaultValue The default value.
495     * @return The associated float.
496     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
497     *         Float.
498     */
499    float getFloat(String key, float defaultValue);
500
501    /**
502     * Gets a {@link Float} associated with the given configuration key. If the key doesn't map to an existing object, the
503     * default value is returned.
504     *
505     * @param key The configuration key.
506     * @param defaultValue The default value.
507     * @return The associated float if key is found and has valid format, default value otherwise.
508     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
509     *         Float.
510     */
511    Float getFloat(String key, Float defaultValue);
512
513    /**
514     * Gets a int associated with the given configuration key.
515     *
516     * @param key The configuration key.
517     * @return The associated int.
518     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
519     *         Integer.
520     */
521    int getInt(String key);
522
523    /**
524     * Gets a int associated with the given configuration key. If the key doesn't map to an existing object, the default
525     * value is returned.
526     *
527     * @param key The configuration key.
528     * @param defaultValue The default value.
529     * @return The associated int.
530     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
531     *         Integer.
532     */
533    int getInt(String key, int defaultValue);
534
535    /**
536     * Gets an {@link Integer} associated with the given configuration key. If the key doesn't map to an existing object,
537     * the default value is returned.
538     *
539     * @param key The configuration key.
540     * @param defaultValue The default value.
541     * @return The associated int if key is found and has valid format, default value otherwise.
542     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
543     *         Integer.
544     */
545    Integer getInteger(String key, Integer defaultValue);
546
547    /**
548     * Gets the list of the keys contained in the configuration. The returned iterator can be used to obtain all defined
549     * keys. It does not allow removing elements from this configuration via its {@code remove()} method. Note that the keys
550     * of this configuration are returned in a form, so that they can be directly evaluated; escaping of special characters
551     * (if necessary) has already been performed.
552     *
553     * @return An Iterator.
554     */
555    Iterator<String> getKeys();
556
557    /**
558     * Gets the list of the keys contained in the configuration that match the specified prefix.
559     * <p>
560     * For instance, if the configuration contains the following keys:
561     * </p>
562     * <pre>
563     * db.user, db.pwd, db.url, window.xpos, window.ypos
564     * </pre>
565     * <p>
566     * The expression {@code getKeys("db")} will return:
567     * </p>
568     *
569     * <pre>
570     * db.user, db.pwd, db.url
571     * </pre>
572     * <p>
573     * Note that the prefix itself is included in the result set if there is a matching key. The exact behavior - how the prefix is actually interpreted -
574     * depends on a concrete implementation.
575     * </p>
576     *
577     * @param prefix The prefix to test against.
578     * @return An Iterator of keys that match the prefix.
579     * @see #getKeys()
580     */
581    Iterator<String> getKeys(String prefix);
582
583    /**
584     * Gets the list of the keys contained in the configuration that match the specified prefix.
585     * <p>
586     * For instance, if the configuration contains the following keys:
587     * </p>
588     *
589     * <pre>
590     * db@user, db@pwd, db@url, window.xpos, window.ypos
591     * </pre>
592     * <p>
593     * The expression {@code getKeys("db","@")} will return:
594     * </p>
595     *
596     * <pre>
597     * db@user, db@pwd, db@url
598     * </pre>
599     * <p>
600     * Note that the prefix itself is included in the result set if there is a matching key. The exact behavior - how the prefix is actually interpreted -
601     * depends on a concrete implementation.
602     * </p>
603     *
604     * @param prefix    The prefix to test against.
605     * @param delimiter The prefix delimiter.
606     * @return An Iterator of keys that match the prefix.
607     * @see #getKeys()
608     * @since 2.10.0
609     */
610    default Iterator<String> getKeys(final String prefix, final String delimiter) {
611        return null;
612    }
613
614    /**
615     * Gets a list of typed objects associated with the given configuration key returning a null if the key doesn't map to
616     * an existing object.
617     *
618     * @param <T> the type expected for the elements of the list
619     * @param cls the class expected for the elements of the list
620     * @param key The configuration key.
621     * @return The associated list if the key is found.
622     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not
623     *         compatible with a list of the specified class.
624     *
625     * @since 2.0
626     */
627    <T> List<T> getList(Class<T> cls, String key);
628
629    /**
630     * Gets a list of typed objects associated with the given configuration key returning the specified default value if the
631     * key doesn't map to an existing object. This method recursively retrieves all values stored for the passed in key,
632     * i.e. if one of these values is again a complex object like an array or a collection (which may be the case for some
633     * concrete subclasses), all values are extracted and added to the resulting list - performing a type conversion if
634     * necessary.
635     *
636     * @param <T> the type expected for the elements of the list
637     * @param cls the class expected for the elements of the list
638     * @param key the configuration key.
639     * @param defaultValue the default value.
640     * @return The associated List.
641     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not
642     *         compatible with a list of the specified class.
643     *
644     * @since 2.0
645     */
646    <T> List<T> getList(Class<T> cls, String key, List<T> defaultValue);
647
648    /**
649     * Gets a List of the values associated with the given configuration key. This method is different from the generic
650     * {@code getList()} method in that it does not recursively obtain all values stored for the specified property key.
651     * Rather, only the first level of the hierarchy is processed. So the resulting list may contain complex objects like
652     * arrays or collections - depending on the storage structure used by a concrete subclass. If the key doesn't map to an
653     * existing object, an empty List is returned.
654     *
655     * @param key The configuration key.
656     * @return The associated List.
657     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
658     *         List.
659     */
660    List<Object> getList(String key);
661
662    /**
663     * Gets a List of strings associated with the given configuration key. If the key doesn't map to an existing object, the
664     * default value is returned.
665     *
666     * @param key The configuration key.
667     * @param defaultValue The default value.
668     * @return The associated List of strings.
669     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
670     *         List.
671     * @see #getList(Class, String, List)
672     */
673    List<Object> getList(String key, List<?> defaultValue);
674
675    /**
676     * Gets a long associated with the given configuration key.
677     *
678     * @param key The configuration key.
679     * @return The associated long.
680     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
681     *         Long.
682     */
683    long getLong(String key);
684
685    /**
686     * Gets a long associated with the given configuration key. If the key doesn't map to an existing object, the default
687     * value is returned.
688     *
689     * @param key The configuration key.
690     * @param defaultValue The default value.
691     * @return The associated long.
692     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
693     *         Long.
694     */
695    long getLong(String key, long defaultValue);
696
697    /**
698     * Gets a {@link Long} associated with the given configuration key. If the key doesn't map to an existing object, the
699     * default value is returned.
700     *
701     * @param key The configuration key.
702     * @param defaultValue The default value.
703     * @return The associated long if key is found and has valid format, default value otherwise.
704     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
705     *         Long.
706     */
707    Long getLong(String key, Long defaultValue);
708
709    /**
710     * Gets a list of properties associated with the given configuration key. This method expects the given key to have an
711     * arbitrary number of String values, each of which is of the form {@code key=value}. These strings are split at the
712     * equals sign, and the key parts will become keys of the returned {@code Properties} object, the value parts become
713     * values.
714     *
715     * @param key The configuration key.
716     * @return The associated properties if key is found.
717     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
718     *         String/List.
719     * @throws IllegalArgumentException if one of the tokens is malformed (does not contain an equals sign).
720     */
721    Properties getProperties(String key);
722
723    /**
724     * Gets a property from the configuration. This is the most basic get method for retrieving values of properties. In a
725     * typical implementation of the {@code Configuration} interface the other get methods (that return specific data types)
726     * will internally make use of this method. On this level variable substitution is not yet performed. The returned
727     * object is an internal representation of the property value for the passed in key. It is owned by the
728     * {@code Configuration} object. So a caller should not modify this object. It cannot be guaranteed that this object
729     * will stay constant over time (i.e. further update operations on the configuration may change its internal state).
730     *
731     * @param key property to retrieve
732     * @return the value to which this configuration maps the specified key, or null if the configuration contains no
733     *         mapping for this key.
734     */
735    Object getProperty(String key);
736
737    /**
738     * Gets a short associated with the given configuration key.
739     *
740     * @param key The configuration key.
741     * @return The associated short.
742     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
743     *         Short.
744     */
745    short getShort(String key);
746
747    /**
748     * Gets a short associated with the given configuration key.
749     *
750     * @param key The configuration key.
751     * @param defaultValue The default value.
752     * @return The associated short.
753     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
754     *         Short.
755     */
756    short getShort(String key, short defaultValue);
757
758    /**
759     * Gets a {@link Short} associated with the given configuration key. If the key doesn't map to an existing object, the
760     * default value is returned.
761     *
762     * @param key The configuration key.
763     * @param defaultValue The default value.
764     * @return The associated short if key is found and has valid format, default value otherwise.
765     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
766     *         Short.
767     */
768    Short getShort(String key, Short defaultValue);
769
770    /**
771     * Gets a string associated with the given configuration key.
772     *
773     * @param key The configuration key.
774     * @return The associated string.
775     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
776     *         String.
777     */
778    String getString(String key);
779
780    /**
781     * Gets a string associated with the given configuration key. If the key doesn't map to an existing object, the default
782     * value is returned.
783     *
784     * @param key The configuration key.
785     * @param defaultValue The default value.
786     * @return The associated string if key is found and has valid format, default value otherwise.
787     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
788     *         String.
789     */
790    String getString(String key, String defaultValue);
791
792    /**
793     * Gets an array of strings associated with the given configuration key. If the key doesn't map to an existing object an
794     * empty array is returned
795     *
796     * @param key The configuration key.
797     * @return The associated string array if key is found.
798     * @throws org.apache.commons.configuration2.ex.ConversionException is thrown if the key maps to an object that is not a
799     *         String/List of Strings.
800     */
801    String[] getStringArray(String key);
802
803    /**
804     * Return a decorator immutable Configuration containing every key from the current Configuration that starts with the
805     * specified prefix. The prefix is removed from the keys in the subset. For example, if the configuration contains the
806     * following properties:
807     *
808     * <pre>
809     *    prefix.number = 1
810     *    prefix.string = Apache
811     *    prefixed.foo = bar
812     *    prefix = Jakarta
813     * </pre>
814     *
815     * the immutable Configuration returned by {@code subset("prefix")} will contain the properties:
816     *
817     * <pre>
818     *    number = 1
819     *    string = Apache
820     *    = Jakarta
821     * </pre>
822     *
823     * (The key for the value "Jakarta" is an empty string)
824     *
825     * @param prefix The prefix used to select the properties.
826     * @return a subset immutable configuration
827     */
828    ImmutableConfiguration immutableSubset(String prefix);
829
830    /**
831     * Checks if the configuration is empty.
832     *
833     * @return {@code true} if the configuration contains no property, {@code false} otherwise.
834     */
835    boolean isEmpty();
836
837    /**
838     * Returns the number of keys stored in this configuration. Note that a concrete implementation is not guaranteed to be
839     * efficient; for some implementations it may be expensive to determine the size. Especially, if you just want to check
840     * whether a configuration is empty, it is preferable to use the {@link #isEmpty()} method.
841     *
842     * @return the number of keys stored in this configuration
843     */
844    int size();
845
846}