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