{"id":19317043,"url":"https://github.com/henkelmax/config-builder","last_synced_at":"2025-04-12T13:40:54.095Z","repository":{"id":63938516,"uuid":"405577039","full_name":"henkelmax/config-builder","owner":"henkelmax","description":"A simple Java configuration library.","archived":false,"fork":false,"pushed_at":"2025-01-26T10:40:03.000Z","size":180,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-26T08:13:56.037Z","etag":null,"topics":["config","config-builder","configuration","java","java-library","java8","properties"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/henkelmax.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-09-12T07:33:15.000Z","updated_at":"2025-01-26T10:39:13.000Z","dependencies_parsed_at":"2023-01-14T15:30:55.351Z","dependency_job_id":null,"html_url":"https://github.com/henkelmax/config-builder","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/henkelmax%2Fconfig-builder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/henkelmax%2Fconfig-builder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/henkelmax%2Fconfig-builder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/henkelmax%2Fconfig-builder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/henkelmax","download_url":"https://codeload.github.com/henkelmax/config-builder/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248574333,"owners_count":21126994,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["config","config-builder","configuration","java","java-library","java8","properties"],"created_at":"2024-11-10T01:13:31.886Z","updated_at":"2025-04-12T13:40:54.083Z","avatar_url":"https://github.com/henkelmax.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ConfigBuilder\n\nA simple Java property configuration library.\n\n## Features\n\n- Simple API\n- Supports boolean, integer, long, float, double, string and enum entries out of the box\n- Supports custom entry types\n- Uses the simple, human-readable [properties](https://en.wikipedia.org/wiki/.properties) file format\n- Automatically handles saving and loading\n- Automatically corrects invalid values or missing entries\n- Supports header and per-entry comments\n- Supports default values\n- Supports min and max values\n- Zero dependencies\n- Supports Java 8 and above\n- Extensively tested with unit tests (100% code coverage)\n\n## Usage\n\n**Maven**\n\n``` xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ede.maxhenkel.configbuilder\u003c/groupId\u003e\n  \u003cartifactId\u003econfigbuilder\u003c/artifactId\u003e\n  \u003cversion\u003e2.0.2\u003c/version\u003e\n\u003c/dependency\u003e\n\n\u003crepositories\u003e\n  \u003crepository\u003e\n    \u003cid\u003ehenkelmax.public\u003c/id\u003e\n    \u003curl\u003ehttps://maven.maxhenkel.de/repository/public\u003c/url\u003e\n  \u003c/repository\u003e\n\u003c/repositories\u003e\n```\n\n**Gradle**\n\n``` groovy\ndependencies {\n  implementation 'de.maxhenkel.configbuilder:configbuilder:2.0.2'\n}\n\nrepositories {\n  maven {\n    name = 'henkelmax.public'\n    url = 'https://maven.maxhenkel.de/repository/public'\n  }\n}\n```\n\n## Example Code\n\n```java\npublic static void main(String[] args) {\n    Config config = ConfigBuilder.builder(Config::new)\n        .path(Paths.get(\"config.properties\")) // The path to the config file\n        .keepOrder(true) // Whether the config should keep the order of the entries - Enabled by default\n        .removeUnused(true) // Whether the config should remove entries that were not defined in the builder - Enabled by default\n        .strict(true) // Whether the config should be strict (compliant to Javas Properties implementation) - Disabled by default\n        .saveAfterBuild(true) // Whether the config should be saved after building - Enabled by default\n        .build();\n\n    System.out.println(config.booleanEntry.getKey() + \": \" + config.booleanEntry.get());  // boolean: false\n    System.out.println(config.integerEntry.getKey() + \": \" + config.integerEntry.get());  // integer: 10\n    System.out.println(config.longEntry.getKey() + \": \" + config.longEntry.get());        // long: 10\n    System.out.println(config.floatEntry.getKey() + \": \" + config.floatEntry.get());      // float: 10.0\n    System.out.println(config.doubleEntry.getKey() + \": \" + config.doubleEntry.get());    // double: 10.0\n    System.out.println(config.stringEntry.getKey() + \": \" + config.stringEntry.get());    // string: test123\n    System.out.println(config.enumEntry.getKey() + \": \" + config.enumEntry.get());        // enum: TEST_1\n\n    config.integerEntry.set(15).save(); // Set the value of the integer entry to 15 and saves the config asynchronously\n    config.integerEntry.set(12).saveSync(); // Set the value of the integer entry to 12 and saves the config synchronously\n    config.integerEntry.reset().save(); // Reset the value of the integer entry to the default value and saves the config asynchronously\n}\n\npublic class Config {\n    public final ConfigEntry\u003cBoolean\u003e booleanEntry;\n    public final ConfigEntry\u003cInteger\u003e integerEntry;\n    public final ConfigEntry\u003cLong\u003e longEntry;\n    public final ConfigEntry\u003cFloat\u003e floatEntry;\n    public final ConfigEntry\u003cDouble\u003e doubleEntry;\n    public final ConfigEntry\u003cString\u003e stringEntry;\n    public final ConfigEntry\u003cTestEnum\u003e enumEntry;\n\n    public Config(ConfigBuilder builder) {\n        builder.header(\n                \"My config version 1.0.0\",\n                \"This is a test config\"\n        );\n        booleanEntry = builder.booleanEntry(\"boolean\", false).comment(\"This is a boolean entry\");\n        integerEntry = builder.integerEntry(\"integer\", 10, 0, 20).comment(\"This is an integer entry with the range 0-20\");\n        longEntry = builder.longEntry(\"long\", 10L, 0L, 20L).comment(\"This is a long entry with the range 0-20\");\n        floatEntry = builder.floatEntry(\"float\", 10F, 0F, 20F).comment(\"This is a float entry with the range 0.0-20.0\");\n        doubleEntry = builder.doubleEntry(\"double\", 10D, 0D, 20D).comment(\"This is a double entry with the range 0.0-20.0\");\n        stringEntry = builder.stringEntry(\"string\", \"test123\").comment(\"This is a string entry\");\n        enumEntry = builder.enumEntry(\"enum\", TestEnum.TEST_1).comment(\"This is an enum entry\");\n    }\n}\n\npublic enum TestEnum {\n    TEST_1, TEST_2, TEST_3;\n}\n```\n\nGenerated config file:\n\n```properties\n# My config version 1.0.0\n# This is a test config\n\n# This is a boolean entry\nboolean=false\n# This is an integer entry with the range 0-20\ninteger=10\n# This is a long entry with the range 0-20\nlong=10\n# This is a float entry with the range 0.0-20.0\nfloat=10.0\n# This is a double entry with the range 0.0-20.0\ndouble=10.0\n# This is a string entry\nstring=test123\n# This is an enum entry\nenum=TEST_1\n```\n\n## Supported Value Types\n\nBesides the types shown in the above example, there are several built-in types that are supported out of the box.\n\n### UUIDs\n\n```java\npublic class Config {\n    public final ConfigEntry\u003cUUID\u003e uuidEntry;\n    public Config(ConfigBuilder builder) {\n        uuidEntry = builder.entry(\"uuid_entry\", UUID.fromString(\"cee9f733-870b-48e3-936f-d3be5d527524\")).comment(\"This is a UUID entry\");\n    }\n}\n```\n\n### Lists\n\nThe `StringList` type is a wrapper around an immutable list.\nIt is serialized as a comma separated list of strings.\n\nIt can be instantiated with `StringList.of(String...)` or `StringList.of(List\u003cString\u003e)`.\n\n```java\npublic class Config {\n    public final ConfigEntry\u003cStringList\u003e stringListEntry;\n    public Config(ConfigBuilder builder) {\n        stringListEntry = builder.entry(\"string_list_entry\", StringList.of(\"test\", \"test1\", \"test2\")).comment(\"This is a string list entry\");\n    }\n}\n```\n\nThe same can be done with `IntegerList`.\n\n\n### Maps\n\nThe `StringMap` type is a wrapper around an immutable map.\n\nIt can be instantiated with `StringMap.of(List\u003cMap\u003cString, String\u003e)` or `StringMap.builder().put(key, value).putAll(map).build()`.\n\n```java\npublic class Config {\n    public final ConfigEntry\u003cStringMap\u003e stringMapEntry;\n    public Config(ConfigBuilder builder) {\n        stringMapEntry = builder.entry(\"string_map_entry\", StringMap.builder().put(\"test\", \"123\").put(\"test1\", \"456\").build()).comment(\"This is a string map entry\");\n    }\n}\n```\n\n\n## Adding Custom Value Types\n\n## Variant 1\n\nAdd your value serializer while creating your config builder.\nYou can also override the default value serializer for an already existing type\nby adding a new value serializer for that type.\nCustom types should always be immutable.\n\n```java\npublic static void main(String[] args) {\n    ConfigBuilder\n            .builder(Config::new)\n            .addValueSerializer(CustomType.class, CustomTypeValueSerializer.INSTANCE)\n            .build();\n}\n\npublic class Config {\n    public final ConfigEntry\u003cCustomType\u003e customType;\n\n    public Config(ConfigBuilder builder) {\n        customType = builder.entry(\"test\", new CustomType(\"Test\")).comment(\"This is a custom entry\");\n    }\n}\n\npublic class CustomType {\n    private final String value;\n\n    public CustomType(String value) {\n        this.value = value;\n    }\n\n    public String getValue() {\n        return value;\n    }\n}\n\npublic class CustomTypeValueSerializer implements ValueSerializer\u003cCustomType\u003e {\n    public static final CustomTypeValueSerializer INSTANCE = new CustomTypeValueSerializer();\n\n    @Nullable\n    @Override\n    public CustomType deserialize(String str) {\n        return new CustomType(str);\n    }\n\n    @Nullable\n    @Override\n    public String serialize(CustomType val) {\n        return val.getValue();\n    }\n}\n```\n\n## Variant 2\n\nAnnotate your custom type with `@ValueSerializable` and provide a serializer class that implements `ValueSerializer`.\nCustom types should always be immutable.\n\n```java\n@ValueSerializable(CustomTypeValueSerializer.class)\npublic class CustomType {\n    private final String value;\n\n    public CustomType(String value) {\n        this.value = value;\n    }\n\n    public String getValue() {\n        return value;\n    }\n}\n```\n\nYour serializer class should have a no-args constructor and implement `ValueSerializer`.\nInvalid conversions should return `null`.\n\n```java\npublic class CustomTypeValueSerializer implements ValueSerializer\u003cCustomType\u003e {\n    @Nullable\n    @Override\n    public CustomType deserialize(String str) {\n        return new CustomType(str);\n    }\n    \n    @Nullable\n    @Override\n    public String serialize(CustomType val) {\n        return val.getValue();\n    }\n}\n```\n\nCustom types can be used like this:\n\n```java\npublic static void main(String[] args) {\n    Config config = ConfigBuilder.builder(Config::new)\n            .path(Paths.get(\"config.properties\"))\n            .build();\n\n    System.out.println(config.customType.get().getValue()); // Prints \"Test\"\n    config.customType.set(new CustomType(\"Test2\"));\n    System.out.println(config.customType.get().getValue()); // Prints \"Test2\"\n}\n\npublic class Config {\n    public final ConfigEntry\u003cCustomType\u003e customType;\n\n    public Config(ConfigBuilder builder) {\n        customType = builder.entry(\"test\", new CustomType(\"Test\")).comment(\"This is a custom entry\");\n    }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhenkelmax%2Fconfig-builder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhenkelmax%2Fconfig-builder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhenkelmax%2Fconfig-builder/lists"}