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}