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 * @author <a href="mailto:ricardo.gladwell@btinternet.com">Ricardo Gladwell</a>
035 * @since 1.0
036 */
037public class ConfigurationMap extends AbstractMap<Object, Object>
038{
039    /**
040     * The {@code Configuration} wrapped by this class.
041     */
042    private final Configuration configuration;
043
044    /**
045     * Creates a new instance of a {@code ConfigurationMap}
046     * that wraps the specified {@code Configuration}
047     * instance.
048     * @param configuration {@code Configuration}
049     * instance.
050     */
051    public ConfigurationMap(final Configuration configuration)
052    {
053        this.configuration = configuration;
054    }
055
056    /**
057     * Returns the wrapped {@code Configuration} object.
058     *
059     * @return the wrapped configuration
060     * @since 1.2
061     */
062    public Configuration getConfiguration()
063    {
064        return configuration;
065    }
066
067    /**
068     * Returns a set with the entries contained in this configuration-based map.
069     *
070     * @return a set with the contained entries
071     * @see java.util.Map#entrySet()
072     */
073    @Override
074    public Set<Map.Entry<Object, Object>> entrySet()
075    {
076        return new ConfigurationSet(configuration);
077    }
078
079    /**
080     * Stores the value for the specified key. The value is stored in the
081     * underlying configuration.
082     *
083     * @param key the key (will be converted to a string)
084     * @param value the value
085     * @return the old value of this key or <b>null</b> if it is new
086     * @see java.util.Map#put(java.lang.Object, java.lang.Object)
087     */
088    @Override
089    public Object put(final Object key, final Object value)
090    {
091        final String strKey = String.valueOf(key);
092        final Object old = configuration.getProperty(strKey);
093        configuration.setProperty(strKey, value);
094        return old;
095    }
096
097    /**
098     * Returns the value of the specified key. The key is converted to a string
099     * and then passed to the underlying configuration.
100     *
101     * @param key the key
102     * @return the value of this key
103     * @see java.util.Map#get(java.lang.Object)
104     */
105    @Override
106    public Object get(final Object key)
107    {
108        return configuration.getProperty(String.valueOf(key));
109    }
110
111    /**
112     * Set of entries in the map.
113     */
114    static class ConfigurationSet extends AbstractSet<Map.Entry<Object, Object>>
115    {
116        /** The configuration mapped to this entry set. */
117        private final Configuration configuration;
118
119        /**
120         * A Map entry in the ConfigurationMap.
121         */
122        private final class Entry implements Map.Entry<Object, Object>
123        {
124            /** The key of the map entry. */
125            private final Object key;
126
127            private Entry(final Object key)
128            {
129                this.key = key;
130            }
131
132            @Override
133            public Object getKey()
134            {
135                return key;
136            }
137
138            @Override
139            public Object getValue()
140            {
141                return configuration.getProperty((String) key);
142            }
143
144            @Override
145            public Object setValue(final Object value)
146            {
147                final Object old = getValue();
148                configuration.setProperty((String) key, value);
149                return old;
150            }
151        }
152
153        /**
154         * Iterator over the entries in the ConfigurationMap.
155         */
156        private final class ConfigurationSetIterator implements Iterator<Map.Entry<Object, Object>>
157        {
158            /** An iterator over the keys in the configuration. */
159            private final Iterator<String> keys;
160
161            private ConfigurationSetIterator()
162            {
163                keys = configuration.getKeys();
164            }
165
166            @Override
167            public boolean hasNext()
168            {
169                return keys.hasNext();
170            }
171
172            @Override
173            public Map.Entry<Object, Object> next()
174            {
175                return new Entry(keys.next());
176            }
177
178            @Override
179            public void remove()
180            {
181                keys.remove();
182            }
183        }
184
185        ConfigurationSet(final Configuration configuration)
186        {
187            this.configuration = configuration;
188        }
189
190        /**
191         * @see java.util.Collection#size()
192         */
193        @Override
194        public int size()
195        {
196            // Ouch. Now _that_ one is expensive...
197            int count = 0;
198            for (final Iterator<String> iterator = configuration.getKeys(); iterator.hasNext();)
199            {
200                iterator.next();
201                count++;
202            }
203            return count;
204        }
205
206        /**
207         * @see java.util.Collection#iterator()
208         */
209        @Override
210        public Iterator<Map.Entry<Object, Object>> iterator()
211        {
212            return new ConfigurationSetIterator();
213        }
214    }
215}