/*
 * 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;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.configuration2.ex.ConfigurationRuntimeException;

/**
 * <p>
 * A Map based Configuration.
 * </p>
 * <p>
 * This implementation of the {@code Configuration} interface is
 * initialized with a {@code java.util.Map}. The methods of the
 * {@code Configuration} interface are implemented on top of the content of
 * this map. The following storage scheme is used:
 * </p>
 * <p>
 * Property keys are directly mapped to map keys, i.e. the
 * {@code getProperty()} method directly performs a {@code get()} on
 * the map. Analogously, {@code setProperty()} or
 * {@code addProperty()} operations write new data into the map. If a value
 * is added to an existing property, a {@code java.util.List} is created,
 * which stores the values of this property.
 * </p>
 * <p>
 * An important use case of this class is to treat a map as a
 * {@code Configuration} allowing access to its data through the richer
 * interface. This can be a bit problematic in some cases because the map may
 * contain values that need not adhere to the default storage scheme used by
 * typical configuration implementations, e.g. regarding lists. In such cases
 * care must be taken when manipulating the data through the
 * {@code Configuration} interface, e.g. by calling
 * {@code addProperty()}; results may be different than expected.
 * </p>
 * <p>
 * The handling of list delimiters is a bit different for this configuration
 * implementation: When a property of type String is queried, it is passed to
 * the current {@link org.apache.commons.configuration2.convert.ListDelimiterHandler
 * ListDelimiterHandler} which may generate multiple values.
 * Note that per default a list delimiter handler is set which does not do any
 * list splitting, so this feature is disabled. It can be enabled by setting
 * a properly configured {@code ListDelimiterHandler} implementation, e.g. a
 * {@link org.apache.commons.configuration2.convert.DefaultListDelimiterHandler
 * DefaultListDelimiterHandler} object.
 * </p>
 * <p>
 * Notice that list splitting is only performed for single string values. If a
 * property has multiple values, the single values are not split even if they
 * contain the list delimiter character.
 * </p>
 * <p>
 * As the underlying {@code Map} is directly used as store of the property
 * values, the thread-safety of this {@code Configuration} implementation
 * depends on the map passed to the constructor.
 * </p>
 * <p>
 * Notes about type safety: For properties with multiple values this implementation
 * creates lists of type {@code Object} and stores them. If a property is assigned
 * another value, the value is added to the list. This can cause problems if the
 * map passed to the constructor already contains lists of other types. This
 * should be avoided, otherwise it cannot be guaranteed that the application
 * might throw {@code ClassCastException} exceptions later.
 * </p>
 *
 * @author Emmanuel Bourg
 * @version $Id$
 * @since 1.1
 */
public class MapConfiguration extends AbstractConfiguration implements Cloneable
{
    /** The Map decorated by this configuration. */
    protected Map<String, Object> map;

    /** A flag whether trimming of property values should be disabled.*/
    private boolean trimmingDisabled;

    /**
     * Create a Configuration decorator around the specified Map. The map is
     * used to store the configuration properties, any change will also affect
     * the Map.
     *
     * @param map the map
     */
    public MapConfiguration(Map<String, ?> map)
    {
        this.map = (Map<String, Object>) map;
    }

    /**
     * Creates a new instance of {@code MapConfiguration} which uses the
     * specified {@code Properties} object as its data store. All changes of
     * this configuration affect the given {@code Properties} object and
     * vice versa. Note that while {@code Properties} actually
     * implements {@code Map<Object, Object>}, we expect it to contain only
     * string keys. Other key types will lead to {@code ClassCastException}
     * exceptions on certain methods.
     *
     * @param props the {@code Properties} object defining the content of this
     *        configuration
     * @since 1.8
     */
    public MapConfiguration(Properties props)
    {
        map = convertPropertiesToMap(props);
    }

    /**
     * Return the Map decorated by this configuration.
     *
     * @return the map this configuration is based onto
     */
    public Map<String, Object> getMap()
    {
        return map;
    }

    /**
     * Returns the flag whether trimming of property values is disabled.
     *
     * @return <b>true</b> if trimming of property values is disabled;
     *         <b>false</b> otherwise
     * @since 1.7
     */
    public boolean isTrimmingDisabled()
    {
        return trimmingDisabled;
    }

    /**
     * Sets a flag whether trimming of property values is disabled. This flag is
     * only evaluated if list splitting is enabled. Refer to the header comment
     * for more information about list splitting and trimming.
     *
     * @param trimmingDisabled a flag whether trimming of property values should
     *        be disabled
     * @since 1.7
     */
    public void setTrimmingDisabled(boolean trimmingDisabled)
    {
        this.trimmingDisabled = trimmingDisabled;
    }

    @Override
    protected Object getPropertyInternal(String key)
    {
        Object value = map.get(key);
        if (value instanceof String)
        {
            Collection<String> list = getListDelimiterHandler().split((String) value, !isTrimmingDisabled());
            return list.size() > 1 ? list : list.iterator().next();
        }
        else
        {
            return value;
        }
    }

    @Override
    protected void addPropertyDirect(String key, Object value)
    {
        Object previousValue = getProperty(key);

        if (previousValue == null)
        {
            map.put(key, value);
        }
        else if (previousValue instanceof List)
        {
            // the value is added to the existing list
            // Note: This is problematic. See header comment!
            ((List<Object>) previousValue).add(value);
        }
        else
        {
            // the previous value is replaced by a list containing the previous value and the new value
            List<Object> list = new ArrayList<Object>();
            list.add(previousValue);
            list.add(value);

            map.put(key, list);
        }
    }

    @Override
    protected boolean isEmptyInternal()
    {
        return map.isEmpty();
    }

    @Override
    protected boolean containsKeyInternal(String key)
    {
        return map.containsKey(key);
    }

    @Override
    protected void clearPropertyDirect(String key)
    {
        map.remove(key);
    }

    @Override
    protected Iterator<String> getKeysInternal()
    {
        return map.keySet().iterator();
    }

    @Override
    protected int sizeInternal()
    {
        return map.size();
    }

    /**
     * Returns a copy of this object. The returned configuration will contain
     * the same properties as the original. Event listeners are not cloned.
     *
     * @return the copy
     * @since 1.3
     */
    @Override
    public Object clone()
    {
        try
        {
            MapConfiguration copy = (MapConfiguration) super.clone();
            // Safe because ConfigurationUtils returns a map of the same types.
            @SuppressWarnings("unchecked")
            Map<String, Object> clonedMap = (Map<String, Object>) ConfigurationUtils.clone(map);
            copy.map = clonedMap;
            copy.cloneInterpolator(this);
            return copy;
        }
        catch (CloneNotSupportedException cex)
        {
            // cannot happen
            throw new ConfigurationRuntimeException(cex);
        }
    }

    /**
     * Helper method for converting the type of the {@code Properties} object
     * to a supported map type. As stated by the comment of the constructor,
     * we expect the {@code Properties} object to contain only String key;
     * therefore, it is safe to do this cast.
     *
     * @param props the {@code Properties} to be copied
     * @return a newly created map with all string keys of the properties
     */
    @SuppressWarnings("unchecked")
    private static Map<String, Object> convertPropertiesToMap(Properties props)
    {
        @SuppressWarnings("rawtypes")
        Map map = props;
        return map;
    }
}
