Skip to content

Instantly share code, notes, and snippets.

@sirolf2009
Created January 25, 2017 14:01
Show Gist options
  • Save sirolf2009/70fda7fef80f926375733d2183539d88 to your computer and use it in GitHub Desktop.
Save sirolf2009/70fda7fef80f926375733d2183539d88 to your computer and use it in GitHub Desktop.
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import org.apache.commons.configuration2.FileBasedConfiguration;
import org.apache.commons.configuration2.XMLPropertiesConfiguration;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.ImmutableTriple;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple;
/**
* Generic hell.... my head hurts
*
* @author Floris
*/
public abstract class SettingsConfiguration {
private final Map<Class<? extends Object>, Consumer<Triple<String, Object, Pair<Consumer<Object>, Consumer<Exception>>>>> typesAndGetters = new HashMap<Class<? extends Object>, Consumer<Triple<String, Object, Pair<Consumer<Object>, Consumer<Exception>>>>>();
private final File file;
private final FileBasedConfiguration configuration;
private final Map<String, Object> defaults;
public SettingsConfiguration(File file) throws FileNotFoundException, ConfigurationException, IOException {
this.file = file;
initializeFile(file);
configuration = new XMLPropertiesConfiguration();
configuration.read(new FileReader(file));
defaults = new HashMap<String, Object>();
setupTypesAndGetters();
}
public static void initializeFile(File file) throws IOException {
if(!file.exists()) {
file.getParentFile().mkdirs();
if(file.createNewFile()) {
writeNewPropertiesFile(file);
}
}
}
public static void writeNewPropertiesFile(File file) throws FileNotFoundException {
PrintWriter writer = new PrintWriter(new FileOutputStream(file));
writer.println("<?xml version=\"1.0\" ?>");
writer.println("<!DOCTYPE properties SYSTEM \"http://java.sun.com/dtd/properties.dtd\" >");
writer.println("<properties>");
writer.println("</properties>");
writer.close();
}
public static void savePropertiesFile(File file, FileBasedConfiguration configuration) throws FileNotFoundException, ConfigurationException, IOException {
initializeFile(file);
PrintWriter writer = new PrintWriter(file);
configuration.write(writer);
writer.close();
}
public void initializeDefaults() throws IllegalArgumentException, IllegalAccessException {
for(Field field : this.getClass().asSubclass(this.getClass()).getDeclaredFields()) {
if(field.isAnnotationPresent(Setting.class)) {
if(!field.isAccessible()) {
field.setAccessible(true);
}
defaults.put(field.getName(), field.get(this));
}
}
}
final List<Exception> exceptions = new ArrayList<Exception>();
public void reload() throws FileNotFoundException, ConfigurationException, IOException {
synchronized(exceptions) {
exceptions.clear();
reload(error -> {
exceptions.add(error.getKey());
});
if(exceptions.size() > 0) {
Exception e = exceptions.get(0);
if(e instanceof FileNotFoundException) {
throw (FileNotFoundException) e;
} else if(e instanceof ConfigurationException) {
throw (ConfigurationException) e;
} else if(e instanceof IOException) {
throw (IOException) e;
} else {
throw new RuntimeException(e);
}
}
}
}
public void reload(Consumer<Pair<Exception, Field>> onError) {
for(final Field field : this.getClass().asSubclass(this.getClass()).getDeclaredFields()) {
if(field.isAnnotationPresent(Setting.class)) {
Class<?> type = field.getType();
typesAndGetters.get(type).accept(new ImmutableTriple<String, Object, Pair<Consumer<Object>, Consumer<Exception>>>(field.getName(), (Object) defaults.get(field.getName()), new ImmutablePair<Consumer<Object>, Consumer<Exception>>(value -> {
try {
field.set(this, value);
} catch(IllegalArgumentException | IllegalAccessException e) {
onError.accept(new ImmutablePair<Exception, Field>(e, field));
}
}, error -> onError.accept(new ImmutablePair<Exception, Field>(error, field)))));
}
}
}
public void setupTypesAndGetters() {
typesAndGetters.put(Boolean.class, getBoolean);
typesAndGetters.put(boolean.class, getBoolean);
typesAndGetters.put(Byte.class, getByte);
typesAndGetters.put(byte.class, getByte);
typesAndGetters.put(Double.class, getDouble);
typesAndGetters.put(double.class, getDouble);
typesAndGetters.put(Float.class, getFloat);
typesAndGetters.put(float.class, getFloat);
typesAndGetters.put(int.class, getInteger);
typesAndGetters.put(Integer.class, getInteger);
typesAndGetters.put(long.class, getLong);
typesAndGetters.put(Long.class, getLong);
typesAndGetters.put(short.class, getShort);
typesAndGetters.put(Short.class, getShort);
typesAndGetters.put(String.class, getString);
}
public Consumer<Triple<String, Object, Pair<Consumer<Object>, Consumer<Exception>>>> getBoolean = input -> {
try {
input.getRight().getLeft().accept(getProperty(input.getLeft(), (Boolean) input.getMiddle(), Boolean.class));
} catch(ConfigurationException | IOException e) {
input.getRight().getRight().accept(e);
}
};
public Consumer<Triple<String, Object, Pair<Consumer<Object>, Consumer<Exception>>>> getByte = input -> {
try {
input.getRight().getLeft().accept(getProperty(input.getLeft(), (Byte) input.getMiddle(), Byte.class));
} catch(ConfigurationException | IOException e) {
input.getRight().getRight().accept(e);
}
};
public Consumer<Triple<String, Object, Pair<Consumer<Object>, Consumer<Exception>>>> getDouble = input -> {
try {
input.getRight().getLeft().accept(getProperty(input.getLeft(), (Double) input.getMiddle(), Double.class));
} catch(ConfigurationException | IOException e) {
input.getRight().getRight().accept(e);
}
};
public Consumer<Triple<String, Object, Pair<Consumer<Object>, Consumer<Exception>>>> getFloat = input -> {
try {
input.getRight().getLeft().accept(getProperty(input.getLeft(), (Float) input.getMiddle(), Float.class));
} catch(ConfigurationException | IOException e) {
input.getRight().getRight().accept(e);
}
};
public Consumer<Triple<String, Object, Pair<Consumer<Object>, Consumer<Exception>>>> getInteger = input -> {
try {
input.getRight().getLeft().accept(getProperty(input.getLeft(), (Integer) input.getMiddle(), Integer.class));
} catch(ConfigurationException | IOException e) {
input.getRight().getRight().accept(e);
}
};
public Consumer<Triple<String, Object, Pair<Consumer<Object>, Consumer<Exception>>>> getLong = input -> {
try {
input.getRight().getLeft().accept(getProperty(input.getLeft(), (Long) input.getMiddle(), Long.class));
} catch(ConfigurationException | IOException e) {
input.getRight().getRight().accept(e);
}
};
public Consumer<Triple<String, Object, Pair<Consumer<Object>, Consumer<Exception>>>> getShort = input -> {
try {
input.getRight().getLeft().accept(getProperty(input.getLeft(), (Short) input.getMiddle(), Short.class));
} catch(ConfigurationException | IOException e) {
input.getRight().getRight().accept(e);
}
};
public Consumer<Triple<String, Object, Pair<Consumer<Object>, Consumer<Exception>>>> getString = input -> {
try {
input.getRight().getLeft().accept(getProperty(input.getLeft(), (String) input.getMiddle(), String.class));
} catch(ConfigurationException | IOException e) {
input.getRight().getRight().accept(e);
}
};
public boolean getBoolean(String key, boolean defaultValue) throws FileNotFoundException, ConfigurationException, IOException {
return getProperty(key, defaultValue, boolean.class);
}
public Boolean getBoolean(String key, Boolean defaultValue) throws FileNotFoundException, ConfigurationException, IOException {
return getProperty(key, defaultValue, Boolean.class);
}
public byte getByte(String key, byte defaultValue) throws FileNotFoundException, ConfigurationException, IOException {
return getProperty(key, defaultValue, byte.class);
}
public Byte getByte(String key, Byte defaultValue) throws FileNotFoundException, ConfigurationException, IOException {
return getProperty(key, defaultValue, Byte.class);
}
public double getDouble(String key, double defaultValue) throws FileNotFoundException, ConfigurationException, IOException {
return getProperty(key, defaultValue, double.class);
}
public Double getDouble(String key, Double defaultValue) throws FileNotFoundException, ConfigurationException, IOException {
return getProperty(key, defaultValue, Double.class);
}
public float getFloat(String key, float defaultValue) throws FileNotFoundException, ConfigurationException, IOException {
return getProperty(key, defaultValue, float.class);
}
public Float getFloat(String key, Float defaultValue) throws FileNotFoundException, ConfigurationException, IOException {
return getProperty(key, defaultValue, Float.class);
}
public int getInt(String key, int defaultValue) throws FileNotFoundException, ConfigurationException, IOException {
return getProperty(key, defaultValue, int.class);
}
public Integer getInteger(String key, Integer defaultValue) throws FileNotFoundException, ConfigurationException, IOException {
return getProperty(key, defaultValue, Integer.class);
}
public long getLong(String key, long defaultValue) throws FileNotFoundException, ConfigurationException, IOException {
return getProperty(key, defaultValue, long.class);
}
public Long getLong(String key, Long defaultValue) throws FileNotFoundException, ConfigurationException, IOException {
return getProperty(key, defaultValue, Long.class);
}
public short getShort(String key, short defaultValue) throws FileNotFoundException, ConfigurationException, IOException {
return getProperty(key, defaultValue, short.class);
}
public Short getShort(String key, Short defaultValue) throws FileNotFoundException, ConfigurationException, IOException {
return getProperty(key, defaultValue, Short.class);
}
public String getString(String key, String defaultValue) throws FileNotFoundException, ConfigurationException, IOException {
return getProperty(key, defaultValue, String.class);
}
private <T> T getProperty(String key, T defaultValue, Class<T> clazz) throws FileNotFoundException, ConfigurationException, IOException {
if(!configuration.containsKey(key)) {
if(defaultValue == null) {
throw new ConfigurationException(key+" is not defined in the settings and no default has been provided");
}
configuration.addProperty(key, defaultValue);
savePropertiesFile(file, configuration);
return configuration.get(clazz, key, defaultValue);
}
return configuration.get(clazz, key, defaultValue);
}
public File getFile() {
return file;
}
public FileBasedConfiguration getConfiguration() {
return configuration;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment