/* * Copyright 2007-2013 * Licensed under GNU Lesser General Public License * * This file is part of EpochX * * EpochX 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 3 of the License, or * (at your option) any later version. * * EpochX 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 EpochX. If not, see <http://www.gnu.org/licenses/>. * * The latest version is available from: http://www.epochx.org */ package org.epochx; import java.util.HashMap; import java.util.Map; import org.epochx.event.ConfigEvent; import org.epochx.event.EventManager; /** * The <code>Config</code> class provides a centralised store for configuration * parameters. It uses a singleton which is obtainable with the * <code>getInstance</code> method. Each parameter is referenced with a * {@link ConfigKey} which is used to both set new parameters and retrieve * existing parameter values. the key also constrains the data-type of the * parameter value with its generic type. * * @see ConfigKey */ public class Config { /** * The singleton instance. */ private static final Config singleton = new Config(); /** * The key -> value mapping. */ private final HashMap<ConfigKey<?>, Object> mapping = new HashMap<ConfigKey<?>, Object>(); /** * No instance are allowed, appart from the singleton. * */ private Config() { } /** * Returns the singleton <code>Config</code> instance. * * @return the singleton <code>Config</code> instance */ public static Config getInstance() { return singleton; } /** * Sets the value of the specified configuration key. If the given key * already has a value associated with it, then it will be overwritten. The * value is constrained to be of the correct object type as defined by the * generic type of the key. Calling this method will trigger the firing of a * new configuration event after the configuration option has been set. * * @param key the <code>ConfigKey</code> for the configuration parameter * that a new value is to be set for * @param value the new value to set for the specified configuration key */ public <T> void set(ConfigKey<T> key, T value) { mapping.put(key, value); EventManager.getInstance().fire(new ConfigEvent(key)); } /** * Retrieves the value of the configuration parameter associated with the * specified key. If no value has been set for the given key then * <code>null</code> is returned. * * @param key the <code>ConfigKey</code> for the configuration parameter * to retrieve * @return the value of the specified configuration parameter, or * <code>null</code> if it has not been set. The object type is * defined by the generic type of the key. */ public <T> T get(ConfigKey<T> key) { return get(key, null); } /** * Retrieves the value of the configuration parameter associated with the * specified key. If the parameter has not been set, the value will be * retrived from the <code>Template</code> object. * * @param key the <code>ConfigKey</code> for the configuration parameter * to retrieve * @param defaultValue the default value to be returned if the parameter * has not been set * @return the value of the specified configuration parameter, or * <code>null</code> if it has not been set. The object type is * defined by the generic type of the key. */ @SuppressWarnings("unchecked") public <T> T get(ConfigKey<T> key, T defaultValue) { T value = (T) mapping.get(key); if (value == null) { Template template = (Template) mapping.get(Template.TEMPLATE); return (template == null) ? defaultValue : template.get(key, defaultValue); } return value; } /** * This method was originally designed to initialize the default values. The preferred * method is to specify a {@link Template} object using the {@link #set(ConfigKey, Object)}. * Calls to this method will initialize the configuration with the {@link GenerationalTemplate}. */ @Deprecated public void defaults() { set(Template.TEMPLATE, new GenerationalTemplate()); } /** * Removes all configuration parameter mapping. The configuration will be * empty this call returns. */ public void reset() { mapping.clear(); } /** * Instances of <code>ConfigKey</code> are used to uniquely identify * configuration parameters. The generic type <code>T</code> defines a * constraint upon the object type of the parameter's value. * * @param <T> the required object type of values for this parameter */ public static class ConfigKey<T> {} /** * The <code>Template</code> class provides a mechanism for setting default * configuration parameter values. */ public abstract static class Template { /** * The key for setting <code>Template</code> parameter. */ public final static ConfigKey<Template> TEMPLATE = new ConfigKey<Template>(); /** * The key -> value mapping. */ private final HashMap<ConfigKey<?>, Object> template = new HashMap<ConfigKey<?>, Object>(1); /** * Constructs a new <code>Template</code>. */ public Template() { fill(template); } /** * Sets the default configuration parameters. * * @param template the default configuration parameters mapping. */ protected abstract void fill(Map<ConfigKey<?>, Object> template); /** * Retrieves the value of the configuration parameter associated with the * specified key. * * @param key the <code>ConfigKey</code> for the configuration parameter * to retrieve * @param defaultValue the default value to be returned if the parameter * has not been set * @return the value of the specified configuration parameter, or * <code>null</code> if it has not been set. The object type is * defined by the generic type of the key. */ @SuppressWarnings("unchecked") private <T> T get(ConfigKey<T> key, T defaultValue) { T value = (T) template.get(key); return (value == null) ? defaultValue : value; } } }