001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2015 ForgeRock AS.
015 */
016package org.forgerock.util;
017
018import static java.util.Collections.unmodifiableMap;
019
020import java.util.IdentityHashMap;
021import java.util.Map;
022
023/**
024 * A set of options which can be used for customizing the behavior of HTTP
025 * clients and servers. Refer to the appropriate class for the list of supported
026 * options.
027 */
028public final class Options {
029    private static final Options DEFAULT = unmodifiableCopyOf(defaultOptions());
030
031    /**
032     * Returns a copy of the provided set of options.
033     *
034     * @param options
035     *            The options to be copied.
036     * @return A copy of the provided set of options.
037     */
038    public static Options copyOf(final Options options) {
039        return new Options(new IdentityHashMap<>(options.map));
040    }
041
042    /**
043     * Returns a new set of options with default settings.
044     *
045     * @return A new set of options with default settings.
046     */
047    public static Options defaultOptions() {
048        return new Options(new IdentityHashMap<Option<?>, Object>());
049    }
050
051    /**
052     * Returns an unmodifiable copy of the provided set of options.
053     *
054     * @param options
055     *            The options to be copied.
056     * @return An unmodifiable copy of the provided set of options.
057     */
058    public static Options unmodifiableCopyOf(final Options options) {
059        return new Options(unmodifiableMap(new IdentityHashMap<>(options.map)));
060    }
061
062    /**
063     * Returns an unmodifiable set of options with default settings.
064     *
065     * @return An unmodifiable set of options with default settings.
066     */
067    public static Options unmodifiableDefaultOptions() {
068        return DEFAULT;
069    }
070
071    private final Map<Option<?>, Object> map;
072
073    private Options(final Map<Option<?>, Object> optionsMap) {
074        this.map = optionsMap;
075    }
076
077    /**
078     * Returns the value associated with the provided option, or its default
079     * value if the option has not been configured.
080     *
081     * @param <T>
082     *            The option type.
083     * @param option
084     *            The option whose associated value is to be returned.
085     * @return The value associated with the provided option, or its default
086     *         value if the option has not been configured.
087     */
088    public <T> T get(final Option<T> option) {
089        return option.getValue(map.get(option));
090    }
091
092    /**
093     * Resets an option to its default behavior.
094     *
095     * @param <T>
096     *            The option type.
097     * @param option
098     *            The option whose value is to be reset.
099     * @return This set of options.
100     * @throws UnsupportedOperationException
101     *             If this set of options is unmodifiable.
102     */
103    public <T> Options reset(final Option<T> option) {
104        map.remove(option);
105        return this;
106    }
107
108    /**
109     * Sets an option to the provided value. If this set of options previously
110     * contained a mapping for the option, the old value is replaced by the
111     * specified value.
112     *
113     * @param <T>
114     *            The option type.
115     * @param option
116     *            The option whose value is to be set.
117     * @param value
118     *            The option value.
119     * @return This set of options.
120     * @throws UnsupportedOperationException
121     *             If this set of options is unmodifiable.
122     */
123    public <T> Options set(final Option<T> option, final T value) {
124        map.put(option, value);
125        return this;
126    }
127
128}