I've updated this class to handle types, and to use overloaded methods. I chose to do this because I'm a a phase of development where I've decided that the base types I'm using, particularly with booleans, are generally not specific enough to meet my needs. By using overloaded methods, I only need to change the definition of the local copy and implementation code, and don't have to worry about going back and re-writing code from the settings window's load/save methods.
I'm particularly fond of the enum methods; just don't try to save a NULL enum - it will crash because NULLs are typeless.
http://bnubot.googlecode.com/svn/trunk/BNUBot/src/net/bnubot/settings/Settings.java/**
* This file is distributed under the GPL
* $Id: Settings.java 1137 2008-03-07 21:43:21Z scotta $
*/
package net.bnubot.settings;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Properties;
import net.bnubot.util.Out;
import net.bnubot.util.SortedProperties;
import net.bnubot.vercheck.CurrentVersion;
public class Settings {
private static final File propsFile = new File("settings.ini");
private static final Properties props = new SortedProperties();
private static Boolean anythingChanged = false;
static {
if(propsFile.exists()) try {
props.load(new FileInputStream(propsFile));
} catch(Exception e) {
Out.exception(e);
}
}
private static String getKey(String header, String setting) {
if(header == null)
return "general_" + setting;
return header + "_" + setting;
}
public static String read(String header, String setting, String defaultValue) {
return props.getProperty(getKey(header, setting), defaultValue);
}
public static boolean read(String header, String setting, boolean defaultValue) {
return Boolean.parseBoolean(read(header, setting, Boolean.toString(defaultValue)));
}
public static int read(String header, String setting, int defaultValue) {
return Integer.parseInt(read(header, setting, Integer.toString(defaultValue)));
}
public static long read(String header, String setting, long defaultValue) {
return Long.parseLong(read(header, setting, Long.toString(defaultValue)));
}
/**
* This method will not handle a NULL value for defaultValue
*/
public static <T extends Enum<T>> T read(String header, String setting, T defaultValue) {
return Enum.valueOf(defaultValue.getDeclaringClass(), read(header, setting, defaultValue.name()));
}
public static void write(String header, String setting, String value) {
String key = getKey(header, setting);
if(value == null)
value = new String();
// Don't allow modification of keys unless they haven't changed
if(props.containsKey(key) && props.getProperty(key).equals(value))
return;
anythingChanged = true;
Out.debug(Settings.class, "setting " + key + "=" + value);
props.setProperty(key, value);
}
public static void write(String header, String setting, boolean value) {
write(header, setting, Boolean.toString(value));
}
public static void write(String header, String setting, int value) {
write(header, setting, Integer.toString(value));
}
public static void write(String header, String setting, long value) {
write(header, setting, Long.toString(value));
}
public static <T extends Enum<T>> void write(String header, String setting, T value) {
write(header, setting, value.name());
}
public static void store() {
if(!anythingChanged)
return;
Out.debug(Settings.class, "Writing settings.ini");
try {
// Generate the comment first, because the settings.ini file could be lost if CurrentVersion.version() fails
String comment = CurrentVersion.version().toString();
props.store(new FileOutputStream(propsFile), comment);
anythingChanged = false;
} catch (Exception e) {
Out.fatalException(e);
}
}
}