{"id":26233969,"url":"https://github.com/teragrep/cnf_01","last_synced_at":"2025-04-22T12:11:36.345Z","repository":{"id":261589637,"uuid":"870566084","full_name":"teragrep/cnf_01","owner":"teragrep","description":"Teragrep Configuration Library for Java","archived":false,"fork":false,"pushed_at":"2025-04-08T07:18:57.000Z","size":64,"stargazers_count":1,"open_issues_count":5,"forks_count":5,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-08T08:27:32.427Z","etag":null,"topics":["config","configuration","java","java-library","library","teragrep"],"latest_commit_sha":null,"homepage":"https://teragrep.com","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/teragrep.png","metadata":{"files":{"readme":"README.adoc","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-10-10T09:18:29.000Z","updated_at":"2025-04-08T07:19:01.000Z","dependencies_parsed_at":"2024-11-27T11:20:26.022Z","dependency_job_id":"4c7e7b9e-2191-40e1-b8ae-3a30c59e406c","html_url":"https://github.com/teragrep/cnf_01","commit_stats":null,"previous_names":["teragrep/cnf_01"],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teragrep%2Fcnf_01","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teragrep%2Fcnf_01/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teragrep%2Fcnf_01/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teragrep%2Fcnf_01/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/teragrep","download_url":"https://codeload.github.com/teragrep/cnf_01/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250237834,"owners_count":21397401,"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","configuration","java","java-library","library","teragrep"],"created_at":"2025-03-13T01:18:20.507Z","updated_at":"2025-04-22T12:11:36.325Z","avatar_url":"https://github.com/teragrep.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"// Before publishing your new repository:\n// 1. Write the readme file\n// 2. Update the issues link in Contributing section in the readme file\n// 3. Update the discussion link in config.yml file in .github/ISSUE_TEMPLATE directory\n\n= Teragrep Configuration Library for Java\n\n// Add a short description of your project. Tell what your project does and what it's used for.\n\nCNF-01 is a library that provides immutable configuration for Java projects. Immutability is achieved by converting the configuration source into an immutable Map. The resulting configuration Map can't be altered even with modifying the underlying source.\n\n== Features\n\n// List your project's features\n- Provides immutable configurations for:\n. configuration files / path properties (`PathConfiguration`)\n. System Properties (`PropertiesConfiguration`)\n. environment variables (`EnvironmentConfiguration`)\n. command line arguments (`ArgsConfiguration`)\n- Default configurations in case the provided configurations from a source are not found or are otherwise broken (`DefaultConfiguration`)\n\n== A Word About Immutability\n\nNotable in CNF-01 is that the *configurations can not change after initialization*.\n\nFor example, something might be added to the Java's System Properties even before calling `asMap()` on the `PropertiesConfiguration` object. However, this will not have effect on the `Configuration` object at all. *All the objects are immutable.*\n\n== How To Implement\n\nWhen implementing CNF-01 to a project, the point is to keep the main objects immutable and simple by moving the handling of configuration to their own objects.\n\nFollow these steps to implement CNF-01 in a Java project:\n\n* Identify the object that has to use configurations.\n* You can define an interface for the factory objects that create the configured objects:\n+\n\n[,java]\n----\npublic interface Factory\u003cT\u003e {\n    public T object();\n}\n----\n\n* Create a Factory object for the object that has to use configurations.\n+\n\n[,java]\n----\npublic final class ExampleFactory implements Factory\u003cExample\u003e {\n\n    private final Map\u003cString, String\u003e config;\n\n    public ExampleFactory(final Map\u003cString, String\u003e config) {\n        this.config = config;\n    }\n\n    @Override\n    public Example object() {\n        // Parsing of values should be done here too if something else than String is needed\n        final String exampleType = config.get(\"example.type\");\n        final String exampleText = config.get(\"example.text\");\n        final Example example;\n\n        if (exampleType.equals(\"good\")) {\n            example = new GoodExample(exampleText);\n        } else {\n            example = new BadExample(exampleText);\n        }\n\n        return example;\n    }\n}\n----\n\n* Utilize the Factory object to get properly initialized objects with the configuration options.\n+\n\n[,java]\n----\nPropertiesConfiguration config = new PropertiesConfiguration();\nMap\u003cString, String\u003e configurationMap = config.asMap();\n\nExampleFactory exampleFactory = new ExampleFactory(configurationMap);\nExample example = exampleFactory.object();\n----\n\n* Create additional factories for other objects that require configurations.\n\n== How To Use\n\n// add instructions how people can start to use your project\n=== Configuration\n\nAll the sources are usable with the same `Configuration` -interface. It has a single function:\n\n[,java]\n----\nMap\u003cString, String\u003e asMap() throws ConfigurationException;\n----\n\n=== System Properties\n\nIn Java, System properties can be utilized with `System.setProperty(key, value)`.\n\nSystem properties can be used as a configuration source in CNF-01 with the `PropertiesConfiguration` object. It has two constructors:\n\n[,java]\n----\npublic PropertiesConfiguration(); // uses System.getProperties()\npublic PropertiesConfiguration(Properties properties); // uses any Java Properties given\n----\n\nMost likely the default constructor is what you'll need, but in some cases the second constructor might become handy.\n\nHere's an example of using `PropertiesConfiguration`:\n\n[,java]\n----\nPropertiesConfiguration config = new PropertiesConfiguration(); // uses System.getProperties()\nMap\u003cString, String\u003e result = config.asMap();\n----\n\n=== Configuration File\n\nOne of the supported configuration sources is a `File`. These are often marked with a \".properties\" file extension but basically any Java's `File` object will do. The properties have to be given in a `key=value` format in the `File`. For example:\n\n[,bash]\n----\nbar=foo\nfoo=bar\n----\n\nA file can be used as a configuration source with the `PathConfiguration` object. It has two constructors:\n\n[,java]\n----\npublic PathConfiguration(final String fileName); // Uses the filename\npublic PathConfiguration(final File file); // Uses Java's File object\n----\n\nHere's an example of using `PathConfiguration`:\n\n[,java]\n----\nConfiguration configuration = new PathConfiguration(\"file/path\");\nMap\u003cString, String\u003e configMap = new HashMap\u003c\u003e();\ntry {\n    configMap = configuration.asMap();\n} catch (ConfigurationException e) {\n    // Handle the exception...\n}\n----\n\n`PathConfiguration` throws an exception if the `File` is not found.\n\nRead Default Configuration section to see how default configurations can be used to avert the need for the try-catch.\n\n=== Command Line Arguments\n\nCommand line arguments (or any `String[] args`) can be utilized as a configuration source with the `ArgsConfiguration` object.\n\nHere's an example of using `ArgsConfiguration`:\n\n[,java]\n----\npublic static void main(String[] args) {\n    Configuration configuration = new ArgsConfiguration(args);\n    Map\u003cString, String\u003e configMap = new HashMap\u003c\u003e();\n    try {\n        configMap = configuration.asMap();\n    } catch (ConfigurationException e) {\n        // Handle the exception...\n    }\n}\n----\n\n`ArgsConfiguration` throws an exception if the Strings in the array don't follow the `key=value` format.\n\nRead Default Configuration section to see how default configurations can be used to avert the need for the try-catch.\n\n=== Environment Variables\n\n`EnvironmentConfiguration` object supports Java's `System.getenv()`, meaning the system's environment variables. The constructor takes no arguments.\n\nHere's an example of using `EnvironmentConfiguration`:\n\n[,java]\n----\nConfiguration configuration = new EnvironmentConfiguration();\nMap\u003cString, String\u003e configMap = configuration.asMap();\n----\n\n=== Default Configuration\n\nDefault configurations can be used in case the `asMap()` function throws `ConfigurationException`. If the function throws an exception, the defaults are used instead. Only `PathConfiguration` and `ArgsConfiguration` can currently throw an exception.\n\n`DefaultConfiguration` follows the pattern of composable decorators introduced in Elegant Objects. Therefore, it takes another `Configuration` object as an argument in the constructor. The second argument is an `ImmutableMap` which is in the CNF-01 library as well.\n\nHere's an example of how to use `DefaultConfiguration` when paired with `PathConfiguration`:\n\n[,java]\n----\nMap\u003cString, String\u003e map = new HashMap\u003c\u003e();\nmap.put(\"foo\", \"bar\");\nImmutableMap\u003cString, String\u003e defaults = new ImmutabilitySupportedMap\u003c\u003e(map).toImmutableMap();\n\nDefaultConfiguration defaultConfiguration = new DefaultConfiguration(\n    new PathConfiguration(\"invalid.path\"), // uses PathConfiguration that will throw an exception\n    defaults\n);\n\nMap\u003cString, String\u003e result = defaultConfiguration.asMap();\n----\n\n== Contributing\n\n// Change the repository name in the issues link to match with your project's name\n\nYou can involve yourself with our project by https://github.com/teragrep/cnf_01/issues/new/choose[opening an issue] or submitting a pull request.\n\nContribution requirements:\n\n. *All changes must be accompanied by a new or changed test.* If you think testing is not required in your pull request, include a sufficient explanation as why you think so.\n. Security checks must pass\n. Pull requests must align with the principles and http://www.extremeprogramming.org/values.html[values] of extreme programming.\n. Pull requests must follow the principles of Object Thinking and Elegant Objects (EO).\n\nRead more in our https://github.com/teragrep/teragrep/blob/main/contributing.adoc[Contributing Guideline].\n\n=== Contributor License Agreement\n\nContributors must sign https://github.com/teragrep/teragrep/blob/main/cla.adoc[Teragrep Contributor License Agreement] before a pull request is accepted to organization's repositories.\n\nYou need to submit the CLA only once. After submitting the CLA you can contribute to all Teragrep's repositories.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fteragrep%2Fcnf_01","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fteragrep%2Fcnf_01","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fteragrep%2Fcnf_01/lists"}