/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.configuration2.builder;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.configuration2.ConfigurationDecoder;
import org.apache.commons.configuration2.io.ConfigurationLogger;
import org.apache.commons.configuration2.beanutils.BeanHelper;
import org.apache.commons.configuration2.convert.ConversionHandler;
import org.apache.commons.configuration2.convert.ListDelimiterHandler;
import org.apache.commons.configuration2.interpol.ConfigurationInterpolator;
import org.apache.commons.configuration2.interpol.InterpolatorSpecification;
import org.apache.commons.configuration2.interpol.Lookup;
import org.apache.commons.configuration2.sync.Synchronizer;

/**
 * <p>
 * An implementation of {@code BuilderParameters} which handles the parameters
 * of a {@link ConfigurationBuilder} common to all concrete
 * {@code Configuration} implementations.
 * </p>
 * <p>
 * This class provides methods for setting standard properties supported by the
 * {@code AbstractConfiguration} base class. A fluent interface can be used to
 * set property values.
 * </p>
 * <p>
 * This class is not thread-safe. It is intended that an instance is constructed
 * and initialized by a single thread during configuration of a
 * {@code ConfigurationBuilder}.
 * </p>
 *
 * @version $Id$
 * @since 2.0
 */
public class BasicBuilderParameters implements Cloneable, BuilderParameters,
        BasicBuilderProperties<BasicBuilderParameters>
{
    /** The key of the <em>throwExceptionOnMissing</em> property. */
    private static final String PROP_THROW_EXCEPTION_ON_MISSING =
            "throwExceptionOnMissing";

    /** The key of the <em>listDelimiterHandler</em> property. */
    private static final String PROP_LIST_DELIMITER_HANDLER = "listDelimiterHandler";

    /** The key of the <em>logger</em> property. */
    private static final String PROP_LOGGER = "logger";

    /** The key for the <em>interpolator</em> property. */
    private static final String PROP_INTERPOLATOR = "interpolator";

    /** The key for the <em>prefixLookups</em> property. */
    private static final String PROP_PREFIX_LOOKUPS = "prefixLookups";

    /** The key for the <em>defaultLookups</em> property. */
    private static final String PROP_DEFAULT_LOOKUPS = "defaultLookups";

    /** The key for the <em>parentInterpolator</em> property. */
    private static final String PROP_PARENT_INTERPOLATOR = "parentInterpolator";

    /** The key for the <em>synchronizer</em> property. */
    private static final String PROP_SYNCHRONIZER = "synchronizer";

    /** The key for the <em>conversionHandler</em> property. */
    private static final String PROP_CONVERSION_HANDLER = "conversionHandler";

    /** The key for the <em>configurationDecoder</em> property. */
    private static final String PROP_CONFIGURATION_DECODER = "configurationDecoder";

    /** The key for the {@code BeanHelper}. */
    private static final String PROP_BEAN_HELPER = RESERVED_PARAMETER_PREFIX
            + "BeanHelper";

    /** The map for storing the current property values. */
    private Map<String, Object> properties;

    /**
     * Creates a new instance of {@code BasicBuilderParameters}.
     */
    public BasicBuilderParameters()
    {
        properties = new HashMap<String, Object>();
    }

    /**
     * {@inheritDoc} This implementation returns a copy of the internal
     * parameters map with the values set so far. Collection structures
     * (e.g. for lookup objects) are stored as defensive copies, so the
     * original data cannot be modified.
     */
    @Override
    public Map<String, Object> getParameters()
    {
        HashMap<String, Object> result =
                new HashMap<String, Object>(properties);
        if (result.containsKey(PROP_INTERPOLATOR))
        {
            // A custom ConfigurationInterpolator overrides lookups
            result.remove(PROP_PREFIX_LOOKUPS);
            result.remove(PROP_DEFAULT_LOOKUPS);
            result.remove(PROP_PARENT_INTERPOLATOR);
        }

        createDefensiveCopies(result);
        return result;
    }

    /**
     * Sets the <em>logger</em> property. With this property a concrete
     * {@code Log} object can be set for the configuration. Thus logging
     * behavior can be controlled.
     *
     * @param log the {@code Log} for the configuration produced by this builder
     * @return a reference to this object for method chaining
     */
    @Override
    public BasicBuilderParameters setLogger(ConfigurationLogger log)
    {
        return setProperty(PROP_LOGGER, log);
    }

    /**
     * Sets the value of the <em>throwExceptionOnMissing</em> property. This
     * property controls the configuration's behavior if missing properties are
     * queried: a value of <b>true</b> causes the configuration to throw an
     * exception, for a value of <b>false</b> it will return <b>null</b> values.
     * (Note: Methods returning a primitive data type will always throw an
     * exception if the property is not defined.)
     *
     * @param b the value of the property
     * @return a reference to this object for method chaining
     */
    @Override
    public BasicBuilderParameters setThrowExceptionOnMissing(boolean b)
    {
        return setProperty(PROP_THROW_EXCEPTION_ON_MISSING, Boolean.valueOf(b));
    }

    /**
     * Sets the value of the <em>listDelimiterHandler</em> property. This
     * property defines the object responsible for dealing with list delimiter
     * and escaping characters. Note:
     * {@link org.apache.commons.configuration2.AbstractConfiguration AbstractConfiguration}
     * does not allow setting this property to <b>null</b>. If the default
     * {@code ListDelimiterHandler} is to be used, do not call this method.
     *
     * @param handler the {@code ListDelimiterHandler}
     * @return a reference to this object for method chaining
     */
    @Override
    public BasicBuilderParameters setListDelimiterHandler(
            ListDelimiterHandler handler)
    {
        return setProperty(PROP_LIST_DELIMITER_HANDLER, handler);
    }

    /**
     * {@inheritDoc} The passed in {@code ConfigurationInterpolator} is set
     * without modifications.
     */
    @Override
    public BasicBuilderParameters setInterpolator(ConfigurationInterpolator ci)
    {
        return setProperty(PROP_INTERPOLATOR, ci);
    }

    /**
     * {@inheritDoc} A defensive copy of the passed in map is created. A
     * <b>null</b> argument causes all prefix lookups to be removed from the
     * internal parameters map.
     */
    @Override
    public BasicBuilderParameters setPrefixLookups(
            Map<String, ? extends Lookup> lookups)
    {
        if (lookups == null)
        {
            properties.remove(PROP_PREFIX_LOOKUPS);
            return this;
        }
        else
        {
            return setProperty(PROP_PREFIX_LOOKUPS,
                    new HashMap<String, Lookup>(lookups));
        }
    }

    /**
     * {@inheritDoc} A defensive copy of the passed in collection is created. A
     * <b>null</b> argument causes all default lookups to be removed from the
     * internal parameters map.
     */
    @Override
    public BasicBuilderParameters setDefaultLookups(
            Collection<? extends Lookup> lookups)
    {
        if (lookups == null)
        {
            properties.remove(PROP_DEFAULT_LOOKUPS);
            return this;
        }
        else
        {
            return setProperty(PROP_DEFAULT_LOOKUPS, new ArrayList<Lookup>(
                    lookups));
        }
    }

    /**
     * {@inheritDoc} This implementation stores the passed in
     * {@code ConfigurationInterpolator} object in the internal parameters map.
     */
    @Override
    public BasicBuilderParameters setParentInterpolator(
            ConfigurationInterpolator parent)
    {
        return setProperty(PROP_PARENT_INTERPOLATOR, parent);
    }

    /**
     * {@inheritDoc} This implementation stores the passed in
     * {@code Synchronizer} object in the internal parameters map.
     */
    @Override
    public BasicBuilderParameters setSynchronizer(Synchronizer sync)
    {
        return setProperty(PROP_SYNCHRONIZER, sync);
    }

    /**
     * {@inheritDoc} This implementation stores the passed in
     * {@code ConversionHandler} object in the internal parameters map.
     */
    @Override
    public BasicBuilderParameters setConversionHandler(ConversionHandler handler)
    {
        return setProperty(PROP_CONVERSION_HANDLER, handler);
    }

    /**
     * {@inheritDoc} This implementation stores the passed in {@code BeanHelper}
     * object in the internal parameters map, but uses a reserved key, so that
     * it is not used for the initialization of properties of the managed
     * configuration object. The {@code fetchBeanHelper()} method can be used to
     * obtain the {@code BeanHelper} instance from a parameters map.
     */
    @Override
    public BasicBuilderParameters setBeanHelper(BeanHelper beanHelper)
    {
        return setProperty(PROP_BEAN_HELPER, beanHelper);
    }

    /**
     * {@inheritDoc} This implementation stores the passed in
     * {@code ConfigurationDecoder} object in the internal parameters map.
     */
    @Override
    public BasicBuilderParameters setConfigurationDecoder(
            ConfigurationDecoder decoder)
    {
        return setProperty(PROP_CONFIGURATION_DECODER, decoder);
    }

    /**
     * Merges this object with the given parameters object. This method adds all
     * property values defined by the passed in parameters object to the
     * internal storage which are not already in. So properties already defined
     * in this object take precedence. Property names starting with the reserved
     * parameter prefix are ignored.
     *
     * @param p the object whose properties should be merged (must not be
     *        <b>null</b>)
     * @throws IllegalArgumentException if the passed in object is <b>null</b>
     */
    public void merge(BuilderParameters p)
    {
        if (p == null)
        {
            throw new IllegalArgumentException(
                    "Parameters to merge must not be null!");
        }

        for (Map.Entry<String, Object> e : p.getParameters().entrySet())
        {
            if (!properties.containsKey(e.getKey())
                    && !e.getKey().startsWith(RESERVED_PARAMETER_PREFIX))
            {
                storeProperty(e.getKey(), e.getValue());
            }
        }
    }

    /**
     * Inherits properties from the specified map. This can be used for instance
     * to reuse parameters from one builder in another builder - also in
     * parent-child relations in which a parent builder creates child builders.
     * The purpose of this method is to let a concrete implementation decide
     * which properties can be inherited. Because parameters are basically
     * organized as a map it would be possible to simply copy over all
     * properties from the source object. However, this is not appropriate in
     * all cases. For instance, some properties - like a
     * {@code ConfigurationInterpolator} - are tightly connected to a
     * configuration and cannot be reused in a different context. For other
     * properties, e.g. a file name, it does not make sense to copy it.
     * Therefore, an implementation has to be explicit in the properties it
     * wants to take over.
     *
     * @param source the source properties to inherit from
     * @throws IllegalArgumentException if the source map is <b>null</b>
     */
    public void inheritFrom(Map<String, ?> source)
    {
        if (source == null)
        {
            throw new IllegalArgumentException(
                    "Source properties must not be null!");
        }
        copyPropertiesFrom(source, PROP_BEAN_HELPER, PROP_CONFIGURATION_DECODER,
                PROP_CONVERSION_HANDLER, PROP_LIST_DELIMITER_HANDLER,
                PROP_LOGGER, PROP_SYNCHRONIZER,
                PROP_THROW_EXCEPTION_ON_MISSING);
    }

    /**
     * Obtains a specification for a {@link ConfigurationInterpolator} from the
     * specified map with parameters. All properties related to interpolation
     * are evaluated and added to the specification object.
     *
     * @param params the map with parameters (must not be <b>null</b>)
     * @return an {@code InterpolatorSpecification} object constructed with data
     *         from the map
     * @throws IllegalArgumentException if the map is <b>null</b> or contains
     *         invalid data
     */
    public static InterpolatorSpecification fetchInterpolatorSpecification(
            Map<String, Object> params)
    {
        checkParameters(params);
        return new InterpolatorSpecification.Builder()
                .withInterpolator(
                        fetchParameter(params, PROP_INTERPOLATOR,
                                ConfigurationInterpolator.class))
                .withParentInterpolator(
                        fetchParameter(params, PROP_PARENT_INTERPOLATOR,
                                ConfigurationInterpolator.class))
                .withPrefixLookups(fetchAndCheckPrefixLookups(params))
                .withDefaultLookups(fetchAndCheckDefaultLookups(params))
                .create();
    }

    /**
     * Obtains the {@code BeanHelper} object from the specified map with
     * parameters. This method can be used to obtain an instance from a
     * parameters map that has been set via the {@code setBeanHelper()} method.
     * If no such instance is found, result is <b>null</b>.
     *
     * @param params the map with parameters (must not be <b>null</b>)
     * @return the {@code BeanHelper} stored in this map or <b>null</b>
     * @throws IllegalArgumentException if the map is <b>null</b>
     */
    public static BeanHelper fetchBeanHelper(Map<String, Object> params)
    {
        checkParameters(params);
        return (BeanHelper) params.get(PROP_BEAN_HELPER);
    }

    /**
     * Clones this object. This is useful because multiple builder instances may
     * use a similar set of parameters. However, single instances of parameter
     * objects must not assigned to multiple builders. Therefore, cloning a
     * parameters object provides a solution for this use case. This method
     * creates a new parameters object with the same content as this one. The
     * internal map storing the parameter values is cloned, too, also collection
     * structures contained in this map. However, no a full deep clone operation
     * is performed. Objects like a {@code ConfigurationInterpolator} or
     * {@code Lookup}s are shared between this and the newly created instance.
     *
     * @return a clone of this object
     */
    @Override
    public BasicBuilderParameters clone()
    {
        try
        {
            BasicBuilderParameters copy =
                    (BasicBuilderParameters) super.clone();
            copy.properties = getParameters();
            return copy;
        }
        catch (CloneNotSupportedException cnex)
        {
            // should not happen
            throw new AssertionError(cnex);
        }
    }

    /**
     * Sets a property for this parameters object. Properties are stored in an
     * internal map. With this method a new entry can be added to this map. If
     * the value is <b>null</b>, the key is removed from the internal map. This
     * method can be used by sub classes which also store properties in a map.
     *
     * @param key the key of the property
     * @param value the value of the property
     */
    protected void storeProperty(String key, Object value)
    {
        if (value == null)
        {
            properties.remove(key);
        }
        else
        {
            properties.put(key, value);
        }
    }

    /**
     * Obtains the value of the specified property from the internal map. This
     * method can be used by derived classes if a specific property is to be
     * accessed. If the given key is not found, result is <b>null</b>.
     *
     * @param key the key of the property in question
     * @return the value of the property with this key or <b>null</b>
     */
    protected Object fetchProperty(String key)
    {
        return properties.get(key);
    }

    /**
     * Copies a number of properties from the given map into this object.
     * Properties are only copied if they are defined in the source map.
     *
     * @param source the source map
     * @param keys the keys to be copied
     */
    protected void copyPropertiesFrom(Map<String, ?> source, String... keys)
    {
        for (String key : keys)
        {
            Object value = source.get(key);
            if (value != null)
            {
                storeProperty(key, value);
            }
        }
    }

    /**
     * Helper method for setting a property value.
     *
     * @param key the key of the property
     * @param value the value of the property
     * @return a reference to this object
     */
    private BasicBuilderParameters setProperty(String key, Object value)
    {
        storeProperty(key, value);
        return this;
    }

    /**
     * Creates defensive copies for collection structures when constructing the
     * map with parameters. It should not be possible to modify this object's
     * internal state when having access to the parameters map.
     *
     * @param params the map with parameters to be passed to the caller
     */
    private static void createDefensiveCopies(HashMap<String, Object> params)
    {
        Map<String, ? extends Lookup> prefixLookups =
                fetchPrefixLookups(params);
        if (prefixLookups != null)
        {
            params.put(PROP_PREFIX_LOOKUPS, new HashMap<String, Lookup>(
                    prefixLookups));
        }
        Collection<? extends Lookup> defLookups = fetchDefaultLookups(params);
        if (defLookups != null)
        {
            params.put(PROP_DEFAULT_LOOKUPS, new ArrayList<Lookup>(defLookups));
        }
    }

    /**
     * Obtains the map with prefix lookups from the parameters map.
     *
     * @param params the map with parameters
     * @return the map with prefix lookups (may be <b>null</b>)
     */
    private static Map<String, ? extends Lookup> fetchPrefixLookups(
            Map<String, Object> params)
    {
        // This is safe to cast because we either have full control over the map
        // and thus know the types of the contained values or have checked
        // the content before
        @SuppressWarnings("unchecked")
        Map<String, ? extends Lookup> prefixLookups =
                (Map<String, ? extends Lookup>) params.get(PROP_PREFIX_LOOKUPS);
        return prefixLookups;
    }

    /**
     * Tests whether the passed in map with parameters contains a map with
     * prefix lookups. This method is used if the parameters map is from an
     * insecure source and we cannot be sure that it contains valid data.
     * Therefore, we have to map that the key for the prefix lookups actually
     * points to a map containing keys and values of expected data types.
     *
     * @param params the parameters map
     * @return the obtained map with prefix lookups
     * @throws IllegalArgumentException if the map contains invalid data
     */
    private static Map<String, ? extends Lookup> fetchAndCheckPrefixLookups(
            Map<String, Object> params)
    {
        Map<?, ?> prefixes =
                fetchParameter(params, PROP_PREFIX_LOOKUPS, Map.class);
        if (prefixes == null)
        {
            return null;
        }

        for (Map.Entry<?, ?> e : prefixes.entrySet())
        {
            if (!(e.getKey() instanceof String)
                    || !(e.getValue() instanceof Lookup))
            {
                throw new IllegalArgumentException(
                        "Map with prefix lookups contains invalid data: "
                                + prefixes);
            }
        }
        return fetchPrefixLookups(params);
    }

    /**
     * Obtains the collection with default lookups from the parameters map.
     *
     * @param params the map with parameters
     * @return the collection with default lookups (may be <b>null</b>)
     */
    private static Collection<? extends Lookup> fetchDefaultLookups(
            Map<String, Object> params)
    {
        // This is safe to cast because we either have full control over the map
        // and thus know the types of the contained values or have checked
        // the content before
        @SuppressWarnings("unchecked")
        Collection<? extends Lookup> defLookups =
                (Collection<? extends Lookup>) params.get(PROP_DEFAULT_LOOKUPS);
        return defLookups;
    }

    /**
     * Tests whether the passed in map with parameters contains a valid
     * collection with default lookups. This method works like
     * {@link #fetchAndCheckPrefixLookups(Map)}, but tests the default lookups
     * collection.
     *
     * @param params the map with parameters
     * @return the collection with default lookups (may be <b>null</b>)
     * @throws IllegalArgumentException if invalid data is found
     */
    private static Collection<? extends Lookup> fetchAndCheckDefaultLookups(
            Map<String, Object> params)
    {
        Collection<?> col =
                fetchParameter(params, PROP_DEFAULT_LOOKUPS, Collection.class);
        if (col == null)
        {
            return null;
        }

        for (Object o : col)
        {
            if (!(o instanceof Lookup))
            {
                throw new IllegalArgumentException(
                        "Collection with default lookups contains invalid data: "
                                + col);
            }
        }
        return fetchDefaultLookups(params);
    }

    /**
     * Obtains a parameter from a map and performs a type check.
     *
     * @param params the map with parameters
     * @param key the key of the parameter
     * @param expClass the expected class of the parameter value
     * @param <T> the parameter type
     * @return the value of the parameter in the correct data type
     * @throws IllegalArgumentException if the parameter is not of the expected
     *         type
     */
    private static <T> T fetchParameter(Map<String, Object> params, String key,
            Class<T> expClass)
    {
        Object value = params.get(key);
        if (value == null)
        {
            return null;
        }
        if (!expClass.isInstance(value))
        {
            throw new IllegalArgumentException(String.format(
                    "Parameter %s is not of type %s!", key,
                    expClass.getSimpleName()));
        }
        return expClass.cast(value);
    }

    /**
     * Checks whether a map with parameters is present. Throws an exception if
     * not.
     *
     * @param params the map with parameters to check
     * @throws IllegalArgumentException if the map is <b>null</b>
     */
    private static void checkParameters(Map<String, Object> params)
    {
        if (params == null)
        {
            throw new IllegalArgumentException(
                    "Parameters map must not be null!");
        }
    }
}
