    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *     http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017
    018package org.apache.commons.configuration2;
    019
    020import java.util.AbstractMap;
    021import java.util.AbstractSet;
    022import java.util.Iterator;
    023import java.util.Map;
    024import java.util.Set;
    025
    026/**
    027 * <p>The {@code ConfigurationMap} wraps a
    028 * configuration-collection
    029 * {@link org.apache.commons.configuration2.Configuration}
    030 * instance to provide a {@code Map} interface.</p>
    031 *
    032 * <p><em>Note:</em> This implementation is incomplete.</p>
    033 *
    034 * @since 1.0
    035 */
    036public class ConfigurationMap extends AbstractMap<Object, Object>
    037{
    038    /**
    039     * The {@code Configuration} wrapped by this class.
    040     */
    041    private final Configuration configuration;
    042
    043    /**
    044     * Creates a new instance of a {@code ConfigurationMap}
    045     * that wraps the specified {@code Configuration}
    046     * instance.
    047     * @param configuration {@code Configuration}
    048     * instance.
    049     */
    050    public ConfigurationMap(final Configuration configuration)
    051    {
    052        this.configuration = configuration;
    053    }
    054
    055    /**
    056     * Returns the wrapped {@code Configuration} object.
    057     *
    058     * @return the wrapped configuration
    059     * @since 1.2
    060     */
    061    public Configuration getConfiguration()
    062    {
    063        return configuration;
    064    }
    065
    066    /**
    067     * Returns a set with the entries contained in this configuration-based map.
    068     *
    069     * @return a set with the contained entries
    070     * @see java.util.Map#entrySet()
    071     */
    072    @Override
    073    public Set<Map.Entry<Object, Object>> entrySet()
    074    {
    075        return new ConfigurationSet(configuration);
    076    }
    077
    078    /**
    079     * Stores the value for the specified key. The value is stored in the
    080     * underlying configuration.
    081     *
    082     * @param key the key (will be converted to a string)
    083     * @param value the value
    084     * @return the old value of this key or <b>null</b> if it is new
    085     * @see java.util.Map#put(java.lang.Object, java.lang.Object)
    086     */
    087    @Override
    088    public Object put(final Object key, final Object value)
    089    {
    090        final String strKey = String.valueOf(key);
    091        final Object old = configuration.getProperty(strKey);
    092        configuration.setProperty(strKey, value);
    093        return old;
    094    }
    095
    096    /**
    097     * Returns the value of the specified key. The key is converted to a string
    098     * and then passed to the underlying configuration.
    099     *
    100     * @param key the key
    101     * @return the value of this key
    102     * @see java.util.Map#get(java.lang.Object)
    103     */
    104    @Override
    105    public Object get(final Object key)
    106    {
    107        return configuration.getProperty(String.valueOf(key));
    108    }
    109
    110    /**
    111     * Set of entries in the map.
    112     */
    113    static class ConfigurationSet extends AbstractSet<Map.Entry<Object, Object>>
    114    {
    115        /** The configuration mapped to this entry set. */
    116        private final Configuration configuration;
    117
    118        /**
    119         * A Map entry in the ConfigurationMap.
    120         */
    121        private final class Entry implements Map.Entry<Object, Object>
    122        {
    123            /** The key of the map entry. */
    124            private final Object key;
    125
    126            private Entry(final Object key)
    127            {
    128                this.key = key;
    129            }
    130
    131            @Override
    132            public Object getKey()
    133            {
    134                return key;
    135            }
    136
    137            @Override
    138            public Object getValue()
    139            {
    140                return configuration.getProperty((String) key);
    141            }
    142
    143            @Override
    144            public Object setValue(final Object value)
    145            {
    146                final Object old = getValue();
    147                configuration.setProperty((String) key, value);
    148                return old;
    149            }
    150        }
    151
    152        /**
    153         * Iterator over the entries in the ConfigurationMap.
    154         */
    155        private final class ConfigurationSetIterator implements Iterator<Map.Entry<Object, Object>>
    156        {
    157            /** An iterator over the keys in the configuration. */
    158            private final Iterator<String> keys;
    159
    160            private ConfigurationSetIterator()
    161            {
    162                keys = configuration.getKeys();
    163            }
    164
    165            @Override
    166            public boolean hasNext()
    167            {
    168                return keys.hasNext();
    169            }
    170
    171            @Override
    172            public Map.Entry<Object, Object> next()
    173            {
    174                return new Entry(keys.next());
    175            }
    176
    177            @Override
    178            public void remove()
    179            {
    180                keys.remove();
    181            }
    182        }
    183
    184        ConfigurationSet(final Configuration configuration)
    185        {
    186            this.configuration = configuration;
    187        }
    188
    189        /**
    190         * @see java.util.Collection#size()
    191         */
    192        @Override
    193        public int size()
    194        {
    195            // Ouch. Now _that_ one is expensive...
    196            int count = 0;
    197            for (final Iterator<String> iterator = configuration.getKeys(); iterator.hasNext();)
    198            {
    199                iterator.next();
    200                count++;
    201            }
    202            return count;
    203        }
    204
    205        /**
    206         * @see java.util.Collection#iterator()
    207         */
    208        @Override
    209        public Iterator<Map.Entry<Object, Object>> iterator()
    210        {
    211            return new ConfigurationSetIterator();
    212        }
    213    }
    214}