Package org.apache.commons.configuration2

# Class AbstractConfiguration

java.lang.Object
org.apache.commons.configuration2.event.BaseEventSource
org.apache.commons.configuration2.AbstractConfiguration

All Implemented Interfaces:
  `Configuration`, `EventSource`, `ImmutableConfiguration`, `SynchronizerSupport`

Direct Known Subclasses:
  `AbstractHierarchicalConfiguration`, `AppletConfiguration`, `BaseConfiguration`, `CompositeConfiguration`, `DatabaseConfiguration`, `DataConfiguration`, `JNDIConfiguration`, `MapConfiguration`, `ServletConfiguration`, `ServletContextConfiguration`, `ServletFilterConfiguration`, `ServletRequestConfiguration`, `SubsetConfiguration`

public abstract class AbstractConfiguration extends BaseEventSource implements Configuration

Abstract configuration class. Provides basic functionality but does not store any data.

If you want to write your own Configuration class then you should implement only abstract methods from this class. A lot of functionality needed by typical implementations of the `Configuration` interface is already provided by this base class. Following is a list of features implemented here:

- Data conversion support. The various data types required by the `Configuration` interface are already handled by this base class. A concrete sub class only needs to provide a generic `getProperty()` method.
- Support for variable interpolation. Property values containing special variable tokens (like `${var}`) will be replaced by their corresponding values.
- Optional support for string lists. The values of properties to be added to this configuration are checked whether they contain a list delimiter character. If this is the case and if list splitting is enabled, the string is split and multiple values are added for this property. List splitting is controlled by a `ListDelimiterHandler` object which can be set using the `setListDelimiterHandler(ListDelimiterHandler)` method. It is disabled per default. To enable this feature, set a suitable `ListDelimiterHandler`, e.g. an instance of `DefaultListDelimiterHandler` configured with the desired list delimiter character.
- Allows specifying how missing properties are treated. Per default the get methods returning an object will return null if the searched property key is not found (and no default value is provided). With the `setThrowExceptionOnMissing()` method this behavior can be changed to throw an exception when a requested property cannot be found.
- Basic event support. Whenever this configuration is modified registered event listeners are notified. Refer to the various `EVENT_XXX` constants to get an impression about which event types are supported.
- Support for proper synchronization based on the `Synchronizer` interface.

Most methods defined by the `Configuration` interface are already implemented in this class. Many method implementations perform basic book-keeping tasks (e.g. firing events, handling synchronization), and then delegate to other (protected) methods executing the actual work. Subclasses override these protected methods to define or adapt behavior. The public entry point methods are final to prevent subclasses from breaking basic functionality.

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `AbstractConfiguration()`
  Creates a new instance of `AbstractConfiguration`.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `final void`
  `addErrorLogListener()`
  Adds a special `EventListener` object to this configuration that will log all internal errors.
  `final void`
  `addProperty(String key, Object value)`
  Add a property to the configuration.
  `protected abstract void`
  `addPropertyDirect(String key, Object value)`
  Adds a key/value pair to the Configuration.
  `protected void`
  `addPropertyInternal(String key, Object value)`
  Actually adds a property to this configuration.
  `void`
  `append(Configuration c)`
  Appends the content of the specified configuration to this configuration.
  `protected void`
  `beginRead(boolean optimize)`
  Notifies this configuration's `Synchronizer` that a read operation is about to start.
  `protected void`
  `beginWrite(boolean optimize)`
  Notifies this configuration's `Synchronizer` that an update operation is about to start.
  `final void`
  `clear()`
  Remove all properties from the configuration.
  `protected void`
  `clearInternal()`
  Clears the whole configuration.
  `final void`
  `clearProperty(String key)`
  Removes the specified property from this configuration.
  `protected abstract void`
  `clearPropertyDirect(String key)`
  Removes the specified property from this configuration.
  `protected void`
  `cloneInterpolator(AbstractConfiguration orgConfig)`
  Creates a clone of the `ConfigurationInterpolator` used by this instance.
  `final boolean`
  `containsKey(String key)`
  Checks if the configuration contains the specified key.
  `protected abstract boolean`
  `containsKeyInternal(String key)`
  Actually checks whether the specified key is contained in this configuration.
  `void`
  `copy(Configuration c)`
  Copies the content of the specified configuration into this configuration.
  `protected void`
  `endRead()`
  Notifies this configuration's `Synchronizer` that a read operation has finished.
  `protected void`
  `endWrite()`
  Notifies this configuration's `Synchronizer` that an update operation has finished.
  `<T> T`
  `get(Class<T> cls, String key)`
  Gets an object of the specified type associated with the given configuration key.
  `<T> T`
  `get(Class<T> cls, String key, T defaultValue)`
  Gets an object of the specified type associated with the given configuration key using a default value.
  `Object`
  `getArray(Class<?> cls, String key)`
  Gets an array of typed objects associated with the given configuration key.
  `Object`
  `getArray(Class<?> cls, String key, Object defaultValue)`
  Gets an array of typed objects associated with the given configuration key.
  `BigDecimal`
  `getBigDecimal(String key)`
  Gets a `BigDecimal` associated with the given configuration key.
  `BigDecimal`
  `getBigDecimal(String key, BigDecimal defaultValue)`
  Gets a `BigDecimal` associated with the given configuration key.
  `BigInteger`
  `getBigInteger(String key)`
  Gets a `BigInteger` associated with the given configuration key.
  `BigInteger`
  `getBigInteger(String key, BigInteger defaultValue)`
  Gets a `BigInteger` associated with the given configuration key.
  `boolean`
  `getBoolean(String key)`
  Gets a boolean associated with the given configuration key.
  `boolean`
  `getBoolean(String key, boolean defaultValue)`
  Gets a boolean associated with the given configuration key.
  `Boolean`
  `getBoolean(String key, Boolean defaultValue)`
  Obtains the value of the specified key and tries to convert it into a `Boolean` object.
  `byte`
  `getByte(String key)`
  Gets a byte associated with the given configuration key.
  `byte`
  `getByte(String key, byte defaultValue)`
  Gets a byte associated with the given configuration key.
  `Byte`
  `getByte(String key, Byte defaultValue)`
  Gets a `Byte` associated with the given configuration key.
  `<T> Collection<T>`
  `getCollection(Class<T> cls, String key, Collection<T> target)`
  Gets a collection of typed objects associated with the given configuration key.
  `<T> Collection<T>`
  `getCollection(Class<T> cls, String key, Collection<T> target, Collection<T> defaultValue)`
  Gets a collection of typed objects associated with the given configuration key using the values in the specified default collection if the key does not map to an existing object.
  `ConfigurationDecoder`
  `getConfigurationDecoder()`
  Gets the `ConfigurationDecoder` used by this instance.
  `ConversionHandler`
  `getConversionHandler()`
  Gets the `ConversionHandler` used by this instance.
  `double`
  `getDouble(String key)`
  Gets a double associated with the given configuration key.
  `double`
  `getDouble(String key, double defaultValue)`
  Gets a double associated with the given configuration key.
  `Double`
  `getDouble(String key, Double defaultValue)`
  Gets a `Double` associated with the given configuration key.
  `Duration`
  `getDuration(String key)`
  Gets a `Duration` associated with the given configuration key.
  `Duration`
  `getDuration(String key, Duration defaultValue)`
  Gets a `Duration` associated with the given configuration key.
  `String`
  `getEncodedString(String key)`
  Gets the value of a string property that is stored in encoded form in this configuration using a default `ConfigurationDecoder`.
  `String`
  `getEncodedString(String key, ConfigurationDecoder decoder)`
  Gets the value of a string property that is stored in encoded form in this configuration.
  `float`
  `getFloat(String key)`
  Gets a float associated with the given configuration key.
  `float`
  `getFloat(String key, float defaultValue)`
  Gets a float associated with the given configuration key.
  `Float`
  `getFloat(String key, Float defaultValue)`
  Gets a `Float` associated with the given configuration key.
  `int`
  `getInt(String key)`
  Gets a int associated with the given configuration key.
  `int`
  `getInt(String key, int defaultValue)`
  Gets a int associated with the given configuration key.
  `Integer`
  `getInteger(String key, Integer defaultValue)`
  Gets an `Integer` associated with the given configuration key.
  `ConfigurationInterpolator`
  `getInterpolator()`
  Gets the `ConfigurationInterpolator` object that manages the lookup objects for resolving variables.
  `final Iterator<String>`
  `getKeys()`
  Gets the list of the keys contained in the configuration.
  `final Iterator<String>`
  `getKeys(String prefix)`
  Gets the list of the keys contained in the configuration that match the specified prefix.
  `final Iterator<String>`
  `getKeys(String prefix, String delimiter)`
  Gets the list of the keys contained in the configuration that match the specified prefix.
  `protected abstract Iterator<String>`
  `getKeysInternal()`
  Actually creates an iterator for iterating over the keys in this configuration.
  `protected Iterator<String>`
  `getKeysInternal(String prefix)`
  Gets an `Iterator` with all property keys starting with the specified prefix.
  `protected Iterator<String>`
  `getKeysInternal(String prefix, String delimiter)`
  Gets an `Iterator` with all property keys starting with the specified prefix and specified delimiter.
  `<T> List<T>`
  `getList(Class<T> cls, String key)`
  Gets a list of typed objects associated with the given configuration key returning a null if the key doesn't map to an existing object.
  `<T> List<T>`
  `getList(Class<T> cls, String key, List<T> defaultValue)`
  Gets a list of typed objects associated with the given configuration key returning the specified default value if the key doesn't map to an existing object.
  `List<Object>`
  `getList(String key)`
  Gets a List of the values associated with the given configuration key.
  `List<Object>`
  `getList(String key, List<?> defaultValue)`
  Gets a List of strings associated with the given configuration key.
  `ListDelimiterHandler`
  `getListDelimiterHandler()`
  Gets the `ListDelimiterHandler` used by this instance.
  `ConfigurationLogger`
  `getLogger()`
  Gets the logger used by this configuration object.
  `long`
  `getLong(String key)`
  Gets a long associated with the given configuration key.
  `long`
  `getLong(String key, long defaultValue)`
  Gets a long associated with the given configuration key.
  `Long`
  `getLong(String key, Long defaultValue)`
  Gets a `Long` associated with the given configuration key.
  `Properties`
  `getProperties(String key)`
  Gets a list of properties associated with the given configuration key.
  `Properties`
  `getProperties(String key, Properties defaults)`
  Gets a list of properties associated with the given configuration key.
  `final Object`
  `getProperty(String key)`
  Gets a property from the configuration.
  `protected abstract Object`
  `getPropertyInternal(String key)`
  Actually obtains the value of the specified property.
  `short`
  `getShort(String key)`
  Gets a short associated with the given configuration key.
  `short`
  `getShort(String key, short defaultValue)`
  Gets a short associated with the given configuration key.
  `Short`
  `getShort(String key, Short defaultValue)`
  Gets a `Short` associated with the given configuration key.
  `String`
  `getString(String key)`
  Gets a string associated with the given configuration key.
  `String`
  `getString(String key, String defaultValue)`
  Gets a string associated with the given configuration key.
  `String[]`
  `getStringArray(String key)`
  Gets an array of strings associated with the given configuration key.
  `final Synchronizer`
  `getSynchronizer()`
  Gets the object responsible for synchronizing this configuration.
  `ImmutableConfiguration`
  `immutableSubset(String prefix)`
  Return a decorator immutable Configuration containing every key from the current Configuration that starts with the specified prefix.
  `protected final void`
  `initLogger(ConfigurationLogger log)`
  Initializes the logger.
  `final void`
  `installInterpolator(Map<String,? extends Lookup> prefixLookups, Collection<? extends Lookup> defLookups)`
  Creates and installs a new `ConfigurationInterpolator` for this `Configuration` based on the passed in arguments.
  `protected Object`
  `interpolate(Object value)`
  Returns the interpolated value.
  `protected String`
  `interpolate(String base)`
  interpolate key names to handle ${key} stuff
  `Configuration`
  `interpolatedConfiguration()`
  Returns a configuration with the same content as this configuration, but with all variables replaced by their actual values.
  `final boolean`
  `isEmpty()`
  Checks if the configuration is empty.
  `protected abstract boolean`
  `isEmptyInternal()`
  Actually checks whether this configuration contains data.
  `protected boolean`
  `isScalarValue(Object value)`
  Checks whether the specified object is a scalar value.
  `boolean`
  `isThrowExceptionOnMissing()`
  Returns true if missing values throw Exceptions.
  `final void`
  `lock(LockMode mode)`
  Locks this object for the specified mode.
  `void`
  `setConfigurationDecoder(ConfigurationDecoder configurationDecoder)`
  Sets the `ConfigurationDecoder` for this configuration.
  `void`
  `setConversionHandler(ConversionHandler conversionHandler)`
  Sets the `ConversionHandler` to be used by this instance.
  `void`
  `setDefaultLookups(Collection<? extends Lookup> lookups)`
  Adds all `Lookup` objects in the given collection as default lookups (i.e.
  `final void`
  `setInterpolator(ConfigurationInterpolator ci)`
  Sets the `ConfigurationInterpolator` object to be used by this `Configuration`.
  `void`
  `setListDelimiterHandler(ListDelimiterHandler listDelimiterHandler)`
  Sets the `ListDelimiterHandler` to be used by this instance.
  `void`
  `setLogger(ConfigurationLogger log)`
  Allows setting the logger to be used by this configuration object.
  `void`
  `setParentInterpolator(ConfigurationInterpolator parent)`
  Sets the specified `ConfigurationInterpolator` as the parent of this configuration's `ConfigurationInterpolator`.
  `void`
  `setPrefixLookups(Map<String,? extends Lookup> lookups)`
  Registers all `Lookup` objects in the given map at the current `ConfigurationInterpolator` of this configuration.
  `final void`
  `setProperty(String key, Object value)`
  Sets a property, this will replace any previously set values.
  `protected void`
  `setPropertyInternal(String key, Object value)`
  Actually sets the value of a property.
  `final void`
  `setSynchronizer(Synchronizer synchronizer)`
  Sets the object responsible for synchronizing this configuration.
  `void`
  `setThrowExceptionOnMissing(boolean throwExceptionOnMissing)`
  Allows to set the `throwExceptionOnMissing` flag.
  `final int`
  `size()`
  Returns the number of keys stored in this configuration.
  `protected int`
  `sizeInternal()`
  Actually calculates the size of this configuration.
  `Configuration`
  `subset(String prefix)`
  Return a decorator Configuration containing every key from the current Configuration that starts with the specified prefix.
  `final void`
  `unlock(LockMode mode)`
  Releases a lock of this object that was obtained using the `SynchronizerSupport.lock(LockMode)` method.

  ### Methods inherited from class org.apache.commons.configuration2.event.BaseEventSource

  `addEventListener, clearErrorListeners, clearEventListeners, clone, copyEventListeners, createErrorEvent, createEvent, fireError, fireEvent, getEventListenerRegistrations, getEventListeners, isDetailEvents, removeEventListener, setDetailEvents`

  ### Methods inherited from class java.lang.Object

  `equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

  ### Methods inherited from interface org.apache.commons.configuration2.ImmutableConfiguration

  `getEnum, getEnum`

- ## Constructor Details

  - ### AbstractConfiguration

    public AbstractConfiguration()
    Creates a new instance of `AbstractConfiguration`.

- ## Method Details

  - ### getListDelimiterHandler

    public ListDelimiterHandler getListDelimiterHandler()
    Gets the `ListDelimiterHandler` used by this instance.
    Returns:
      the `ListDelimiterHandler`
    Since:
      2.0

  - ### setListDelimiterHandler

    public void setListDelimiterHandler(ListDelimiterHandler listDelimiterHandler)

    Sets the `ListDelimiterHandler` to be used by this instance. This object is invoked every time when dealing with string properties that may contain a list delimiter and thus have to be split to multiple values. Per default, a `ListDelimiterHandler` implementation is set which does not support list splitting. This can be changed for instance by setting a `DefaultListDelimiterHandler` object.

    Warning: Be careful when changing the list delimiter handler when the configuration has already been loaded/populated. List handling is typically applied already when properties are added to the configuration. If later another handler is set which processes lists differently, results may be unexpected; some operations may even cause exceptions.

    Parameters:
      `listDelimiterHandler` - the `ListDelimiterHandler` to be used (must not be null)
    Throws:
      `IllegalArgumentException` - if the `ListDelimiterHandler` is null
    Since:
      2.0

  - ### getConversionHandler

    public ConversionHandler getConversionHandler()
    Gets the `ConversionHandler` used by this instance.
    Returns:
      the `ConversionHandler`
    Since:
      2.0

  - ### setConversionHandler

    public void setConversionHandler(ConversionHandler conversionHandler)
    Sets the `ConversionHandler` to be used by this instance. The `ConversionHandler` is responsible for every kind of data type conversion. It is consulted by all get methods returning results in specific data types. A newly created configuration uses a default `ConversionHandler` implementation. This can be changed while initializing the configuration (e.g. via a builder). Note that access to this property is not synchronized.
    Parameters:
      `conversionHandler` - the `ConversionHandler` to be used (must not be null)
    Throws:
      `IllegalArgumentException` - if the `ConversionHandler` is null
    Since:
      2.0

  - ### setThrowExceptionOnMissing

    public void setThrowExceptionOnMissing(boolean throwExceptionOnMissing)
    Allows to set the `throwExceptionOnMissing` flag. This flag controls the behavior of property getter methods that return objects if the requested property is missing. If the flag is set to false (which is the default value), these methods will return null. If set to true, they will throw a `NoSuchElementException` exception. Note that getter methods for primitive data types are not affected by this flag.
    Parameters:
      `throwExceptionOnMissing` - The new value for the property

  - ### isThrowExceptionOnMissing

    public boolean isThrowExceptionOnMissing()
    Returns true if missing values throw Exceptions.
    Returns:
      true if missing values throw Exceptions

  - ### getInterpolator

    public ConfigurationInterpolator getInterpolator()
    Gets the `ConfigurationInterpolator` object that manages the lookup objects for resolving variables. Unless a custom interpolator has been set or the instance has been modified, the returned interpolator will resolve values from this configuration instance and support the `default prefix lookups`.
    Specified by:
      `getInterpolator` in interface `Configuration`
    Returns:
      the `ConfigurationInterpolator` associated with this configuration
    Since:
      1.4
    See Also:
      - `ConfigurationInterpolator.getDefaultPrefixLookups()`

  - ### setInterpolator

    public final void setInterpolator(ConfigurationInterpolator ci)
    Sets the `ConfigurationInterpolator` object to be used by this `Configuration`. This object is invoked for each access of a string property in order to substitute variables which may be contained. The argument can be null to disable interpolation at all. This implementation sets the passed in object without further modifications. A null argument is allowed; this disables interpolation.
    Specified by:
      `setInterpolator` in interface `Configuration`
    Parameters:
      `ci` - the new `ConfigurationInterpolator`
    Since:
      2.0

  - ### installInterpolator

    public final void installInterpolator(Map<String,? extends Lookup> prefixLookups, Collection<? extends Lookup> defLookups)
    Creates and installs a new `ConfigurationInterpolator` for this `Configuration` based on the passed in arguments. This method creates a default `ConfigurationInterpolator` instance and initializes it with the passed in `Lookup` objects. It also adds a special default `Lookup` object that tries to resolve variables by matching them with properties contained in this `Configuration`. This is also the main difference to the `Configuration.setInterpolator(ConfigurationInterpolator)` method which sets the passed in object as is without adding this special lookup. This implementation creates a new `ConfigurationInterpolator` instance and initializes it with the given `Lookup` objects. In addition, it adds a specialized default `Lookup` object which queries this `Configuration`.
    Specified by:
      `installInterpolator` in interface `Configuration`
    Parameters:
      `prefixLookups` - the map with `Lookup` objects associated with specific prefixes (can be null)
      `defLookups` - a collection with default `Lookup` objects (can be null)
    Since:
      2.0
    See Also:
      - `ConfigurationInterpolator`

  - ### setPrefixLookups

    public void setPrefixLookups(Map<String,? extends Lookup> lookups)
    Registers all `Lookup` objects in the given map at the current `ConfigurationInterpolator` of this configuration. The set of default lookup objects (for variables without a prefix) is not modified by this method. If this configuration does not have a `ConfigurationInterpolator`, a new instance is created. Note: This method is mainly intended to be used for initializing a configuration when it is created by a builder. Normal client code should better call `installInterpolator(Map, Collection)` to define the `ConfigurationInterpolator` in a single step.
    Parameters:
      `lookups` - a map with new `Lookup` objects and their prefixes (may be null)
    Since:
      2.0

  - ### setDefaultLookups

    public void setDefaultLookups(Collection<? extends Lookup> lookups)
    Adds all `Lookup` objects in the given collection as default lookups (i.e. lookups without a variable prefix) to the `ConfigurationInterpolator` object of this configuration. In addition, it adds a specialized default `Lookup` object which queries this `Configuration`. The set of `Lookup` objects with prefixes is not modified by this method. If this configuration does not have a `ConfigurationInterpolator`, a new instance is created. Note: This method is mainly intended to be used for initializing a configuration when it is created by a builder. Normal client code should better call `installInterpolator(Map, Collection)` to define the `ConfigurationInterpolator` in a single step.
    Parameters:
      `lookups` - the collection with default `Lookup` objects to be added
    Since:
      2.0

  - ### setParentInterpolator

    public void setParentInterpolator(ConfigurationInterpolator parent)
    Sets the specified `ConfigurationInterpolator` as the parent of this configuration's `ConfigurationInterpolator`. If this configuration does not have a `ConfigurationInterpolator`, a new instance is created. Note: This method is mainly intended to be used for initializing a configuration when it is created by a builder. Normal client code can directly update the `ConfigurationInterpolator`.
    Parameters:
      `parent` - the parent `ConfigurationInterpolator` to be set
    Since:
      2.0

  - ### setConfigurationDecoder

    public void setConfigurationDecoder(ConfigurationDecoder configurationDecoder)
    Sets the `ConfigurationDecoder` for this configuration. This object is used by `getEncodedString(String)`.
    Parameters:
      `configurationDecoder` - the `ConfigurationDecoder`
    Since:
      2.0

  - ### getConfigurationDecoder

    public ConfigurationDecoder getConfigurationDecoder()
    Gets the `ConfigurationDecoder` used by this instance.
    Returns:
      the `ConfigurationDecoder`
    Since:
      2.0

  - ### cloneInterpolator

    protected void cloneInterpolator(AbstractConfiguration orgConfig)
    Creates a clone of the `ConfigurationInterpolator` used by this instance. This method can be called by `clone()` implementations of derived classes. Normally, the `ConfigurationInterpolator` of a configuration instance must not be shared with other instances because it contains a specific `Lookup` object pointing to the owning configuration. This has to be taken into account when cloning a configuration. This method creates a new `ConfigurationInterpolator` for this configuration instance which contains all lookup objects from the original `ConfigurationInterpolator` except for the configuration specific lookup pointing to the passed in original configuration. This one is replaced by a corresponding `Lookup` referring to this configuration.
    Parameters:
      `orgConfig` - the original configuration from which this one was cloned
    Since:
      2.0

  - ### getLogger

    public ConfigurationLogger getLogger()
    Gets the logger used by this configuration object.
    Returns:
      the logger
    Since:
      2.0

  - ### setLogger

    public void setLogger(ConfigurationLogger log)
    Allows setting the logger to be used by this configuration object. This method makes it possible for clients to exactly control logging behavior. Per default a logger is set that will ignore all log messages. Derived classes that want to enable logging should call this method during their initialization with the logger to be used. It is legal to pass a null logger; in this case, logging will be disabled.
    Parameters:
      `log` - the new logger
    Since:
      2.0

  - ### addErrorLogListener

    public final void addErrorLogListener()
    Adds a special `EventListener` object to this configuration that will log all internal errors. This method is intended to be used by certain derived classes, for which it is known that they can fail on property access (e.g. `DatabaseConfiguration`).
    Since:
      1.4

  - ### getSynchronizer

    public final Synchronizer getSynchronizer()
    Gets the object responsible for synchronizing this configuration. All access to this configuration - both read and write access - is controlled by this object. This implementation never returns null. If no `Synchronizer` has been set, a `NoOpSynchronizer` is returned. So, per default, instances of `AbstractConfiguration` are not thread-safe unless a suitable `Synchronizer` is set!
    Specified by:
      `getSynchronizer` in interface `SynchronizerSupport`
    Returns:
      the `Synchronizer` used by this instance
    Since:
      2.0

  - ### setSynchronizer

    public final void setSynchronizer(Synchronizer synchronizer)
    Sets the object responsible for synchronizing this configuration. This method has to be called with a suitable `Synchronizer` object when initializing this configuration instance in order to make it thread-safe.
    Specified by:
      `setSynchronizer` in interface `SynchronizerSupport`
    Parameters:
      `synchronizer` - the new `Synchronizer`; can be null, then this instance uses a `NoOpSynchronizer`
    Since:
      2.0

  - ### lock

    public final void lock(LockMode mode)
    Locks this object for the specified mode. This call may block until this object is released from other lock operations. When it returns the caller can access the object in a way compatible to the specified `LockMode`. When done the `unlock()` must be called with the same `LockMode` argument. In practice, a try-finally construct should be used as in the following example:

         SynchronizerSupport syncSupport = ...;
         syncSupport.lock(LockMode.READ);
         try
         {
             // read access to syncSupport
         }
         finally
         {
             syncSupport.unlock(LockMode.READ);
         }

    Note: Always use this method for obtaining a lock rather than accessing the object's `Synchronizer` directly. An implementation may perform additional actions which are not executed when only interacting with the `Synchronizer`. This implementation delegates to `beginRead()` or `beginWrite()`, depending on the `LockMode` argument. Subclasses can override these protected methods to perform additional steps when a configuration is locked.
    Specified by:
      `lock` in interface `SynchronizerSupport`
    Parameters:
      `mode` - the `LockMode`
    Throws:
      `NullPointerException` - if the argument is null
    Since:
      2.0

  - ### unlock

    public final void unlock(LockMode mode)
    Releases a lock of this object that was obtained using the `SynchronizerSupport.lock(LockMode)` method. This method must always be called pair-wise with `lock()`. The argument must match to the one passed to the corresponding `lock()` call; otherwise, the behavior of the `Synchronizer` is unspecified. This implementation delegates to `endRead()` or `endWrite()`, depending on the `LockMode` argument. Subclasses can override these protected methods to perform additional steps when a configuration's lock is released.
    Specified by:
      `unlock` in interface `SynchronizerSupport`
    Parameters:
      `mode` - the `LockMode`
    Throws:
      `NullPointerException` - if the argument is null

  - ### beginRead

    protected void beginRead(boolean optimize)
    Notifies this configuration's `Synchronizer` that a read operation is about to start. This method is called by all methods which access this configuration in a read-only mode. Subclasses may override it to perform additional actions before this read operation. The boolean optimize argument can be evaluated by overridden methods in derived classes. Some operations which require a lock do not need a fully initialized configuration object. By setting this flag to true, such operations can give a corresponding hint. An overridden implementation of `beginRead()` can then decide to skip some initialization steps. All basic operations in this class (and most of the basic `Configuration` implementations) call this method with a parameter value of false. In any case the inherited method must be called! Otherwise, proper synchronization is not guaranteed.
    Parameters:
      `optimize` - a flag whether optimization can be performed
    Since:
      2.0

  - ### endRead

    protected void endRead()
    Notifies this configuration's `Synchronizer` that a read operation has finished. This method is called by all methods which access this configuration in a read-only manner at the end of their execution. Subclasses may override it to perform additional actions after this read operation. In any case the inherited method must be called! Otherwise, the read lock will not be released.
    Since:
      2.0

  - ### beginWrite

    protected void beginWrite(boolean optimize)
    Notifies this configuration's `Synchronizer` that an update operation is about to start. This method is called by all methods which modify this configuration. Subclasses may override it to perform additional operations before an update. For a description of the boolean optimize argument refer to the documentation of `beginRead()`. In any case the inherited method must be called! Otherwise, proper synchronization is not guaranteed.
    Parameters:
      `optimize` - a flag whether optimization can be performed
    Since:
      2.0
    See Also:
      - `beginRead(boolean)`

  - ### endWrite

    protected void endWrite()
    Notifies this configuration's `Synchronizer` that an update operation has finished. This method is called by all methods which modify this configuration at the end of their execution. Subclasses may override it to perform additional operations after an update. In any case the inherited method must be called! Otherwise, the write lock will not be released.
    Since:
      2.0

  - ### addProperty

    public final void addProperty(String key, Object value)
    Description copied from interface: `Configuration`
    Add a property to the configuration. If it already exists then the value stated here will be added to the configuration entry. For example, if the property:

         resource.loader = file

    is already present in the configuration and you call

         addProperty("resource.loader", "classpath")

    Then you will end up with a List like the following:

         ["file", "classpath"]

    Specified by:
      `addProperty` in interface `Configuration`
    Parameters:
      `key` - The key to add the property to.
      `value` - The value to add.

  - ### addPropertyInternal

    protected void addPropertyInternal(String key, Object value)
    Actually adds a property to this configuration. This method is called by `addProperty()`. It performs list splitting if necessary and delegates to `addPropertyDirect(String, Object)` for every single property value.
    Parameters:
      `key` - the key of the property to be added
      `value` - the new property value
    Since:
      2.0

  - ### addPropertyDirect

    protected abstract void addPropertyDirect(String key, Object value)
    Adds a key/value pair to the Configuration. Override this method to provide write access to underlying Configuration store.
    Parameters:
      `key` - key to use for mapping
      `value` - object to store

  - ### interpolate

    protected String interpolate(String base)
    interpolate key names to handle ${key} stuff
    Parameters:
      `base` - string to interpolate
    Returns:
      returns the key name with the ${key} substituted

  - ### interpolate

    protected Object interpolate(Object value)
    Returns the interpolated value. This implementation delegates to the current `ConfigurationInterpolator`. If no `ConfigurationInterpolator` is set, the passed in value is returned without changes.
    Parameters:
      `value` - the value to interpolate
    Returns:
      the value with variables substituted

  - ### subset

    public Configuration subset(String prefix)
    Description copied from interface: `Configuration`
    Return a decorator Configuration containing every key from the current Configuration that starts with the specified prefix. The prefix is removed from the keys in the subset. For example, if the configuration contains the following properties:

            prefix.number = 1
            prefix.string = Apache
            prefixed.foo = bar
            prefix = Jakarta

    the Configuration returned by `subset("prefix")` will contain the properties:

            number = 1
            string = Apache
            = Jakarta

    (The key for the value "Jakarta" is an empty string)

    Since the subset is a decorator and not a modified copy of the initial Configuration, any change made to the subset is available to the Configuration, and reciprocally.

    Specified by:
      `subset` in interface `Configuration`
    Parameters:
      `prefix` - The prefix used to select the properties.
    Returns:
      a subset configuration
    See Also:
      - `SubsetConfiguration`

  - ### immutableSubset

    public ImmutableConfiguration immutableSubset(String prefix)
    Description copied from interface: `ImmutableConfiguration`
    Return a decorator immutable Configuration containing every key from the current Configuration that starts with the specified prefix. The prefix is removed from the keys in the subset. For example, if the configuration contains the following properties:

            prefix.number = 1
            prefix.string = Apache
            prefixed.foo = bar
            prefix = Jakarta

    the immutable Configuration returned by `subset("prefix")` will contain the properties:

            number = 1
            string = Apache
            = Jakarta

    (The key for the value "Jakarta" is an empty string)
    Specified by:
      `immutableSubset` in interface `ImmutableConfiguration`
    Parameters:
      `prefix` - The prefix used to select the properties.
    Returns:
      a subset immutable configuration

  - ### setProperty

    public final void setProperty(String key, Object value)
    Description copied from interface: `Configuration`
    Sets a property, this will replace any previously set values. Set values is implicitly a call to clearProperty(key), addProperty(key, value).
    Specified by:
      `setProperty` in interface `Configuration`
    Parameters:
      `key` - The key of the property to change
      `value` - The new value

  - ### setPropertyInternal

    protected void setPropertyInternal(String key, Object value)
    Actually sets the value of a property. This method is called by `setProperty()`. It provides a default implementation of this functionality by clearing the specified key and delegating to `addProperty()`. Subclasses should override this method if they can provide a more efficient algorithm for setting a property value.
    Parameters:
      `key` - the property key
      `value` - the new property value
    Since:
      2.0

  - ### clearProperty

    public final void clearProperty(String key)
    Removes the specified property from this configuration. This implementation performs some preparations and then delegates to `clearPropertyDirect()`, which will do the real work.
    Specified by:
      `clearProperty` in interface `Configuration`
    Parameters:
      `key` - the key to be removed

  - ### clearPropertyDirect

    protected abstract void clearPropertyDirect(String key)
    Removes the specified property from this configuration. This method is called by `clearProperty()` after it has done some preparations. It must be overridden in sub classes.
    Parameters:
      `key` - the key to be removed

  - ### clear

    public final void clear()
    Description copied from interface: `Configuration`
    Remove all properties from the configuration.
    Specified by:
      `clear` in interface `Configuration`

  - ### clearInternal

    protected void clearInternal()
    Clears the whole configuration. This method is called by `clear()` after some preparations have been made. This base implementation uses the iterator provided by `getKeys()` to remove every single property. Subclasses should override this method if there is a more efficient way of clearing the configuration.

  - ### getKeys

    public final Iterator<String> getKeys()
    Gets the list of the keys contained in the configuration. The returned iterator can be used to obtain all defined keys. It does not allow removing elements from this configuration via its `remove()` method. Note that the keys of this configuration are returned in a form, so that they can be directly evaluated; escaping of special characters (if necessary) has already been performed. This implementation takes care of synchronization and then delegates to `getKeysInternal()` for obtaining the actual iterator. Note that depending on a concrete implementation, an iteration may fail if the configuration is updated concurrently.
    Specified by:
      `getKeys` in interface `ImmutableConfiguration`
    Returns:
      An Iterator.

  - ### getKeys

    public final Iterator<String> getKeys(String prefix)
    Gets the list of the keys contained in the configuration that match the specified prefix. For instance, if the configuration contains the following keys:
    `db.user, db.pwd, db.url, window.xpos, window.ypos`,
    an invocation of `getKeys("db");`
    will return the keys below:
    `db.user, db.pwd, db.url`.
    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 - depends on a concrete implementation. This implementation returns keys that either match the prefix or start with the prefix followed by a dot ('.'). So the call `getKeys("db");` will find the keys `db`, `db.user`, or `db.password`, but not the key `dbdriver`.
    Specified by:
      `getKeys` in interface `ImmutableConfiguration`
    Parameters:
      `prefix` - The prefix to test against.
    Returns:
      An Iterator of keys that match the prefix.
    See Also:
      - `ImmutableConfiguration.getKeys()`

  - ### getKeys

    public final Iterator<String> getKeys(String prefix, String delimiter)
    Gets the list of the keys contained in the configuration that match the specified prefix. For instance, if the configuration contains the following keys:
    `db@user, db@pwd, db@url, window.xpos, window.ypos`,
    an invocation of `getKeys("db","@");`
    will return the keys below:
    `db@user, db@pwd, db@url`.
    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 - depends on a concrete implementation. This implementation returns keys that either match the prefix or start with the prefix followed by the delimiter. So the call `getKeys("db");` will find the keys `db`, `db@user`, or `db@password`, but not the key `dbdriver`.
    Specified by:
      `getKeys` in interface `ImmutableConfiguration`
    Parameters:
      `prefix` - The prefix to test against.
      `delimiter` - The prefix delimiter.
    Returns:
      An Iterator of keys that match the prefix.
    See Also:
      - `ImmutableConfiguration.getKeys()`

  - ### getKeysInternal

    protected abstract Iterator<String> getKeysInternal()
    Actually creates an iterator for iterating over the keys in this configuration. This method is called by `getKeys()`, it has to be defined by concrete subclasses.
    Returns:
      an `Iterator` with all property keys in this configuration
    Since:
      2.0

  - ### getKeysInternal

    protected Iterator<String> getKeysInternal(String prefix)
    Gets an `Iterator` with all property keys starting with the specified prefix. This method is called by `getKeys(String)`. It is fully implemented by delegating to `getKeysInternal()` and returning a special iterator which filters for the passed in prefix. Subclasses can override it if they can provide a more efficient way to iterate over specific keys only.
    Parameters:
      `prefix` - the prefix for the keys to be taken into account
    Returns:
      an `Iterator` returning the filtered keys
    Since:
      2.0

  - ### getKeysInternal

    protected Iterator<String> getKeysInternal(String prefix, String delimiter)
    Gets an `Iterator` with all property keys starting with the specified prefix and specified delimiter. This method is called by `getKeys(String)`. It is fully implemented by delegating to `getKeysInternal()` and returning a special iterator which filters for the passed in prefix. Subclasses can override it if they can provide a more efficient way to iterate over specific keys only.
    Parameters:
      `prefix` - the prefix for the keys to be taken into account
      `delimiter` - the prefix delimiter
    Returns:
      an `Iterator` returning the filtered keys
    Since:
      2.10.0

  - ### getProperty

    public final Object getProperty(String key)
    Gets a property from the configuration. This is the most basic get method for retrieving values of properties. In a typical implementation of the `Configuration` interface the other get methods (that return specific data types) will internally make use of this method. On this level variable substitution is not yet performed. The returned object is an internal representation of the property value for the passed in key. It is owned by the `Configuration` object. So a caller should not modify this object. It cannot be guaranteed that this object will stay constant over time (i.e. further update operations on the configuration may change its internal state). This implementation ensures proper synchronization. Subclasses have to define the abstract `getPropertyInternal()` method which is called from here.
    Specified by:
      `getProperty` in interface `ImmutableConfiguration`
    Parameters:
      `key` - property to retrieve
    Returns:
      the value to which this configuration maps the specified key, or null if the configuration contains no mapping for this key.

  - ### getPropertyInternal

    protected abstract Object getPropertyInternal(String key)
    Actually obtains the value of the specified property. This method is called by `getProperty()`. Concrete subclasses must define it to fetch the value of the desired property.
    Parameters:
      `key` - the key of the property in question
    Returns:
      the (raw) value of this property
    Since:
      2.0

  - ### isEmpty

    public final boolean isEmpty()
    Checks if the configuration is empty. This implementation handles synchronization and delegates to `isEmptyInternal()`.
    Specified by:
      `isEmpty` in interface `ImmutableConfiguration`
    Returns:
      `true` if the configuration contains no property, `false` otherwise.

  - ### isEmptyInternal

    protected abstract boolean isEmptyInternal()
    Actually checks whether this configuration contains data. This method is called by `isEmpty()`. It has to be defined by concrete subclasses.
    Returns:
      true if this configuration contains no data, false otherwise
    Since:
      2.0

  - ### size

    public final int size()
    Returns the number of keys stored in this configuration. Note that a concrete implementation is not guaranteed to be efficient; for some implementations it may be expensive to determine the size. Especially, if you just want to check whether a configuration is empty, it is preferable to use the `ImmutableConfiguration.isEmpty()` method. This implementation handles synchronization and delegates to `sizeInternal()`.
    Specified by:
      `size` in interface `ImmutableConfiguration`
    Returns:
      the number of keys stored in this configuration

  - ### sizeInternal

    protected int sizeInternal()
    Actually calculates the size of this configuration. This method is called by `size()` with a read lock held. The base implementation provided here calculates the size based on the iterator returned by `getKeys()`. Sub classes which can determine the size in a more efficient way should override this method.
    Returns:
      the size of this configuration (i.e. the number of keys)

  - ### containsKey

    public final boolean containsKey(String key)
    Checks if the configuration contains the specified key. This implementation handles synchronization and delegates to `containsKeyInternal()`.
    Specified by:
      `containsKey` in interface `ImmutableConfiguration`
    Parameters:
      `key` - the key whose presence in this configuration is to be tested
    Returns:
      `true` if the configuration contains a value for this key, `false` otherwise

  - ### containsKeyInternal

    protected abstract boolean containsKeyInternal(String key)
    Actually checks whether the specified key is contained in this configuration. This method is called by `containsKey()`. It has to be defined by concrete subclasses.
    Parameters:
      `key` - the key in question
    Returns:
      true if this key is contained in this configuration, false otherwise
    Since:
      2.0

  - ### getProperties

    public Properties getProperties(String key)
    Description copied from interface: `ImmutableConfiguration`
    Gets a list of properties associated with the given configuration key. This method expects the given key to have an arbitrary number of String values, each of which is of the form `key=value`. These strings are split at the equals sign, and the key parts will become keys of the returned `Properties` object, the value parts become values.
    Specified by:
      `getProperties` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
    Returns:
      The associated properties if key is found.

  - ### getProperties

    public Properties getProperties(String key, Properties defaults)
    Gets a list of properties associated with the given configuration key.
    Parameters:
      `key` - The configuration key.
      `defaults` - Any default values for the returned `Properties` object. Ignored if `null`.
    Returns:
      The associated properties if key is found.
    Throws:
      `ConversionException` - is thrown if the key maps to an object that is not a String/List of Strings.
      `IllegalArgumentException` - if one of the tokens is malformed (does not contain an equals sign).

  - ### getBoolean

    public boolean getBoolean(String key)
    Description copied from interface: `ImmutableConfiguration`
    Gets a boolean associated with the given configuration key.
    Specified by:
      `getBoolean` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
    Returns:
      The associated boolean.

  - ### getBoolean

    public boolean getBoolean(String key, boolean defaultValue)
    Description copied from interface: `ImmutableConfiguration`
    Gets a boolean associated with the given configuration key. If the key doesn't map to an existing object, the default value is returned.
    Specified by:
      `getBoolean` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
      `defaultValue` - The default value.
    Returns:
      The associated boolean.

  - ### getBoolean

    public Boolean getBoolean(String key, Boolean defaultValue)
    Obtains the value of the specified key and tries to convert it into a `Boolean` object. If the property has no value, the passed in default value will be used.
    Specified by:
      `getBoolean` in interface `ImmutableConfiguration`
    Parameters:
      `key` - the key of the property
      `defaultValue` - the default value
    Returns:
      the value of this key converted to a `Boolean`
    Throws:
      `ConversionException` - if the value cannot be converted to a `Boolean`

  - ### getByte

    public byte getByte(String key)
    Description copied from interface: `ImmutableConfiguration`
    Gets a byte associated with the given configuration key.
    Specified by:
      `getByte` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
    Returns:
      The associated byte.

  - ### getByte

    public byte getByte(String key, byte defaultValue)
    Description copied from interface: `ImmutableConfiguration`
    Gets a byte associated with the given configuration key. If the key doesn't map to an existing object, the default value is returned.
    Specified by:
      `getByte` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
      `defaultValue` - The default value.
    Returns:
      The associated byte.

  - ### getByte

    public Byte getByte(String key, Byte defaultValue)
    Description copied from interface: `ImmutableConfiguration`
    Gets a `Byte` associated with the given configuration key.
    Specified by:
      `getByte` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
      `defaultValue` - The default value.
    Returns:
      The associated byte if key is found and has valid format, default value otherwise.

  - ### getDouble

    public double getDouble(String key)
    Description copied from interface: `ImmutableConfiguration`
    Gets a double associated with the given configuration key.
    Specified by:
      `getDouble` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
    Returns:
      The associated double.

  - ### getDouble

    public double getDouble(String key, double defaultValue)
    Description copied from interface: `ImmutableConfiguration`
    Gets a double associated with the given configuration key. If the key doesn't map to an existing object, the default value is returned.
    Specified by:
      `getDouble` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
      `defaultValue` - The default value.
    Returns:
      The associated double.

  - ### getDouble

    public Double getDouble(String key, Double defaultValue)
    Description copied from interface: `ImmutableConfiguration`
    Gets a `Double` associated with the given configuration key.
    Specified by:
      `getDouble` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
      `defaultValue` - The default value.
    Returns:
      The associated double if key is found and has valid format, default value otherwise.

  - ### getDuration

    public Duration getDuration(String key)
    Description copied from interface: `ImmutableConfiguration`
    Gets a `Duration` associated with the given configuration key.
    Specified by:
      `getDuration` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
    Returns:
      The associated Duration if key is found and has valid format, default value otherwise.

  - ### getDuration

    public Duration getDuration(String key, Duration defaultValue)
    Description copied from interface: `ImmutableConfiguration`
    Gets a `Duration` associated with the given configuration key.
    Specified by:
      `getDuration` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
      `defaultValue` - The default value.
    Returns:
      The associated Duration if key is found and has valid format, default value otherwise.

  - ### getFloat

    public float getFloat(String key)
    Description copied from interface: `ImmutableConfiguration`
    Gets a float associated with the given configuration key.
    Specified by:
      `getFloat` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
    Returns:
      The associated float.

  - ### getFloat

    public float getFloat(String key, float defaultValue)
    Description copied from interface: `ImmutableConfiguration`
    Gets a float associated with the given configuration key. If the key doesn't map to an existing object, the default value is returned.
    Specified by:
      `getFloat` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
      `defaultValue` - The default value.
    Returns:
      The associated float.

  - ### getFloat

    public Float getFloat(String key, Float defaultValue)
    Description copied from interface: `ImmutableConfiguration`
    Gets a `Float` associated with the given configuration key. If the key doesn't map to an existing object, the default value is returned.
    Specified by:
      `getFloat` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
      `defaultValue` - The default value.
    Returns:
      The associated float if key is found and has valid format, default value otherwise.

  - ### getInt

    public int getInt(String key)
    Description copied from interface: `ImmutableConfiguration`
    Gets a int associated with the given configuration key.
    Specified by:
      `getInt` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
    Returns:
      The associated int.

  - ### getInt

    public int getInt(String key, int defaultValue)
    Description copied from interface: `ImmutableConfiguration`
    Gets a int associated with the given configuration key. If the key doesn't map to an existing object, the default value is returned.
    Specified by:
      `getInt` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
      `defaultValue` - The default value.
    Returns:
      The associated int.

  - ### getInteger

    public Integer getInteger(String key, Integer defaultValue)
    Description copied from interface: `ImmutableConfiguration`
    Gets an `Integer` associated with the given configuration key. If the key doesn't map to an existing object, the default value is returned.
    Specified by:
      `getInteger` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
      `defaultValue` - The default value.
    Returns:
      The associated int if key is found and has valid format, default value otherwise.

  - ### getLong

    public long getLong(String key)
    Description copied from interface: `ImmutableConfiguration`
    Gets a long associated with the given configuration key.
    Specified by:
      `getLong` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
    Returns:
      The associated long.

  - ### getLong

    public long getLong(String key, long defaultValue)
    Description copied from interface: `ImmutableConfiguration`
    Gets a long associated with the given configuration key. If the key doesn't map to an existing object, the default value is returned.
    Specified by:
      `getLong` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
      `defaultValue` - The default value.
    Returns:
      The associated long.

  - ### getLong

    public Long getLong(String key, Long defaultValue)
    Description copied from interface: `ImmutableConfiguration`
    Gets a `Long` associated with the given configuration key. If the key doesn't map to an existing object, the default value is returned.
    Specified by:
      `getLong` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
      `defaultValue` - The default value.
    Returns:
      The associated long if key is found and has valid format, default value otherwise.

  - ### getShort

    public short getShort(String key)
    Description copied from interface: `ImmutableConfiguration`
    Gets a short associated with the given configuration key.
    Specified by:
      `getShort` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
    Returns:
      The associated short.

  - ### getShort

    public short getShort(String key, short defaultValue)
    Description copied from interface: `ImmutableConfiguration`
    Gets a short associated with the given configuration key.
    Specified by:
      `getShort` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
      `defaultValue` - The default value.
    Returns:
      The associated short.

  - ### getShort

    public Short getShort(String key, Short defaultValue)
    Description copied from interface: `ImmutableConfiguration`
    Gets a `Short` associated with the given configuration key. If the key doesn't map to an existing object, the default value is returned.
    Specified by:
      `getShort` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
      `defaultValue` - The default value.
    Returns:
      The associated short if key is found and has valid format, default value otherwise.

  - ### getBigDecimal

    public BigDecimal getBigDecimal(String key)
    Gets a `BigDecimal` associated with the given configuration key.
    Specified by:
      `getBigDecimal` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
    Returns:
      The associated BigDecimal if key is found and has valid format
    See Also:
      - `setThrowExceptionOnMissing(boolean)`

  - ### getBigDecimal

    public BigDecimal getBigDecimal(String key, BigDecimal defaultValue)
    Description copied from interface: `ImmutableConfiguration`
    Gets a `BigDecimal` associated with the given configuration key. If the key doesn't map to an existing object, the default value is returned.
    Specified by:
      `getBigDecimal` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
      `defaultValue` - The default value.
    Returns:
      The associated BigDecimal if key is found and has valid format, default value otherwise.

  - ### getBigInteger

    public BigInteger getBigInteger(String key)
    Gets a `BigInteger` associated with the given configuration key.
    Specified by:
      `getBigInteger` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
    Returns:
      The associated BigInteger if key is found and has valid format
    See Also:
      - `setThrowExceptionOnMissing(boolean)`

  - ### getBigInteger

    public BigInteger getBigInteger(String key, BigInteger defaultValue)
    Description copied from interface: `ImmutableConfiguration`
    Gets a `BigInteger` associated with the given configuration key. If the key doesn't map to an existing object, the default value is returned.
    Specified by:
      `getBigInteger` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
      `defaultValue` - The default value.
    Returns:
      The associated BigInteger if key is found and has valid format, default value otherwise.

  - ### getString

    public String getString(String key)
    Gets a string associated with the given configuration key.
    Specified by:
      `getString` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
    Returns:
      The associated string.
    See Also:
      - `setThrowExceptionOnMissing(boolean)`

  - ### getString

    public String getString(String key, String defaultValue)
    Description copied from interface: `ImmutableConfiguration`
    Gets a string associated with the given configuration key. If the key doesn't map to an existing object, the default value is returned.
    Specified by:
      `getString` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
      `defaultValue` - The default value.
    Returns:
      The associated string if key is found and has valid format, default value otherwise.

  - ### getEncodedString

    public String getEncodedString(String key, ConfigurationDecoder decoder)
    Gets the value of a string property that is stored in encoded form in this configuration. This method obtains the value of the string property identified by the given key. This value is then passed to the provided `ConfigurationDecoder`. The value returned by the `ConfigurationDecoder` is passed to the caller. If the key is not associated with a value, the decoder is not invoked; depending on this configuration's settings either null is returned or an exception is thrown. This implementation delegates to `getString(String)` in order to obtain the value of the passed in key. This value is passed to the decoder. Because `getString()` is used behind the scenes all standard features like handling of missing keys and interpolation work as expected.
    Specified by:
      `getEncodedString` in interface `ImmutableConfiguration`
    Parameters:
      `key` - the configuration key
      `decoder` - the `ConfigurationDecoder` (must not be null)
    Returns:
      the plain string value of the specified encoded property

  - ### getEncodedString

    public String getEncodedString(String key)
    Gets the value of a string property that is stored in encoded form in this configuration using a default `ConfigurationDecoder`. This method works like the method with the same name, but it uses a default `ConfigurationDecoder` associated with this configuration. It depends on a specific implementation how this default decoder is obtained. This implementation makes use of the `ConfigurationDecoder` set for this configuration. If no such object has been set, an `IllegalStateException` exception is thrown.
    Specified by:
      `getEncodedString` in interface `ImmutableConfiguration`
    Parameters:
      `key` - the configuration key
    Returns:
      the plain string value of the specified encoded property
    Throws:
      `IllegalStateException` - if no `ConfigurationDecoder` is set
    See Also:
      - `setConfigurationDecoder(ConfigurationDecoder)`

  - ### getStringArray

    public String[] getStringArray(String key)
    Gets an array of strings associated with the given configuration key. If the key doesn't map to an existing object, an empty array is returned. When a property is added to a configuration, it is checked whether it contains multiple values. This is obvious if the added object is a list or an array. For strings the association `ListDelimiterHandler` is consulted to find out whether the string can be split into multiple values.
    Specified by:
      `getStringArray` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
    Returns:
      The associated string array if key is found.
    Throws:
      `ConversionException` - is thrown if the key maps to an object that is not a String/List of Strings.
    See Also:
      - `setListDelimiterHandler(ListDelimiterHandler)`

  - ### getList

    public List<Object> getList(String key)
    Gets a List of the values associated with the given configuration key. This method is different from the generic `getList()` method in that it does not recursively obtain all values stored for the specified property key. Rather, only the first level of the hierarchy is processed. So the resulting list may contain complex objects like arrays or collections - depending on the storage structure used by a concrete subclass. If the key doesn't map to an existing object, an empty List is returned.
    Specified by:
      `getList` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
    Returns:
      The associated List.
    See Also:
      - `getStringArray(String)`

  - ### getList

    public List<Object> getList(String key, List<?> defaultValue)
    Description copied from interface: `ImmutableConfiguration`
    Gets a List of strings associated with the given configuration key. If the key doesn't map to an existing object, the default value is returned.
    Specified by:
      `getList` in interface `ImmutableConfiguration`
    Parameters:
      `key` - The configuration key.
      `defaultValue` - The default value.
    Returns:
      The associated List of strings.
    See Also:
      - `ImmutableConfiguration.getList(Class, String, List)`

  - ### get

    public <T> T get(Class<T> cls, String key)
    Description copied from interface: `ImmutableConfiguration`
    Gets an object of the specified type associated with the given configuration key. If the key doesn't map to an existing object, the method returns null unless `isThrowExceptionOnMissing()` is set to `true`.
    Specified by:
      `get` in interface `ImmutableConfiguration`
    Type Parameters:
      `T` - the target type of the value
    Parameters:
      `cls` - the target class of the value
      `key` - the key of the value
    Returns:
      the value of the requested type for the key

  - ### get

    public <T> T get(Class<T> cls, String key, T defaultValue)
    Gets an object of the specified type associated with the given configuration key using a default value. If the key doesn't map to an existing object, the default value is returned. This implementation delegates to the `ConversionHandler` to perform the actual type conversion.
    Specified by:
      `get` in interface `ImmutableConfiguration`
    Type Parameters:
      `T` - the target type of the value
    Parameters:
      `cls` - the target class of the value
      `key` - the key of the value
      `defaultValue` - the default value
    Returns:
      the value of the requested type for the key

  - ### getArray

    public Object getArray(Class<?> cls, String key)
    Description copied from interface: `ImmutableConfiguration`
    Gets an array of typed objects associated with the given configuration key. If the key doesn't map to an existing object, an empty list is returned.
    Specified by:
      `getArray` in interface `ImmutableConfiguration`
    Parameters:
      `cls` - the type expected for the elements of the array
      `key` - The configuration key.
    Returns:
      The associated array if the key is found, and the value compatible with the type specified.

  - ### getArray

    public Object getArray(Class<?> cls, String key, Object defaultValue)
    Gets an array of typed objects associated with the given configuration key. If the key doesn't map to an existing object, the default value is returned. This implementation delegates to the `ConversionHandler` to perform the actual type conversion. If this results in a null result (because the property is undefined), the default value is returned. It is checked whether the default value is an array with the correct component type. If not, an exception is thrown.
    Specified by:
      `getArray` in interface `ImmutableConfiguration`
    Parameters:
      `cls` - the type expected for the elements of the array
      `key` - the configuration key.
      `defaultValue` - the default value
    Returns:
      The associated array if the key is found, and the value compatible with the type specified.
    Throws:
      `IllegalArgumentException` - if the default value is not a compatible array

  - ### getList

    public <T> List<T> getList(Class<T> cls, String key)
    Description copied from interface: `ImmutableConfiguration`
    Gets a list of typed objects associated with the given configuration key returning a null if the key doesn't map to an existing object.
    Specified by:
      `getList` in interface `ImmutableConfiguration`
    Type Parameters:
      `T` - the type expected for the elements of the list
    Parameters:
      `cls` - the class expected for the elements of the list
      `key` - The configuration key.
    Returns:
      The associated list if the key is found.

  - ### getList

    public <T> List<T> getList(Class<T> cls, String key, List<T> defaultValue)
    Gets a list of typed objects associated with the given configuration key returning the specified default value if the key doesn't map to an existing object. This method recursively retrieves all values stored for the passed in key, 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 concrete subclasses), all values are extracted and added to the resulting list - performing a type conversion if necessary. This implementation delegates to the generic `getCollection()`. As target collection a newly created `ArrayList` is passed in.
    Specified by:
      `getList` in interface `ImmutableConfiguration`
    Type Parameters:
      `T` - the type expected for the elements of the list
    Parameters:
      `cls` - the class expected for the elements of the list
      `key` - the configuration key.
      `defaultValue` - the default value.
    Returns:
      The associated List.

  - ### getCollection

    public <T> Collection<T> getCollection(Class<T> cls, String key, Collection<T> target)
    Description copied from interface: `ImmutableConfiguration`
    Gets a collection of typed objects associated with the given configuration key. This method works like `ImmutableConfiguration.getCollection(Class, String, Collection, Collection)` passing in null as default value.
    Specified by:
      `getCollection` in interface `ImmutableConfiguration`
    Type Parameters:
      `T` - the element type of the result list
    Parameters:
      `cls` - the element class of the result list
      `key` - the configuration key
      `target` - the target collection (may be null)
    Returns:
      the collection to which data was added

  - ### getCollection

    public <T> Collection<T> getCollection(Class<T> cls, String key, Collection<T> target, Collection<T> defaultValue)
    Gets a collection of typed objects associated with the given configuration key using the values in the specified default collection if the key does not map to an existing object. This method is similar to `getList()`, however, it allows specifying a target collection. Results are added to this collection. This is useful if the data retrieved should be added to a specific kind of collection, e.g. a set to remove duplicates. The return value is as follows:
    - If the key does not map to an existing object and the default value is null, the method returns null.
    - If the target collection is not null and data has been added (either from the resolved property value or from the default collection), the target collection is returned.
    - If the target collection is null and data has been added (either from the resolved property value or from the default collection), return value is the target collection created by this method.
    This implementation delegates to the `ConversionHandler` to perform the actual conversion. If no target collection is provided, an `ArrayList` is created.
    Specified by:
      `getCollection` in interface `ImmutableConfiguration`
    Type Parameters:
      `T` - the element type of the result list
    Parameters:
      `cls` - the element class of the result list
      `key` - the configuration key
      `target` - the target collection (may be null)
      `defaultValue` - the default value (may be null)
    Returns:
      the collection to which data was added

  - ### isScalarValue

    protected boolean isScalarValue(Object value)
    Checks whether the specified object is a scalar value. This method is called by `getList()` and `getStringArray()` if the property requested is not a string, a list, or an array. If it returns true, the calling method transforms the value to a string and returns a list or an array with this single element. This implementation returns true if the value is of a wrapper type for a primitive type.
    Parameters:
      `value` - the value to be checked
    Returns:
      a flag whether the value is a scalar
    Since:
      1.7

  - ### copy

    public void copy(Configuration c)
    Copies the content of the specified configuration into this configuration. If the specified configuration contains a key that is also present in this configuration, the value of this key will be replaced by the new value. Note: This method won't work well when copying hierarchical configurations because it is not able to copy information about the properties' structure (i.e. the parent-child-relationships will get lost). So when dealing with hierarchical configuration objects their `clone()` methods should be used.
    Parameters:
      `c` - the configuration to copy (can be null, then this operation will have no effect)
    Since:
      1.5

  - ### append

    public void append(Configuration c)
    Appends the content of the specified configuration to this configuration. The values of all properties contained in the specified configuration will be appended to this configuration. So if a property is already present in this configuration, its new value will be a union of the values in both configurations. Note: This method won't work well when appending hierarchical configurations because it is not able to copy information about the properties' structure (i.e. the parent-child-relationships will get lost). So when dealing with hierarchical configuration objects their `clone()` methods should be used.
    Parameters:
      `c` - the configuration to be appended (can be null, then this operation will have no effect)
    Since:
      1.5

  - ### interpolatedConfiguration

    public Configuration interpolatedConfiguration()
    Returns a configuration with the same content as this configuration, but with all variables replaced by their actual values. This method tries to clone the configuration and then perform interpolation on all properties. So property values of the form `${var}` will be resolved as far as possible (if a variable cannot be resolved, it remains unchanged). This operation is useful if the content of a configuration is to be exported or processed by an external component that does not support variable interpolation.
    Returns:
      a configuration with all variables interpolated
    Throws:
      `ConfigurationRuntimeException` - if this configuration cannot be cloned
    Since:
      1.5

  - ### initLogger

    protected final void initLogger(ConfigurationLogger log)
    Initializes the logger. Supports null input. This method can be called by derived classes in order to enable logging.
    Parameters:
      `log` - the logger
    Since:
      2.0