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