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

cl.core.configurable.Configurable Maven / Gradle / Ivy

The newest version!
package cl.core.configurable;

import java.util.Set;
import java.util.stream.Stream;

/**
 * A {@code Configurable} object is an object who's behavior may be altered prior to its use by changing
 * the object's configuration parameters.
 * 
 * 

A configurable object exposes its parameters via strongly typed {@link Key}s. Every key has * a name, a type, and a default value. The default values are mandatory, so that configurable objects * behave sensibly even when created without altering configuration. A key default value * is evaluated lazily to avoid unnecessary computations prior to actual configuration setting usage. * *

Once the configuration settings are set on a configurable object, the object should be locked * before calling methods on it. This behavior prevents changes in configuration while the object is being * operational. The default {@code Configurable} implementation class {@link ConfigurableObject} will * throw a {@link ConfigurableException} when an attempt is made to alter the object's configuration * after calling {@code Configurable.locked()}. The implementations are also encouraged to throw * whenever an object is being used prior to calling {@code Configurable.locked()}. * *

The easiest way to implement a {@code Configurable} object is to extend {@link ConfigurableObject} class, * and override its {@code build() } method. The following snippet illustrates the pattern. * *

{@code
 * 
 * public class HTTPClient extends ConfigurableObject {
 *   
 *   // expose HTTPClient configuration keys
 *   public static Key socketTimeout = new Key<>(() -> 10_000){}
 *   public static Key logging       = new Key<>(() -> false){}
 * 
 *   //Override
 *   protected void build() {
 *    // initialize HTTPClient according to the configuration settings available via calling
 *    // get(key) method.  Assume, that all configuration values has been set at this point.
 *   }
 *   
 *   public HTTPResponse executeGet(String url) {
 *     // execute GET request, and return some HTTPResponse object
 *   }
 *   
 *   // more methods ...
 * }
 * 
 * // create and use your object
 * 
 * HTTPClient c = new HTTPClient()
 *                  .with(socketTimeout, 60_000) // change default socket timeout
 *                  .with(logging, true)         // change default logging flag
 *                  .locked();                   // lock configuration (calls build())
 * 
 * c.executeGet(myUrl);
 * 
 * }
* @param the type of the object itself. This is necessary in order to make methods like locked() and * with() return the reference to the object itself. * * @see ConfigurableObject * @see Key * @see ConfigurableException */ public interface Configurable> { /** * Set a value for the given configuration key. * * @param key configuration key * @param value configuration value * @return a reference to object itself * @throws ConfigurableException if the object is locked or there is some other problem setting the value */ C with(Key key, T value); /** * Get a configuration value. It might return a value set by {@code with} or the default value (which * may be null). * * @param key configuration key * @return configuration value */ T get(Key key); /** * Return a set of keys for this configurable object. Calling this method does not depend on whether * the object is locked or unlocked. */ Set> keys(); /** * Set all configuration values from a different configurable object. This may be useful when objects * of different or the same type share the same set of configuration keys and values. * *

If the target object is locked, the {@code ConfigurableException} will be thrown. The * other object doesn't have to be locked. * * @return a reference to itself * @throws ConfigurableException if the object is locked or there is some other problem setting the values */ C withConfigurationFrom(Configurable other); /** * Prevent the object's configuration from further modifications. Any attempt to use {@code with()} on a locked * object should throw {@code ConfigurableException}. Also, it is recommended that the methods, * defined by the object, throw exceptions if used before {@code locked()} is called. * * @return a reference to the object itself */ C locked(); /** * Convert a set of configuration keys with their default values into a {@code Configurable} object. * This method is useful when a collection of configuration keys has to be passed around as one * object. The returned {@code Configurable} object is locked. */ static Configurable configurationWith(Key ... keys) { Configurable configurable = empty(); Stream.of(keys).forEach(key -> configurable.with(key, null)); return configurable.locked(); } /** * Return an empty unlocked configuration. This object can be used * to collect configuration values and lock it afterwards. */ static Configurable empty() { return new ConfigurationHolder(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy