{"id":15089866,"url":"https://github.com/dgroup/tagyml","last_synced_at":"2025-04-11T22:11:17.850Z","repository":{"id":33999967,"uuid":"163536050","full_name":"dgroup/tagyml","owner":"dgroup","description":"Laconic API for YAML files processing","archived":false,"fork":false,"pushed_at":"2023-11-15T08:14:21.000Z","size":116,"stargazers_count":4,"open_issues_count":12,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-25T18:09:52.609Z","etag":null,"topics":["elegantobjects","java","java-library","oop","oop-principles","yaml","yaml-parser","yml","yml-files"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dgroup.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"license.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2018-12-29T19:32:59.000Z","updated_at":"2020-01-06T04:23:27.000Z","dependencies_parsed_at":"2023-11-15T09:28:27.537Z","dependency_job_id":"5ce4c879-a217-41e3-b0ef-fa416157edf1","html_url":"https://github.com/dgroup/tagyml","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dgroup%2Ftagyml","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dgroup%2Ftagyml/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dgroup%2Ftagyml/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dgroup%2Ftagyml/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dgroup","download_url":"https://codeload.github.com/dgroup/tagyml/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248487695,"owners_count":21112191,"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":["elegantobjects","java","java-library","oop","oop-principles","yaml","yaml-parser","yml","yml-files"],"created_at":"2024-09-25T09:02:32.444Z","updated_at":"2025-04-11T22:11:17.808Z","avatar_url":"https://github.com/dgroup.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Maven](https://img.shields.io/maven-central/v/io.github.dgroup/tagyml.svg)](https://mvnrepository.com/artifact/io.github.dgroup/tagyml)\n[![Javadocs](http://www.javadoc.io/badge/io.github.dgroup/tagyml.svg)](http://www.javadoc.io/doc/io.github.dgroup/tagyml)\n[![License: MIT](https://img.shields.io/github/license/mashape/apistatus.svg)](./license.txt)\n[![Commit activity](https://img.shields.io/github/commit-activity/y/dgroup/tagyml.svg?style=flat-square)](https://github.com/dgroup/tagyml/graphs/commit-activity)\n[![Hits-of-Code](https://hitsofcode.com/github/dgroup/tagyml)](https://hitsofcode.com/view/github/dgroup/tagyml)\n\n[![Build Status](https://travis-ci.org/dgroup/tagyml.svg?branch=master\u0026style=for-the-badge)](https://travis-ci.org/dgroup/tagyml)\n[![0pdd](http://www.0pdd.com/svg?name=dgroup/tagyml)](http://www.0pdd.com/p?name=dgroup/tagyml)\n[![Dependency Status](https://requires.io/github/dgroup/tagyml/requirements.svg?branch=master)](https://requires.io/github/dgroup/tagyml/requirements/?branch=master)\n[![Known Vulnerabilities](https://snyk.io/test/github/dgroup/tagyml/badge.svg)](https://snyk.io/org/dgroup/project/58b731a9-6b07-4ccf-9044-ad305ad243e6/?tab=dependencies\u0026vulns=vulnerable)\n\n[![DevOps By Rultor.com](http://www.rultor.com/b/dgroup/tagyml)](http://www.rultor.com/p/dgroup/tagyml)\n[![EO badge](http://www.elegantobjects.org/badge.svg)](http://www.elegantobjects.org/#principles)\n[![We recommend IntelliJ IDEA](http://www.elegantobjects.org/intellij-idea.svg)](https://www.jetbrains.com/idea/)\n\n[![Qulice](https://img.shields.io/badge/qulice-passed-blue.svg)](http://www.qulice.com/)\n[![SQ maintainability](https://sonarcloud.io/api/project_badges/measure?project=io.github.dgroup%3Atagyml\u0026metric=sqale_rating)](https://sonarcloud.io/dashboard?id=io.github.dgroup%3Atagyml)\n[![Codebeat](https://codebeat.co/badges/f61cb4a4-660f-4149-bbc6-8b66fec90941)](https://codebeat.co/projects/github-com-dgroup-tagyml-master)\n[![Codacy Badge](https://api.codacy.com/project/badge/Grade/b7e76567bb99484a9bff9d2ff1ff4be3)](https://www.codacy.com/app/dgroup/tagyml?utm_source=github.com\u0026amp;utm_medium=referral\u0026amp;utm_content=dgroup/tagyml\u0026amp;utm_campaign=Badge_Grade)\n[![Codecov](https://codecov.io/gh/dgroup/tagyml/branch/master/graph/badge.svg?token=Pqdeao3teI)](https://codecov.io/gh/dgroup/tagyml)\n\n**ATTENTION**: We're still in a very early alpha version, the API\nmay and _will_ change frequently. Please, use it at your own risk,\nuntil we release version 1.0.\n\nMaven:\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.github.dgroup\u003c/groupId\u003e\n    \u003cartifactId\u003etagyml\u003c/artifactId\u003e\n\u003c/dependency\u003e\n```\nGradle:\n```groovy\ndependencies {\n    compile 'io.github.dgroup:tagyml:\u003cversion\u003e'\n}\n```\n\n### Get started \n**Represents the YAML file as an object `Teams`**\n\nThe examples below are built on top of [snakeyaml](https://bitbucket.org/asomov/snakeyaml) framework, but you can override it \nby using the [extension point](/src/main/java/io/github/dgroup/tagyml/Yaml.java) in favour of your favourite framework.\n\n 1. Define YAML [file](/src/test/resources/yaml/teams.yaml) for version `1.0`.\n    ```yaml\n    version: 1.0\n\n    teams:\n\n      - id: 100\n        name:     BSS dream team\n        lead:\n          name:   Bob Marley\n          email:  bob.marley@dreamteam.com\n        properties:\n          total-devs: 5\n          total-managers: 10\n\n      - id: 200\n        name:     OSS dream team\n        lead:\n          name:   Jules Verne\n          email:  jules.verne@dreamteam.com\n        properties:\n          total-devs: 5\n          total-managers: 5\n    ```\n    in\n    ```\n    tagyml $ tree\n    ...\n    |-- src\n    |   |-- main\n    |   |   |-- ...\n    |   |\n    |   `-- test\n    |       |-- java\n    |       |   `-- ...\n    |       `-- resources\n    |           `-- yaml\n    |               |-- teams.yaml\n    |               |-- ...\n    ...\n    ```\n 2. Define the interfaces for the domain model\n    ```java\n    /** \n     * YAML file-based team.\n     */\n    public interface Team {\n        int id() throws YamlFormatException;\n        String name() throws YamlFormatException;\n        User lead() throws YamlFormatException;\n        Properties properties() throws YamlFormatException;\n    }\n    \n    /**\n     * YAML file-based user.\n     */\n    public interface User {\n        String name();\n        String email();\n    }\n    ```\n    See [UncheckedYamlFormatException](/src/main/java/io/github/dgroup/tagyml/UncheckedYamlFormatException.java) in case if you don't wan't to throw the checked exception during YAML file parsing procedure.\n\n 3. Define the YAML parsing process\n    ```java\n    public class Teams implements Scalar\u003cIterable\u003cTeam\u003e\u003e {\n\n        private static final Logger LOG = LoggerFactory.getLogger(Teams.class);\n\n        /**\n         * @param path The path to the YAML file.\n         * @param charset The charset of YAML file to read.\n         */\n        public Teams(final Path path, final Charset charset) {\n            this.path = path;\n            this.charset = charset;\n        }\n        \n        @Override\n        public Iterable\u003cTeam\u003e value() throws YamlFormatException {\n            // Parse YAML file using first supported YAML format\n            return new FirstIn\u003c\u003e(\n                // Print to logs the details about failed attempt of\n                // parsing YAML file using a particular format.\n                (version, exception) -\u003e LOG.warn(\n                    new FormattedText(\n                        \"Unable to parse '%s' using '%s' format\",\n                        this.path, version\n                    ).asString(),\n                    exception\n                ),\n                // The exception message in case if YAML file can't be\n                // parsed using any specified formats below\n                new FormattedText(\n                    \"The file %s has unsupported YAML format\", this.path\n                ),\n                // The supported YAML formats\n                new TeamsV1(this.path, this.charset),\n                new TeamsV2(this.path, this.charset),\n                ...\n                new TeamsVn(this.path, this.charset)\n            ).value();\n        }\n    }\n    ```\n    See [FirstIn](/src/main/java/io/github/dgroup/tagyml/format/FirstIn.java).\n\n 4. Define YAML format for version 1.0 - `TeamsV1`\n    ```java\n    final class TeamsV1 implements Format\u003cIterable\u003cTeam\u003e\u003e {\n    \n        private final Path path;\n        private final Charset charset;\n    \n        TeamsV1(final Path path, final Charset charset) {\n            this.path = path;\n            this.charset = charset;\n        }\n\n        @Override\n        public String version() {\n            return \"1.0\";\n        }\n\n        @Override\n        public Iterable\u003cTeam\u003e value() throws YamlFormatException {\n            return new Snakeyaml(YamlFile.class)\n                .apply(new YamlText(this.path, this.charset))\n                .tagTeams();\n        }\n    \n        /**\n         * The object which represents YAML file.\n         * The YAML file should have at least `version` and collection of `team`.\n         * The EO concept is against getters/setters, but we need them in order to\n         *  parse the file by snakeyaml lib, thus, once we completed the parsing\n         *  procedure, we should restrict any possible access to such type of objects.\n         */\n        private static class YamlFile {\n            public double version;\n            public List\u003cYmlTeam\u003e teams;\n    \n            public double tagVersion() throws YamlFormatException {\n                return new Version(this.version).value();\n            }\n    \n            public Iterable\u003cTeam\u003e tagTeams() throws YamlFormatException {\n                return new Mapped\u003c\u003e(\n                    YamlTeam::tagTeam, new TagOf\u003c\u003e(\"teams\", this.teams).value()\n                );\n            }\n        }\n    \n        /**\n         * Represents 1 element from YAML tag `teams`.\n         */\n        private static class YmlTeam {\n            public int id;\n            public String name;\n            public YmlTeamMember lead;\n            public Map\u003cString, String\u003e properties;\n    \n            public Team tagTeam() {\n                return new Team() {\n                    @Override\n                    public int id() throws YamlFormatException {\n                        return new TagOf\u003c\u003e(\"id\", id).value();\n                    }\n    \n                    @Override\n                    public String name() throws YamlFormatException {\n                        return new TagOf\u003c\u003e(\"name\", name).value();\n                    }\n    \n                    @Override\n                    public User lead() throws YamlFormatException {\n                        return new TagOf\u003c\u003e(\"lead\", lead).value().tagUser();\n                    }\n    \n                    @Override\n                    public Properties properties() throws YamlFormatException {\n                        return new PropertiesOf(\"properties\", properties).value();\n                    }\n                };\n            }\n        }\n    \n        /**\n         * Represents YAML tag `lead`\n         */\n        private static class YmlTeamMember {\n            public String name;\n            public String email;\n    \n            public User tagUser() {\n                return new User() {\n                    @Override\n                    public String name() {\n                        return new Unchecked(new TagOf\u003c\u003e(\"name\", name)).value();\n                    }\n\n                    @Override\n                    public String email() {\n                        return new Unchecked(new TagOf\u003c\u003e(\"email\", email)).value();\n                    }\n                );\n            }\n        }\n    }\n    ```\n    See [Format](src/main/java/io/github/dgroup/tagyml/Format.java), \n    [Snakeyaml](src/main/java/io/github/dgroup/tagyml/yaml/Snakeyaml.java), \n    [Version](src/main/java/io/github/dgroup/tagyml/tag/Version.java), \n    [PropertiesOf](src/main/java/io/github/dgroup/tagyml/tag/PropertiesOf.java), \n    [TagOf](src/main/java/io/github/dgroup/tagyml/tag/TagOf.java) and \n    [Unchecked](src/main/java/io/github/dgroup/tagyml/tag/Unchecked.java).\n    \n    Instead of [Snakeyaml](src/main/java/io/github/dgroup/tagyml/yaml/Snakeyaml.java) \n    you may implement [Yaml](/src/main/java/io/github/dgroup/tagyml/Yaml.java) \n    using your favourite framework in the same way.\n \n 5. Parse YAML file in [EO](http://www.elegantobjects.org/#principles) way\n    ```java\n    @Test\n    public void yamlParsingProcessIsSuccessfull() throws YmlFormatException {\n        final Iterable\u003cTeam\u003e teams = new Teams(\n            Paths.get(\"src\", \"test\", \"resources\", \"yml\", \"1.0\", \"teams.yml\")\n        ).value();\n        MatcherAssert.assertThat(\n            \"There are 2 teams defined in YAML file\",\n            teams, Matchers.iterableWithSize(2)\n        );\n        MatcherAssert.assertThat(\n            \"The 1st team defined in YAML tag has id 100\",\n            teams.iterator().next().id(),\n            new IsEqual\u003c\u003e(100)\n        );\n        MatcherAssert.assertThat(\n            \"The 1st team defined in YAML tag has property `total-dev`\",\n            teams.iterator().next().properties().getProperty(\"total-dev\"),\n            new IsEqual\u003c\u003e(5)\n        );\n    }\n    ```\n    See [SnakeyamlTest](/src/test/java/io/github/dgroup/tagyml/yaml/SnakeyamlTest.java)\n    for details. Of course, the test above is testing a lot of things and should \n    be separated into bunch of tests with single `MatcherAssert.assertThat` each,\n    but here it was done for educational purposes.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdgroup%2Ftagyml","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdgroup%2Ftagyml","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdgroup%2Ftagyml/lists"}