    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 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 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 <strong>null</strong> if it is new
    184     * @see 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}