All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jboss.xnio.OptionMap Maven / Gradle / Ivy

There is a newer version: 3.8.16.Final
Show newest version
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2009, JBoss Inc., and individual contributors as indicated
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.jboss.xnio;

import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Properties;
import java.io.Serializable;
import org.jboss.xnio.log.Logger;

/**
 * An immutable map of options to option values.  No {@code null} keys or values are permitted.
 */
public final class OptionMap implements Iterable>, Serializable {

    private static final long serialVersionUID = 3632842565346928132L;

    private final Map, Object> value;

    private OptionMap(final Map, Object> value) {
        this.value = value;
    }

    /**
     * Determine whether this option map contains the given option.
     *
     * @param option the option to check
     * @return {@code true} if the option is present in the option map
     */
    public boolean contains(Option option) {
        return value.containsKey(option);
    }

    /**
     * Get the value of an option from this option map.
     *
     * @param option the option to get
     * @param  the type of the option
     * @return the option value, or {@code null} if it is not present
     */
    public  T get(Option option) {
        return option.cast(value.get(option));
    }

    /**
     * Get the value of an option from this option map, with a specified default if the value is missing.
     *
     * @param option the option to get
     * @param  the type of the option
     * @return the option value, or {@code null} if it is not present
     */
    public  T get(Option option, T defaultValue) {
        final Object o = value.get(option);
        return o == null ? defaultValue : option.cast(o);
    }

    /**
     * Get a boolean value from this option map, with a specified default if the value is missing.
     *
     * @param option the option to get
     * @param defaultValue the default value if the option is not present
     * @return the result
     */
    public boolean get(Option option, boolean defaultValue) {
        final Object o = value.get(option);
        return o == null ? defaultValue : option.cast(o).booleanValue();
    }

    /**
     * Get a int value from this option map, with a specified default if the value is missing.
     *
     * @param option the option to get
     * @param defaultValue the default value if the option is not present
     * @return the result
     */
    public int get(Option option, int defaultValue) {
        final Object o = value.get(option);
        return o == null ? defaultValue : option.cast(o).intValue();
    }

    /**
     * Get a long value from this option map, with a specified default if the value is missing.
     *
     * @param option the option to get
     * @param defaultValue the default value if the option is not present
     * @return the result
     */
    public long get(Option option, long defaultValue) {
        final Object o = value.get(option);
        return o == null ? defaultValue : option.cast(o).longValue();
    }

    /**
     * Iterate over the options in this map.
     *
     * @return an iterator over the options
     */
    public Iterator> iterator() {
        return Collections.unmodifiableCollection(value.keySet()).iterator();
    }

    /**
     * Get the number of options stored in this map.
     *
     * @return the number of options
     */
    public int size() {
        return value.size();
    }

    /**
     * The empty option map.
     */
    public static final OptionMap EMPTY = new OptionMap(Collections., Object>emptyMap());

    /**
     * Create a new builder.
     *
     * @return a new builder
     */
    public static Builder builder() {
        return new Builder();
    }

    /**
     * A builder for immutable option maps.  Create an instance with the {@link OptionMap#builder()} method.
     */
    public static final class Builder {

        private static final Logger log = Logger.getLogger("org.jboss.xnio.option.parse");

        private Builder() {
        }

        private static class OVPair {
            Option option;
            T value;

            private OVPair(final Option option, final T value) {
                this.option = option;
                this.value = value;
            }
        }

        private List> list = new ArrayList>();

        /**
         * Set a key-value pair, parsing the value from the given string.
         *
         * @param key the key
         * @param stringValue the string value
         * @param  the option type
         * @return this builder
         */
        public  Builder parse(Option key, String stringValue) {
            set(key, key.parseValue(stringValue));
            return this;
        }

        /**
         * Add all options from a properties file.  Finds all entries which start with a given prefix; the remainder
         * of the property key (after the prefix) is the option name, and the value is the option value.
         *
         * @param props the properties to read
         * @param prefix the prefix
         * @param optionClassLoader the class loader to use to resolve option names
         * @return this builder
         */
        public Builder parseAll(Properties props, String prefix, ClassLoader optionClassLoader) {
            for (String name : props.stringPropertyNames()) {
                if (name.startsWith(prefix)) {
                    final String optionName = name.substring(prefix.length());
                    try {
                        final Option option = Option.fromString(optionName, optionClassLoader);
                        parse(option, props.getProperty(name));
                    } catch (IllegalArgumentException e) {
                        log.warn("Invalid option '%s' in property '%s': %s", optionName, name, e);
                    }
                }
            }
            return this;
        }

        /**
         * Add all options from a properties file.  Finds all entries which start with a given prefix; the remainder
         * of the property key (after the prefix) is the option name, and the value is the option value.
         *
         * @param props the properties to read
         * @param prefix the prefix
         * @return this builder
         */
        public Builder parseAll(Properties props, String prefix) {
            for (String name : props.stringPropertyNames()) {
                if (name.startsWith(prefix)) {
                    final String optionName = name.substring(prefix.length());
                    try {
                        final Option option = Option.fromString(optionName, null);
                        parse(option, props.getProperty(name));
                    } catch (IllegalArgumentException e) {
                        log.warn("Invalid option '%s' in property '%s': %s", optionName, name, e);
                    }
                }
            }
            return this;
        }

        /**
         * Set a key-value pair.
         *
         * @param key the key
         * @param value the value
         * @param  the option type
         * @return this builder
         */
        public  Builder set(Option key, T value) {
            if (value == null) {
                throw new NullPointerException("value is null");
            }
            list.add(new OVPair(key, value));
            return this;
        }

        /**
         * Set an int value for an Integer key.
         *
         * @param key the option
         * @param value the value
         * @return this builder
         */
        public Builder set(Option key, int value) {
            list.add(new OVPair(key, Integer.valueOf(value)));
            return this;
        }

        /**
         * Set int values for an Integer sequence key.
         *
         * @param key the key
         * @param values the values
         * @return this builder
         */
        public Builder setSequence(Option> key, int... values) {
            Integer[] a = new Integer[values.length];
            for (int i = 0; i < values.length; i++) {
                a[i] = Integer.valueOf(values[i]);
            }
            list.add(new OVPair>(key, Sequence.of(a)));
            return this;
        }

        /**
         * Set a long value for a Long key.
         *
         * @param key the option
         * @param value the value
         * @return this builder
         */
        public Builder set(Option key, long value) {
            list.add(new OVPair(key, Long.valueOf(value)));
            return this;
        }

        /**
         * Set long values for a Long sequence key.
         *
         * @param key the key
         * @param values the values
         * @return this builder
         */
        public Builder setSequence(Option> key, long... values) {
            Long[] a = new Long[values.length];
            for (int i = 0; i < values.length; i++) {
                a[i] = Long.valueOf(values[i]);
            }
            list.add(new OVPair>(key, Sequence.of(a)));
            return this;
        }

        /**
         * Set a boolean value for a Boolean key.
         *
         * @param key the option
         * @param value the value
         * @return this builder
         */
        public Builder set(Option key, boolean value) {
            list.add(new OVPair(key, Boolean.valueOf(value)));
            return this;
        }


        /**
         * Set boolean values for an Boolean sequence key.
         *
         * @param key the key
         * @param values the values
         * @return this builder
         */
        public Builder setSequence(Option> key, boolean... values) {
            Boolean[] a = new Boolean[values.length];
            for (int i = 0; i < values.length; i++) {
                a[i] = Boolean.valueOf(values[i]);
            }
            list.add(new OVPair>(key, Sequence.of(a)));
            return this;
        }

        /**
         * Set a key-value pair, where the value is a sequence type.
         *
         * @param key the key
         * @param values the values
         * @param  the option type
         * @return this builder
         */
        public  Builder setSequence(Option> key, T... values) {
            list.add(new OVPair>(key, Sequence.of(values)));
            return this;
        }

        private  void copy(Map map, Option option) {
            set(option, option.cast(map.get(option)));
        }

        /**
         * Add all the entries of a map.  Any keys of the map which are not valid {@link Option}s, or whose
         * values are not valid arguments for the given {@code Option}, will cause an exception to be thrown.
         * Any keys which occur more than once in this builder will be overwritten with the last occurring value.
         *
         * @param map the map
         * @return this builder
         * @throws ClassCastException if any entries of the map are not valid option-value pairs
         */
        public Builder add(Map map) throws ClassCastException {
            for (Object key : map.keySet()) {
                final Option option = Option.class.cast(key);
                copy(map, option);
            }
            return this;
        }

        private  void copy(OptionMap optionMap, Option option) {
            set(option, optionMap.get(option));
        }

        /**
         * Add all entries from an existing option map to the one being built.
         * Any keys which occur more than once in this builder will be overwritten with the last occurring value.
         *
         * @param optionMap the original option map
         * @return this builder
         */
        public Builder addAll(OptionMap optionMap) {
            for (Option option : optionMap) {
                copy(optionMap, option);
            }
            return this;
        }

        /**
         * Build a map that reflects the current state of this builder.
         *
         * @return the new immutable option map
         */
        public OptionMap getMap() {
            final List> list = this.list;
            if (list.size() == 0) {
                return EMPTY;
            } else if (list.size() == 1) {
                final OVPair pair = list.get(0);
                return new OptionMap(Collections., Object>singletonMap(pair.option, pair.value));
            } else {
                final Map, Object> map = new IdentityHashMap, Object>();
                for (OVPair ovPair : list) {
                    map.put(ovPair.option, ovPair.value);
                }
                return new OptionMap(map);
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy