I'm trying to make plugins as versatile as possible. Before I go all out and configuring a lame system, I was wondering if anyone else has a better system. This uses Niji's/hMod's old PropertiesFile class for saving default values (it's damn nifty). In a nutshell, it's a wrapper class with an Enum + Hashtable combo for each data type. To prevent unnecessary casting later and simplify the loading process. Any thoughts? PHP: import java.util.Arrays;import java.util.Hashtable;import java.util.List;import com.shade.util.PropertiesFile;import com.shade.util.StringMgmt; public class Test { public static void main(String args[]) { Setting.load("test.properties"); Hashtable<Object,Object> settings = Setting.getMap(); for (Object key : settings.keySet()) System.out.println(key.toString() + " : " +settings.get(key).toString()); }}class Setting { // List<String> public enum StringList { RESIDENT_COMMANDS, TOWN_COMMANDS } // String public enum Str { KING_PREFIX, REGISTRATION_MSG, NEW_TOWN_MSG, NEW_NATION_MSG } // Integer public enum Int { MAX_TOWN_BLOCKS } // Boolean public enum Bool { DEBUG_MODE } private static Hashtable<Setting.StringList,List<String>> configStringList = new Hashtable<Setting.StringList,List<String>>(); private static Hashtable<Setting.Str,String> configStr = new Hashtable<Setting.Str,String>(); private static Hashtable<Setting.Int,Integer> configInt = new Hashtable<Setting.Int,Integer>(); private static Hashtable<Setting.Bool,Boolean> configBool = new Hashtable<Setting.Bool,Boolean>(); public static Hashtable<Object,Object> getMap() { Hashtable<Object,Object> out = new Hashtable<Object,Object>(); out.putAll(configStringList); out.putAll(configStr); out.putAll(configInt); out.putAll(configBool); return out; } public static Integer get(Setting.Int key) { return configInt.get(key); } public static String get(Setting.Str key) { return configStr.get(key); } public static Boolean get(Setting.Bool key) { return configBool.get(key); } public static List<String> get(Setting.StringList key) { return configStringList.get(key); } public static void load(String filename) { PropertiesFile propertiesFile = new PropertiesFile(filename); for (Setting.StringList key : Setting.StringList.values()) { String line = propertiesFile.getString(key.toString().toLowerCase(), StringMgmt.join(get(key), ",")); configStringList.put(key, Arrays.asList(line.split(","))); } for (Setting.Str key : Setting.Str.values()) configStr.put(key, propertiesFile.getString(key.toString().toLowerCase(), get(key))); for (Setting.Int key : Setting.Int.values()) configInt.put(key, propertiesFile.getInt(key.toString().toLowerCase(), get(key))); for (Setting.Bool key : Setting.Bool.values()) configBool.put(key, propertiesFile.getBoolean(key.toString().toLowerCase(), get(key))); } static { configStringList.put(Setting.StringList.RESIDENT_COMMANDS, Arrays.asList(new String[]{"/resident","/r"})); configStringList.put(Setting.StringList.TOWN_COMMANDS, Arrays.asList(new String[]{"/town","/t"})); configStr.put(Setting.Str.REGISTRATION_MSG, "Welcome this is your first login.@You've successfully registered!"); configStr.put(Setting.Str.NEW_TOWN_MSG, "%s created a new town called %s"); configStr.put(Setting.Str.NEW_NATION_MSG, "%s created a new nation called %s"); configStr.put(Setting.Str.KING_PREFIX, "King "); configInt.put(Setting.Int.MAX_TOWN_BLOCKS, 64); configBool.put(Setting.Bool.DEBUG_MODE, true); }}
In my python projects I have used yaml which translates very well into python objects. I've seen some projects also use yaml, but I don't know how "java" it is.
HashTables aren't very good for multiple threads (which Bukkit has). Basically, if 2 CPU threads try to access the same hashtable at the same time, only 1 will win, and the other will get a null reference. Since you don't expect lookups to fail, it may cause odd behavior. Use something that is multiple thread safe. I switched from Hashmaps to ConcurrentHashMap's myself. Concurrent structures will support multiple lookups and modifications. I'm not sure how kosher this is, but I use one ConcurrentHashMap for configuration, with a string key and object storage type, so I can store anything in it, and cast it once I need it, instead of having a bunch of separate tables. But I am not a software engineer, so take my advice here at face value... I also wrote my own flatfile reader, for more verisitility, but that's really a matter of opinion as well.
Hmmmm Yaml does the necessary casting for loading itself. Very nice. Very nice indeed. *downloads snake* Seeing as how I'm treating this as a bunch of constants, multiple lookups is probably a plus vs the locking necessary for modifications. Mind you, I'll be keeping my enums. I'm 99% sure they are faster to use as keys than strings.
Enums are faster than strings, for sure. If you know what you'll be storing in advance, than stick with them.