[LIB] ConfigurationAPI 1.0.1

Discussion in 'Resources' started by Faithcaio, Nov 22, 2013.

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

    Faithcaio

    This library provides an easy to use configuration API that maps class fields to readable configurations. It is possible to use any format, however by default the YAML format is provided with the library.

    Features:
    1. path and default value for every configuration entry is defined in code: Example
    2. comments on every field in the configuration: Example
    3. custom converter for your own data types: Example
    4. Type safety (due to 1.)
    Source: GitHub

    How to use the library

    Check Maven Central for the latest version.
    To see this library in action take a look at the CubeEngine project.

    If you have any suggestions or problems feel free to create an issue on GitHub.
     
    totokaka, Minecrell and Quick_Wango like this.
  2. Offline

    totokaka

    I am a part of the project this was developed for. This library is really a pleasure to use! The config files look really nice, both in code and as config files. I'll upload an example later today to illustrate better how nice it is.
     
  3. Offline

    xTrollxDudex

    .__. All config files look the same... Keys paths, and values.
     
    DarkBladee12 likes this.
  4. Offline

    arigatou


    config.yml:

    [​IMG]
     
  5. Offline

    xTrollxDudex

  6. Offline

    Quick_Wango

    Not quite. Readablility makes the difference. Configs generated by this API are formatted to be readable. In addition comments can be added to any configuration path.
    All that isn't even the best part of this library.
    Have you ever done something like config.getString("a.supr.loooong.path") and wondered why you got null instead of the string due to the typo? That simply can't happen with this library, as the configuration paths are defined by code and therefore accesses are validated at compile time. the above example would look like this using above library instead of Bukkit's config API: config.a.supr.looong.path
    A typo would obviously result in a compilation error. Accidently getting a number from a path instead of a string? Not possible either as the field types are validated at compile time as well. More compile time checks ==> less time wasted with debugging strange bugs caused by typos in string constants.
     
  7. Offline

    xTrollxDudex

    Quick_Wango
    Hmm. I'll make sure to link this to the noobs ;) then. Always having trouble with configs...
     
  8. Offline

    totokaka

    So I've created a simple example plugin to show off this lib.
    Source code:
    Show Spoiler

    Main class:
    Code:java
    1. import de.cubeisland.engine.configuration.ConfigurationFactory;
    2. import de.cubeisland.engine.configuration.codec.ConverterManager;
    3. import de.cubeisland.engine.configuration.convert.Converter;
    4. import de.cubeisland.engine.configuration.exception.ConversionException;
    5. import de.cubeisland.engine.configuration.exception.InvalidConfigurationException;
    6. import de.cubeisland.engine.configuration.node.Node;
    7. import de.cubeisland.engine.configuration.node.StringNode;
    8. import org.bukkit.Material;
    9. import org.bukkit.plugin.java.JavaPlugin;
    10.  
    11. import java.io.File;
    12. import java.io.IOException;
    13. import java.util.logging.Level;
    14.  
    15. public class ConfigPlugin extends JavaPlugin
    16. {
    17.  
    18. // We need a converter because The config API doesn't know about Bukkit classes
    19. public class MaterialConverter implements Converter<Material>
    20. {
    21. @Override
    22. public Node toNode(Material material, ConverterManager manager) throws ConversionException
    23. {
    24. return new StringNode(material.name());
    25. }
    26.  
    27. @Override
    28. public Material fromNode(Node node, ConverterManager manager) throws ConversionException {
    29. return Material.valueOf(node.asText());
    30. }
    31. }
    32.  
    33. public PluginConfig config;
    34.  
    35. public void onEnable()
    36. {
    37. // The ConfigurationFactory is the core of the ConfigurationAPI
    38. ConfigurationFactory configFactory = new ConfigurationFactory();
    39.  
    40. // Because We'll use a custom class as key in the config(Material)
    41. // We have to register a Converter
    42. configFactory.getDefaultConverterManager().registerConverter(Material.class, new MaterialConverter());
    43.  
    44. // Try to load the config from file, or create it if it doesn't exist
    45. try
    46. {
    47. File dataFolder = this.getDataFolder();
    48. if (!dataFolder.exists() && !dataFolder.mkdirs())
    49. {
    50. throw new IOException("Could not create config folder");
    51. }
    52.  
    53. this.config = configFactory.load(PluginConfig.class, new File(dataFolder, "config.yml"));
    54. }
    55. catch (InvalidConfigurationException ex)
    56. {
    57. this.getLogger().log(Level.WARNING, "Could not load the config files!");
    58. this.getLogger().log(Level.SEVERE, ex.getLocalizedMessage(), ex);
    59. this.getLogger().log(Level.WARNING, "Disabling plugin...");
    60. this.getServer().getPluginManager().disablePlugin(this);
    61. return;
    62. }
    63. catch (IOException ex)
    64. {
    65. this.getLogger().log(Level.WARNING, "Could not load the config files!");
    66. this.getLogger().log(Level.SEVERE, ex.getLocalizedMessage(), ex);
    67. this.getLogger().log(Level.WARNING, "Disabling plugin...");
    68. this.getServer().getPluginManager().disablePlugin(this);
    69. return;
    70. }
    71.  
    72. // We can now use the values in the config:
    73. this.getLogger().log(Level.INFO, config.helloMessage);
    74. this.getLogger().log(Level.INFO, "Block with id 20 is: " + config.ids.blocks.get(20));
    75. }
    76.  
    77. public void onDisable()
    78. {
    79. // We save the config when we shut down. This is necessary if we changed the config from the plugin.
    80. config.save();
    81. }
    82.  
    83. }


    Config Class:
    Code:java
    1. import de.cubeisland.engine.configuration.Section;
    2. import de.cubeisland.engine.configuration.YamlConfiguration;
    3. import de.cubeisland.engine.configuration.annotations.Comment;
    4. import de.cubeisland.engine.configuration.annotations.Name;
    5. import org.bukkit.Material;
    6.  
    7. import java.util.HashMap;
    8. import java.util.Map;
    9.  
    10. // This is the config class. It does not have to be an internal class!
    11. // It has to extend YamlConfiguration
    12. public class PluginConfig extends YamlConfiguration
    13. {
    14. public String[] head()
    15. {
    16. return new String[] {"This is the head comment of the configuration file.",
    17. "It supports multiple lines!"};
    18. }
    19.  
    20. // This is a String value in the config.
    21. // In the config It'll be named 'hello-message', but you don't have to care about that
    22. // The value read from the config is inserted in this field
    23. public String helloMessage = "Hello there!";
    24.  
    25. // This is a integer value in the config.
    26. // It'll be named 'secret-number' in the config because of the [USER=35164]name[/USER] annotation
    27. // But you don't need to care about that. The value from the config is inserted back
    28. // in this field.
    29. // This field will also have a comment above it, because of the @Comment annotation.
    30. @Comment({"This is the key!",
    31. "Keep it secret!"})
    32. [USER=35164]name[/USER]("secret-number")
    33. public int x = 3301;
    34.  
    35. // This is a section in config
    36. // The library will initialize the object
    37. @Comment("Mappings of every block and item in the game")
    38. [USER=35164]name[/USER]("ids")
    39. public IdsSection ids;
    40.  
    41. public class IdsSection implements Section
    42. {
    43. // These fields will be under the path 'ids.blocks' and 'ids.items' in the config
    44. @Comment("Mapping from every block in the game to it's id")
    45. public Map<Integer, Material> blocks = new HashMap<Integer, Material>();
    46. @Comment("Mapping from every item in the game to it's id")
    47. public Map<Integer, Material> items = new HashMap<Integer, Material>();
    48.  
    49. // Insert the blocks and the id's in the maps
    50. {
    51. for (Material m : Material.values())
    52. {
    53. if (m.isBlock())
    54. {
    55. blocks.put(m.getId(), m);
    56. }
    57. else
    58. {
    59. items.put(m.getId(), m);
    60. }
    61. }
    62. }
    63. }
    64.  
    65. public String[] tail()
    66. {
    67. return new String[] {"This is the end of the config.",
    68. "I hope you liked the ConfigurationAPI!"};
    69. }
    70. }
    71.  



    And the beutiful config file it creates. Keep in mind this is not modified in any way by me, the ConfigurationAPI creates them like this:
    Code:
    # This is the head comment of the configuration file.
    # It supports multiple lines!
     
    hello-message: Hello there!
     
    # This is the key!
    # Keep it secret!
    secret-number: 3301
     
    # Mappings of every block and item in the game
    ids:
      # Mapping from every block in the game to it's id
      blocks:
        0: AIR
        1: STONE
        2: GRASS
        3: DIRT
        4: COBBLESTONE
        5: WOOD
        6: SAPLING
        7: BEDROCK
        8: WATER
        9: STATIONARY_WATER
        10: LAVA
        11: STATIONARY_LAVA
        12: SAND
        13: GRAVEL
        14: GOLD_ORE
        15: IRON_ORE
        17: LOG
        16: COAL_ORE
        19: SPONGE
        18: LEAVES
        21: LAPIS_ORE
        20: GLASS
        23: DISPENSER
        22: LAPIS_BLOCK
        25: NOTE_BLOCK
        24: SANDSTONE
        27: POWERED_RAIL
        26: BED_BLOCK
        29: PISTON_STICKY_BASE
        28: DETECTOR_RAIL
        31: LONG_GRASS
        30: WEB
        34: PISTON_EXTENSION
        35: WOOL
        32: DEAD_BUSH
        33: PISTON_BASE
        38: RED_ROSE
        39: BROWN_MUSHROOM
        36: PISTON_MOVING_PIECE
        37: YELLOW_FLOWER
        42: IRON_BLOCK
        43: DOUBLE_STEP
        40: RED_MUSHROOM
        41: GOLD_BLOCK
        46: TNT
        47: BOOKSHELF
        44: STEP
        45: BRICK
        51: FIRE
        50: TORCH
        49: OBSIDIAN
        48: MOSSY_COBBLESTONE
        55: REDSTONE_WIRE
        54: CHEST
        53: WOOD_STAIRS
        52: MOB_SPAWNER
        59: CROPS
        58: WORKBENCH
        57: DIAMOND_BLOCK
        56: DIAMOND_ORE
        63: SIGN_POST
        62: BURNING_FURNACE
        61: FURNACE
        60: SOIL
        68: WALL_SIGN
        69: LEVER
        70: STONE_PLATE
        71: IRON_DOOR_BLOCK
        64: WOODEN_DOOR
        65: LADDER
        66: RAILS
        67: COBBLESTONE_STAIRS
        76: REDSTONE_TORCH_ON
        77: STONE_BUTTON
        78: SNOW
        79: ICE
        72: WOOD_PLATE
        73: REDSTONE_ORE
        74: GLOWING_REDSTONE_ORE
        75: REDSTONE_TORCH_OFF
        85: FENCE
        84: JUKEBOX
        87: NETHERRACK
        86: PUMPKIN
        81: CACTUS
        80: SNOW_BLOCK
        83: SUGAR_CANE_BLOCK
        82: CLAY
        93: DIODE_BLOCK_OFF
        92: CAKE_BLOCK
        95: LOCKED_CHEST
        94: DIODE_BLOCK_ON
        89: GLOWSTONE
        88: SOUL_SAND
        91: JACK_O_LANTERN
        90: PORTAL
        102: THIN_GLASS
        103: MELON_BLOCK
        100: HUGE_MUSHROOM_2
        101: IRON_FENCE
        98: SMOOTH_BRICK
        99: HUGE_MUSHROOM_1
        96: TRAP_DOOR
        97: MONSTER_EGGS
        110: MYCEL
        111: WATER_LILY
        108: BRICK_STAIRS
        109: SMOOTH_STAIRS
        106: VINE
        107: FENCE_GATE
        104: PUMPKIN_STEM
        105: MELON_STEM
        119: ENDER_PORTAL
        118: CAULDRON
        117: BREWING_STAND
        116: ENCHANTMENT_TABLE
        115: NETHER_WARTS
        114: NETHER_BRICK_STAIRS
        113: NETHER_FENCE
        112: NETHER_BRICK
        127: COCOA
        126: WOOD_STEP
        125: WOOD_DOUBLE_STEP
        124: REDSTONE_LAMP_ON
        123: REDSTONE_LAMP_OFF
        122: DRAGON_EGG
        121: ENDER_STONE
        120: ENDER_PORTAL_FRAME
        137: COMMAND
        136: JUNGLE_WOOD_STAIRS
        139: COBBLE_WALL
        138: BEACON
        141: CARROT
        140: FLOWER_POT
        143: WOOD_BUTTON
        142: POTATO
        129: EMERALD_ORE
        128: SANDSTONE_STAIRS
        131: TRIPWIRE_HOOK
        130: ENDER_CHEST
        133: EMERALD_BLOCK
        132: TRIPWIRE
        135: BIRCH_WOOD_STAIRS
        134: SPRUCE_WOOD_STAIRS
        152: REDSTONE_BLOCK
        153: QUARTZ_ORE
        154: HOPPER
        155: QUARTZ_BLOCK
        156: QUARTZ_STAIRS
        157: ACTIVATOR_RAIL
        158: DROPPER
        159: STAINED_CLAY
        144: SKULL
        145: ANVIL
        146: TRAPPED_CHEST
        147: GOLD_PLATE
        148: IRON_PLATE
        149: REDSTONE_COMPARATOR_OFF
        150: REDSTONE_COMPARATOR_ON
        151: DAYLIGHT_DETECTOR
        171: CARPET
        170: HAY_BLOCK
        173: COAL_BLOCK
        172: HARD_CLAY
     
      # Mapping from every item in the game to it's id
      items:
        275: STONE_AXE
        274: STONE_PICKAXE
        273: STONE_SPADE
        272: STONE_SWORD
        279: DIAMOND_AXE
        278: DIAMOND_PICKAXE
        277: DIAMOND_SPADE
        276: DIAMOND_SWORD
        283: GOLD_SWORD
        282: MUSHROOM_SOUP
        281: BOWL
        280: STICK
        287: STRING
        286: GOLD_AXE
        285: GOLD_PICKAXE
        284: GOLD_SPADE
        258: IRON_AXE
        259: FLINT_AND_STEEL
        256: IRON_SPADE
        257: IRON_PICKAXE
        262: ARROW
        263: COAL
        260: APPLE
        261: BOW
        266: GOLD_INGOT
        267: IRON_SWORD
        264: DIAMOND
        265: IRON_INGOT
        270: WOOD_PICKAXE
        271: WOOD_AXE
        268: WOOD_SWORD
        269: WOOD_SPADE
        305: CHAINMAIL_BOOTS
        304: CHAINMAIL_LEGGINGS
        307: IRON_CHESTPLATE
        306: IRON_HELMET
        309: IRON_BOOTS
        308: IRON_LEGGINGS
        311: DIAMOND_CHESTPLATE
        310: DIAMOND_HELMET
        313: DIAMOND_BOOTS
        312: DIAMOND_LEGGINGS
        315: GOLD_CHESTPLATE
        314: GOLD_HELMET
        317: GOLD_BOOTS
        316: GOLD_LEGGINGS
        319: PORK
        318: FLINT
        288: FEATHER
        289: SULPHUR
        290: WOOD_HOE
        291: STONE_HOE
        292: IRON_HOE
        293: DIAMOND_HOE
        294: GOLD_HOE
        295: SEEDS
        296: WHEAT
        297: BREAD
        298: LEATHER_HELMET
        299: LEATHER_CHESTPLATE
        300: LEATHER_LEGGINGS
        301: LEATHER_BOOTS
        302: CHAINMAIL_HELMET
        303: CHAINMAIL_CHESTPLATE
        343: POWERED_MINECART
        342: STORAGE_MINECART
        341: SLIME_BALL
        340: BOOK
        2264: RECORD_9
        339: PAPER
        2265: RECORD_10
        338: SUGAR_CANE
        2266: RECORD_11
        337: CLAY_BALL
        2267: RECORD_12
        336: CLAY_BRICK
        2260: RECORD_5
        351: INK_SACK
        2261: RECORD_6
        350: COOKED_FISH
        2262: RECORD_7
        349: RAW_FISH
        2263: RECORD_8
        348: GLOWSTONE_DUST
        2256: GOLD_RECORD
        347: WATCH
        2257: GREEN_RECORD
        346: FISHING_ROD
        2258: RECORD_3
        345: COMPASS
        2259: RECORD_4
        344: EGG
        326: WATER_BUCKET
        327: LAVA_BUCKET
        324: WOOD_DOOR
        325: BUCKET
        322: GOLDEN_APPLE
        323: SIGN
        320: GRILLED_PORK
        321: PAINTING
        334: LEATHER
        335: MILK_BUCKET
        332: SNOW_BALL
        333: BOAT
        330: IRON_DOOR
        331: REDSTONE
        328: MINECART
        329: SADDLE
        373: POTION
        372: NETHER_STALK
        375: SPIDER_EYE
        374: GLASS_BOTTLE
        369: BLAZE_ROD
        368: ENDER_PEARL
        371: GOLD_NUGGET
        370: GHAST_TEAR
        381: EYE_OF_ENDER
        380: CAULDRON_ITEM
        383: MONSTER_EGG
        382: SPECKLED_MELON
        377: BLAZE_POWDER
        376: FERMENTED_SPIDER_EYE
        379: BREWING_STAND_ITEM
        378: MAGMA_CREAM
        356: DIODE
        357: COOKIE
        358: MAP
        359: SHEARS
        352: BONE
        353: SUGAR
        354: CAKE
        355: BED
        364: COOKED_BEEF
        365: RAW_CHICKEN
        366: COOKED_CHICKEN
        367: ROTTEN_FLESH
        360: MELON
        361: PUMPKIN_SEEDS
        362: MELON_SEEDS
        363: RAW_BEEF
        408: HOPPER_MINECART
        402: FIREWORK_CHARGE
        403: ENCHANTED_BOOK
        400: PUMPKIN_PIE
        401: FIREWORK
        406: QUARTZ
        407: EXPLOSIVE_MINECART
        404: REDSTONE_COMPARATOR
        405: NETHER_BRICK_ITEM
        395: EMPTY_MAP
        394: POISONOUS_POTATO
        393: BAKED_POTATO
        392: POTATO_ITEM
        399: NETHER_STAR
        398: CARROT_STICK
        397: SKULL_ITEM
        396: GOLDEN_CARROT
        387: WRITTEN_BOOK
        386: BOOK_AND_QUILL
        385: FIREBALL
        384: EXP_BOTTLE
        391: CARROT_ITEM
        390: FLOWER_POT_ITEM
        389: ITEM_FRAME
        388: EMERALD
        417: IRON_BARDING
        419: DIAMOND_BARDING
        418: GOLD_BARDING
        421: NAME_TAG
        420: LEASH
    # This is the end of the config.
    # I hope you liked the ConfigurationAPI!
    Even though this is really easy to use it is not aimed at noobs especially. The goal of it was to have configs that create nicer files, has easier support for child configs, and cleaner and easier to use in code. It allows for some quite advanced features.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 5, 2016
  9. Offline

    Mathias Eklund

    Thats great :) My configs are so ugly :)
     
  10. Offline

    xTrollxDudex

    totokaka
    That looks exactly what my config would look like if I had that many elements to use
     
  11. Offline

    totokaka

    Of course you can make configs like this with Bukkit's config API, but if you are going to make many configurations, or some big ones, you'll get a lot more code duplication that you get with this library.

    And I know that at least I am so lazy that I don't bother to find a way to create comments in my configs. With this Lib, comments become cheap and easy to use.
     
Thread Status:
Not open for further replies.

Share This Page