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