OkaeriPoland / okaeri-configs

Simple Java/POJO config library written with love and Lombok
MIT License
77 stars 11 forks source link
bukkit bungee config gson hjson hocon java json minecraft paper snakeyaml spigot yaml

Okaeri Configs

License Total lines Repo size Contributors Discord

Supported platforms (general use)

General implementations based on standard format libraries directly.

Supported platforms (environment dependant)

Special implementations for safe use in specific environment, eg. gameservers.

Validation extensions

Serialization extensions

Recommendations

For standalone platforms hjson module is the best choice, it supports all the features, eg. full comment support. Combine it with Okaeri Validator for the best config experience. Total of only ~155kB, less than half of just the latest snakeyaml 1.28 which is 319kB!

For any platform if some form of config validation is applicable (eg. requiring that integer is positive) it is recommended to use Okaeri Validator when possible. Only few kilobytes but makes for a lot better experience for the end-user and developer too.

For any platform if some form of the i18n/translation is needed, you may be interested in okaeri-i18n which can use okaeri-configs as a translation source.

Genesis

Okaeri's configuration library is an easy way to use java classes as config adapters:

Example

// getter/setter from lombok recommended
@Header("################################################################")
@Header("#                                                              #")
@Header("#    okaeri-configs test                                       #")
@Header("#                                                              #")
@Header("#    Nie wiesz jak uzywac? Zerknij do dokumentacji!            #")
@Header("#    https://github.com/OkaeriPoland/okaeri-configs            #")
@Header("#                                                              #")
@Header("#    Trouble using? Check out the documentation!               #")
@Header("#    https://github.com/OkaeriPoland/okaeri-configs            #")
@Header("#                                                              #")
@Header("################################################################")
// optional global key formatting (may yield unexpected names, use at own risk)
// @Names(strategy = NameStrategy.HYPHEN_CASE, modifier = NameModifier.TO_LOWER_CASE)
public class TestConfig extends OkaeriConfig {

    @Variable("APP_TOKEN") // use jvm property or environment variable if available
    @Comment({"Klucz prywatny API", "API secret"})
    private String token = "";

    @CustomKey("myList")
    @Comment({"Example list", "providing @CustomKey demonstration"})
    private List<String> exampleList = Collections.singletonList("127.0.0.1");

    @Comment({"Simple maps", "ready to go"})
    private Map<String, String> messages = Collections.singletonMap("test", "testing");

    @Comment({"Test complex map 1", "looks like complex maps are working too"})
    private Map<String, Map<String, Integer>> complexMap = Collections.singletonMap("aa", Collections.singletonMap("bb", 222));

    @Comment("Test complex map 2")
    private Map<String, Map<Integer, String>> complexMap2 = Collections.singletonMap("bb", Collections.singletonMap(232, "aadda"));

    @Comment("Custom objects can be serialized")
    private Location spawn = new Location(null, 1, 2, 3, 4, 5);

    @Comment("Non-string map keys")
    private Map<Integer, String> levels = Collections.singletonMap(1, "aaaaaa");

    @Comment("okaeri-configs likes classes more than primitives")
    private Integer version = 2;

    @Comment({"Test enum", "very nice", "right?"})
    private TestEnum testEnum = TestEnum.ONE_THO_THREE;

    @Comment("Test enum list")
    private List<TestEnum> testEnumList = Arrays.asList(TestEnum.ONE, TestEnum.ONE_THO_THREE);

    @Comment("Test enum set")
    private Set<TestEnum> testEnumSet = new HashSet<>(Arrays.asList(TestEnum.ONE, TestEnum.ONE_THO_THREE));

    @Comment("Test custom object list")
    @Comment(".. and repeating comments")
    private List<Location> testLocationList = Arrays.asList(
            new Location(null, 1, 2, 3, 4, 5),
            new Location(null, 3, 3, 5, 6, 9)
    );

    @Comment("Uber-complex-map test")
    private Map<TestEnum, Location> enumToLocationMap = Collections.singletonMap(TestEnum.THREE, new Location(null, 1, 2, 3, 4, 5));

    @CustomKey("listToUberComplexMap")
    @Comment("List-to-Uber-complex-map test")
    private List<Map<TestEnum, Location>> listMapEnumToLocationMap = Arrays.asList(
            Collections.singletonMap(TestEnum.THREE, new Location(null, 1, 2, 3, 4, 5)),
            Collections.singletonMap(TestEnum.ONE_THO_THREE, new Location(null, 3, 2, 3, 4, 5))
    );

    @Comment("Math test")
    private BigInteger bigInteger = new BigInteger("999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999876543210");

    @Comment("Subconfigs are the way!")
    private StorageConfig storage = new StorageConfig();

    // getter/setter from lombok recommended
    public class StorageConfig extends OkaeriConfig {

        @Variable("APP_STORAGE_URI")
        @Comment("FLAT   : not applicable, plugin controlled")
        @Comment("REDIS  : redis://localhost")
        @Comment("MYSQL  : jdbc:mysql://localhost:3306/db?user=root&password=1234")
        @Comment("H2     : jdbc:h2:file:./plugins/OkaeriPlatformBukkitExample/storage;mode=mysql")
        private String uri = "redis://localhost";

        /* ... */
    }

    // in-memory only field
    private transient Instant start = Instant.now();

    /* ... */
}

Usage

With create(clazz, initializer)

// recommended
TestConfig config = ConfigManager.create(TestConfig.class, (it) -> {
    it.withConfigurer(new YamlBukkitConfigurer(), new SerdesBukkit()); // specify configurer implementation, optionally additional serdes packages
    it.withBindFile(new File(this.getDataFolder(), "config.yml")); // specify Path, File or pathname
    it.withRemoveOrphans(true); // automatic removal of undeclared keys
    it.saveDefaults(); // save file if does not exists
    it.load(true); // load and save to update comments/new fields 
});

With create(clazz)

TestConfig config = (TestConfig) ConfigManager.create(TestConfig.class)
    .withConfigurer(new YamlBukkitConfigurer(), new SerdesBukkit()) // specify configurer implementation, optionally additional serdes packages
    .withBindFile(new File(this.getDataFolder(), "config.yml")) // specify Path, File or pathname
    .withRemoveOrphans(true); // automatic removal of undeclared keys
    .saveDefaults() // save file if does not exists
    .load(true); // load and save to update comments/new fields

Supported types