Skip to content

Commit

Permalink
Refactor configuration API to add single Configurable interface and A…
Browse files Browse the repository at this point in the history
…bstractConfigurable as a utility class.
  • Loading branch information
kuujo committed Jan 2, 2015
1 parent 4fe66b8 commit 029c3e6
Show file tree
Hide file tree
Showing 29 changed files with 266 additions and 132 deletions.
6 changes: 3 additions & 3 deletions api/src/main/java/net/kuujo/copycat/CopycatConfig.java
Expand Up @@ -31,7 +31,7 @@
* *
* @author <a href="http://github.com/kuujo">Jordan Halterman</a> * @author <a href="http://github.com/kuujo">Jordan Halterman</a>
*/ */
public class CopycatConfig extends Config { public class CopycatConfig extends AbstractConfigurable {
public static final String COPYCAT_SERIALIZER = "serializer"; public static final String COPYCAT_SERIALIZER = "serializer";
public static final String COPYCAT_CLUSTER = "cluster"; public static final String COPYCAT_CLUSTER = "cluster";
public static final String COPYCAT_RESOURCES = "resources"; public static final String COPYCAT_RESOURCES = "resources";
Expand All @@ -46,7 +46,7 @@ public CopycatConfig(Map<String, Object> config) {
super(config); super(config);
} }


public CopycatConfig(Config config) { private CopycatConfig(CopycatConfig config) {
super(config); super(config);
} }


Expand Down Expand Up @@ -155,7 +155,7 @@ public Map<String, ResourceConfig> getResourceConfigs() {
Map<String, Map<String, Object>> resources = get(COPYCAT_RESOURCES, new HashMap<>(0)); Map<String, Map<String, Object>> resources = get(COPYCAT_RESOURCES, new HashMap<>(0));
Map<String, ResourceConfig> configs = new HashMap<>(resources.size()); Map<String, ResourceConfig> configs = new HashMap<>(resources.size());
for (Map.Entry<String, Map<String, Object>> entry : resources.entrySet()) { for (Map.Entry<String, Map<String, Object>> entry : resources.entrySet()) {
configs.put(entry.getKey(), load(entry.getValue())); configs.put(entry.getKey(), Configurable.load(entry.getValue()));
} }
return configs; return configs;
} }
Expand Down
Expand Up @@ -15,7 +15,6 @@
*/ */
package net.kuujo.copycat.collections; package net.kuujo.copycat.collections;


import net.kuujo.copycat.Config;
import net.kuujo.copycat.ResourceConfig; import net.kuujo.copycat.ResourceConfig;


import java.util.Map; import java.util.Map;
Expand All @@ -34,7 +33,7 @@ protected AsyncCollectionConfig(Map<String, Object> config) {
super(config); super(config);
} }


protected AsyncCollectionConfig(Config config) { protected AsyncCollectionConfig(T config) {
super(config); super(config);
} }


Expand Down
Expand Up @@ -15,7 +15,6 @@
*/ */
package net.kuujo.copycat.collections; package net.kuujo.copycat.collections;


import net.kuujo.copycat.Config;
import net.kuujo.copycat.StateLogConfig; import net.kuujo.copycat.StateLogConfig;
import net.kuujo.copycat.cluster.ClusterConfig; import net.kuujo.copycat.cluster.ClusterConfig;
import net.kuujo.copycat.cluster.coordinator.CoordinatedResourceConfig; import net.kuujo.copycat.cluster.coordinator.CoordinatedResourceConfig;
Expand All @@ -38,7 +37,7 @@ public AsyncListConfig(Map<String, Object> config) {
super(config); super(config);
} }


protected AsyncListConfig(Config config) { protected AsyncListConfig(AsyncListConfig config) {
super(config); super(config);
} }


Expand Down
Expand Up @@ -15,7 +15,6 @@
*/ */
package net.kuujo.copycat.collections; package net.kuujo.copycat.collections;


import net.kuujo.copycat.Config;
import net.kuujo.copycat.ResourceConfig; import net.kuujo.copycat.ResourceConfig;
import net.kuujo.copycat.StateLogConfig; import net.kuujo.copycat.StateLogConfig;
import net.kuujo.copycat.cluster.ClusterConfig; import net.kuujo.copycat.cluster.ClusterConfig;
Expand All @@ -39,7 +38,7 @@ public AsyncLockConfig(Map<String, Object> config) {
super(config); super(config);
} }


public AsyncLockConfig(Config config) { protected AsyncLockConfig(AsyncLockConfig config) {
super(config); super(config);
} }


Expand Down
Expand Up @@ -15,7 +15,6 @@
*/ */
package net.kuujo.copycat.collections; package net.kuujo.copycat.collections;


import net.kuujo.copycat.Config;
import net.kuujo.copycat.ResourceConfig; import net.kuujo.copycat.ResourceConfig;
import net.kuujo.copycat.StateLogConfig; import net.kuujo.copycat.StateLogConfig;
import net.kuujo.copycat.cluster.ClusterConfig; import net.kuujo.copycat.cluster.ClusterConfig;
Expand All @@ -39,7 +38,7 @@ public AsyncMapConfig(Map<String, Object> config) {
super(config); super(config);
} }


public AsyncMapConfig(Config config) { protected AsyncMapConfig(AsyncMapConfig config) {
super(config); super(config);
} }


Expand Down
Expand Up @@ -15,7 +15,6 @@
*/ */
package net.kuujo.copycat.collections; package net.kuujo.copycat.collections;


import net.kuujo.copycat.Config;
import net.kuujo.copycat.ResourceConfig; import net.kuujo.copycat.ResourceConfig;
import net.kuujo.copycat.StateLogConfig; import net.kuujo.copycat.StateLogConfig;
import net.kuujo.copycat.cluster.ClusterConfig; import net.kuujo.copycat.cluster.ClusterConfig;
Expand All @@ -39,7 +38,7 @@ public AsyncMultiMapConfig(Map<String, Object> config) {
super(config); super(config);
} }


public AsyncMultiMapConfig(Config config) { protected AsyncMultiMapConfig(AsyncMultiMapConfig config) {
super(config); super(config);
} }


Expand Down
Expand Up @@ -15,7 +15,6 @@
*/ */
package net.kuujo.copycat.collections; package net.kuujo.copycat.collections;


import net.kuujo.copycat.Config;
import net.kuujo.copycat.StateLogConfig; import net.kuujo.copycat.StateLogConfig;
import net.kuujo.copycat.cluster.ClusterConfig; import net.kuujo.copycat.cluster.ClusterConfig;
import net.kuujo.copycat.cluster.coordinator.CoordinatedResourceConfig; import net.kuujo.copycat.cluster.coordinator.CoordinatedResourceConfig;
Expand All @@ -38,7 +37,7 @@ public AsyncSetConfig(Map<String, Object> config) {
super(config); super(config);
} }


public AsyncSetConfig(Config config) { protected AsyncSetConfig(AsyncSetConfig config) {
super(config); super(config);
} }


Expand Down
Expand Up @@ -17,82 +17,67 @@


import net.kuujo.copycat.internal.util.Assert; import net.kuujo.copycat.internal.util.Assert;


import java.lang.reflect.Constructor; import java.util.HashMap;
import java.lang.reflect.InvocationTargetException; import java.util.Map;
import java.util.*; import java.util.Set;
import java.util.function.Consumer;


/** /**
* Base configuration for configurable types. * Base configuration for configurable types.
* *
* @author <a href="http://github.com/kuujo">Jordan Halterman</a> * @author <a href="http://github.com/kuujo">Jordan Halterman</a>
*/ */
public class Config implements Copyable<Config>, Iterable<Map.Entry<String, Object>> { public abstract class AbstractConfigurable implements Configurable {
public static final String CONFIG_CLASS = "class"; public static final String CONFIG_CLASS = "class";
private final Map<String, Object> config; private Map<String, Object> config;


public Config() { protected AbstractConfigurable() {
this(new HashMap<>(128)); this(new HashMap<>(128));
} }


public Config(Map<String, Object> config) { protected AbstractConfigurable(Map<String, Object> config) {
this.config = config; this.config = config;
} }


protected Config(Config config) { protected AbstractConfigurable(Configurable config) {
this(new HashMap<>(config.config)); this(config.toMap());
} }


/** @Override
* Loads a configuration object from the given configuration map. public Configurable copy() {
*
* @param config The configuration map from which to load the configuration object.
* @param <T> The configuration object type.
* @return The loaded configuration object.
*/
@SuppressWarnings("unchecked")
protected static <T extends Config> T load(Map<String, Object> config) {
String className = (String) config.get(CONFIG_CLASS);
if (className == null) {
return (T) new Config(config);
}
try { try {
Class<?> clazz = Class.forName(className); Configurable copy = getClass().newInstance();
Constructor<?> constructor = clazz.getConstructor(Map.class); copy.configure(toMap());
return (T) constructor.newInstance(config); return copy;
} catch (ClassNotFoundException | NoSuchMethodException e) { } catch (InstantiationException | IllegalAccessException e) {
throw new ConfigurationException("Invalid configuration class", e); throw new ConfigurationException("Failed to create configuration copy", e);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | ClassCastException e) {
throw new ConfigurationException("Failed to instantiate configuration object", e);
} }
} }


@Override @Override
public Config copy() { public void configure(Map<String, Object> config) {
return new Config(this); this.config = config;
} }


/** /**
* Puts a configuration value in the configuration. * Puts a configuration value in the configuration.
* *
* @param key The configuration key. * @param key The configuration key.
* @param value The configuration value. * @param value The configuration value.
* @return The configuration instance.
*/ */
public Config put(String key, Object value) { @SuppressWarnings("unchecked")
config.put(Assert.isNotNull(key, "key"), value instanceof Config ? ((Config) value).toMap() : value); protected void put(String key, Object value) {
return this; config.put(Assert.isNotNull(key, "key"), value instanceof Configurable ? ((Configurable) value).toMap() : value);
} }


/** /**
* Gets a configuration value from the configuration. * Gets a configuration value from the configuration.
* *
* @param key The configuration key. * @param key The configuration key.
* @param <T> The configuration value type. * @param <U> The configuration value type.
* @return The configuration value. * @return The configuration value.
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> T get(String key) { protected <U> U get(String key) {
return get(key, null); return get(key, null);
} }


Expand All @@ -101,34 +86,34 @@ public <T> T get(String key) {
* *
* @param key The configuration key. * @param key The configuration key.
* @param defaultValue The default value to return if the configuration does not exist. * @param defaultValue The default value to return if the configuration does not exist.
* @param <T> The configuration type. * @param <U> The configuration type.
* @return The configuration value. * @return The configuration value.
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> T get(String key, T defaultValue) { protected <U> U get(String key, U defaultValue) {
Assert.isNotNull(key, "key"); Assert.isNotNull(key, "key");
Object value = config.containsKey(key) ? (T) config.get(key) : defaultValue; Object value = config.containsKey(key) ? config.get(key) : defaultValue;
if (value == null) { if (value == null) {
return null; return null;
} else if (value instanceof Map) { } else if (value instanceof Map) {
String className = (String) ((Map<?, ?>) value).get(CONFIG_CLASS); String className = (String) ((Map<?, ?>) value).get(CONFIG_CLASS);
if (className != null) { if (className != null) {
return (T) load((Map<String, Object>) value); return (U) Configurable.load((Map<String, Object>) value);
} }
} }
return (T) value; return (U) value;
} }


/** /**
* Removes a configuration value from the configuration. * Removes a configuration value from the configuration.
* *
* @param key The configuration key. * @param key The configuration key.
* @param <T> The configuration value type. * @param <U> The configuration value type.
* @return The configuration value that was removed. * @return The configuration value that was removed.
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> T remove(String key) { protected <U> U remove(String key) {
return (T) config.remove(Assert.isNotNull(key, "key")); return (U) config.remove(Assert.isNotNull(key, "key"));
} }


/** /**
Expand All @@ -137,7 +122,7 @@ public <T> T remove(String key) {
* @param key The key to check. * @param key The key to check.
* @return Indicates whether the configuration contains the given key. * @return Indicates whether the configuration contains the given key.
*/ */
public boolean containsKey(String key) { protected boolean containsKey(String key) {
return config.containsKey(Assert.isNotNull(key, "key")); return config.containsKey(Assert.isNotNull(key, "key"));
} }


Expand All @@ -146,7 +131,7 @@ public boolean containsKey(String key) {
* *
* @return The configuration key set. * @return The configuration key set.
*/ */
public Set<String> keySet() { protected Set<String> keySet() {
return config.keySet(); return config.keySet();
} }


Expand All @@ -155,40 +140,19 @@ public Set<String> keySet() {
* *
* @return The configuration entry set. * @return The configuration entry set.
*/ */
public Set<Map.Entry<String, Object>> entrySet() { protected Set<Map.Entry<String, Object>> entrySet() {
return config.entrySet(); return config.entrySet();
} }


/** /**
* Clears the configuration. * Clears the configuration.
*
* @return The configuration instance.
*/ */
public Config clear() { @SuppressWarnings("unchecked")
protected void clear() {
config.clear(); config.clear();
return this;
} }


@Override @Override
public Iterator<Map.Entry<String, Object>> iterator() {
return config.entrySet().iterator();
}

@Override
public void forEach(Consumer<? super Map.Entry<String, Object>> action) {
config.entrySet().forEach(action);
}

@Override
public Spliterator<Map.Entry<String, Object>> spliterator() {
return config.entrySet().spliterator();
}

/**
* Returns the configuration as a map.
*
* @return The configuration map.
*/
public Map<String, Object> toMap() { public Map<String, Object> toMap() {
Map<String, Object> config = new HashMap<>(this.config); Map<String, Object> config = new HashMap<>(this.config);
config.put("class", getClass().getName()); config.put("class", getClass().getName());
Expand Down

0 comments on commit 029c3e6

Please sign in to comment.