Settings file advice

Discussion in 'Plugin Development' started by Shade, Jan 20, 2011.

Thread Status:
Not open for further replies.
  1. Offline

    Shade

    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,Objectsettings 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,StringconfigStr = new Hashtable<Setting.Str,String>();
        private static 
    Hashtable<Setting.Int,IntegerconfigInt = new Hashtable<Setting.Int,Integer>();
        private static 
    Hashtable<Setting.Bool,BooleanconfigBool = new Hashtable<Setting.Bool,Boolean>();

        public static 
    Hashtable<Object,ObjectgetMap() {
            
    Hashtable<Object,Objectout = 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<
    Stringget(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(keyArrays.asList(line.split(",")));
            }
            for (
    Setting.Str key Setting.Str.values())
                
    configStr.put(keypropertiesFile.getString(key.toString().toLowerCase(), get(key)));
            for (
    Setting.Int key Setting.Int.values())
                
    configInt.put(keypropertiesFile.getInt(key.toString().toLowerCase(), get(key)));
            for (
    Setting.Bool key Setting.Bool.values())
                
    configBool.put(keypropertiesFile.getBoolean(key.toString().toLowerCase(), get(key)));
        }

        static {
            
    configStringList.put(Setting.StringList.RESIDENT_COMMANDSArrays.asList(new String[]{"/resident","/r"}));
            
    configStringList.put(Setting.StringList.TOWN_COMMANDSArrays.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_BLOCKS64);
            
    configBool.put(Setting.Bool.DEBUG_MODEtrue);
        }
    }
     
  2. Offline

    croxis

    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.
     
  3. Offline

    Afforess

    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.
     
  4. Offline

    Shade

    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.
     
  5. Offline

    Afforess

    Enums are faster than strings, for sure. If you know what you'll be storing in advance, than stick with them.
     
Thread Status:
Not open for further replies.

Share This Page