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