1
mirror of https://github.com/CarmJos/EasyConfiguration.git synced 2026-06-04 10:38:19 +08:00

Compare commits

...

448 Commits

Author SHA1 Message Date
renovate[bot] 1674fccf4b fix(deps): update kotlin monorepo to v2.4.0 2026-06-03 23:55:15 +00:00
renovate[bot] 85266283c4 fix(deps): update dependency com.typesafe:config to v1.4.9 (#243)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-06-03 23:54:59 +00:00
renovate[bot] b0a9f6505c fix(deps): update dependency org.mongodb:mongodb-driver-sync to v5.8.0 (#241)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-05-29 02:01:07 +00:00
renovate[bot] 8c40eb20ea chore(deps): update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.5.6 (#240)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-05-28 00:33:52 +00:00
renovate[bot] 25ff7ab350 fix(deps): update dependency org.mongodb:mongodb-driver-sync to v5.7.1 (#238)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-05-27 17:17:07 +00:00
renovate[bot] ad90251596 chore(deps): update log4j2 monorepo to v2.26.0 (#236)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-05-07 14:42:19 +00:00
renovate[bot] ed05374054 fix(deps): update dependency com.typesafe:config to v1.4.8 (#234)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-05-05 14:36:51 +00:00
renovate[bot] b5681f2412 fix(deps): update dependency org.mongodb:mongodb-driver-sync to v5.7.0 (#233)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-05-01 01:59:52 +00:00
renovate[bot] bd9923ab7e fix(deps): update dependency com.typesafe:config to v1.4.7 (#231)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-28 15:14:18 +00:00
renovate[bot] 9dece6004e fix(deps): update dependency com.google.code.gson:gson to v2.14.0 (#230)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-24 00:34:46 +00:00
renovate[bot] 654782afe1 fix(deps): update kotlin monorepo to v2.3.21 (#223)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-23 14:42:12 +00:00
renovate[bot] 903f0239b2 fix(deps): update dependency org.mongodb:mongodb-driver-sync to v5.6.5 (#228)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-09 13:37:56 +00:00
renovate[bot] dda929c0a9 chore(deps): update log4j2 monorepo to v2.25.4 (#227)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-28 16:53:33 +00:00
renovate[bot] 2482048449 chore(deps): update dependency org.jetbrains.dokka:dokka-maven-plugin to v2.2.0 (#225)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-26 14:33:40 +00:00
carm f54ee83938 feat(holder): Add file type multi configuration. #169 2026-03-11 11:24:27 +08:00
carm f5316eb320 feat(holder): Add file type multi configuration. #169 2026-03-11 11:16:19 +08:00
carm 500eebefde feat(holder): Try to support MultiConfiguration. #169 2026-03-11 11:02:11 +08:00
renovate[bot] d9cb95b2e9 chore(deps): update actions/upload-artifact action to v7 2026-03-10 08:05:30 +08:00
renovate[bot] ce6554c3f1 chore(deps): update dependency org.apache.maven.plugins:maven-shade-plugin to v3.6.2 (#221)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-05 14:36:14 +00:00
renovate[bot] 7dcd690a05 fix(deps): update dependency org.yaml:snakeyaml to v2.6 (#219)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-27 01:25:07 +00:00
renovate[bot] f376f22ad0 fix(deps): update dependency com.typesafe:config to v1.4.6 (#218)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-24 19:45:53 +00:00
renovate[bot] ab586c4b00 fix(deps): update dependency org.mongodb:mongodb-driver-sync to v5.6.4 (#216)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-23 12:44:42 +00:00
renovate[bot] 64cbfaa974 chore(deps): update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.5.5 (#215)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-21 17:50:54 +00:00
dependabot[bot] 3cab343919 build(deps): bump kotlin.version from 2.3.0 to 2.3.10
Bumps `kotlin.version` from 2.3.0 to 2.3.10.

Updates `org.jetbrains.kotlin:kotlin-stdlib-jdk8` from 2.3.0 to 2.3.10
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v2.3.0...v2.3.10)

Updates `org.jetbrains.kotlin:kotlin-maven-plugin` from 2.3.0 to 2.3.10

---
updated-dependencies:
- dependency-name: org.jetbrains.kotlin:kotlin-stdlib-jdk8
  dependency-version: 2.3.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.jetbrains.kotlin:kotlin-maven-plugin
  dependency-version: 2.3.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-21 00:56:59 +08:00
renovate[bot] 1ad8c1f407 chore(deps): update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.15.0 (#207)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-19 00:58:38 +00:00
renovate[bot] 4e6db50049 fix(deps): update dependency org.mongodb:mongodb-driver-sync to v5.6.3 (#209)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-18 22:45:39 +00:00
renovate[bot] e62cef5644 fix(deps): update dependency org.jetbrains:annotations to v26.1.0 (#214)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-18 18:56:13 +00:00
dependabot[bot] d6a56003aa build(deps): bump org.sonatype.central:central-publishing-maven-plugin
Bumps [org.sonatype.central:central-publishing-maven-plugin](https://github.com/sonatype/central-publishing-maven-plugin) from 0.9.0 to 0.10.0.
- [Commits](https://github.com/sonatype/central-publishing-maven-plugin/commits)

---
updated-dependencies:
- dependency-name: org.sonatype.central:central-publishing-maven-plugin
  dependency-version: 0.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-31 02:46:18 +08:00
renovate[bot] 8a5870300d chore(deps): update actions/upload-artifact action to v6 2025-12-29 08:50:26 +08:00
dependabot[bot] 42885b2a12 build(deps): bump kotlin.version from 2.2.21 to 2.3.0
Bumps `kotlin.version` from 2.2.21 to 2.3.0.

Updates `org.jetbrains.kotlin:kotlin-stdlib-jdk8` from 2.2.21 to 2.3.0
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/v2.3.0/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v2.2.21...v2.3.0)

Updates `org.jetbrains.kotlin:kotlin-maven-plugin` from 2.2.21 to 2.3.0

---
updated-dependencies:
- dependency-name: org.jetbrains.kotlin:kotlin-stdlib-jdk8
  dependency-version: 2.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: org.jetbrains.kotlin:kotlin-maven-plugin
  dependency-version: 2.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-29 08:50:04 +08:00
renovate[bot] 96216d5126 chore(deps): update log4j2 monorepo to v2.25.3 (#204)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-16 21:58:48 +00:00
renovate[bot] d890ce1b94 chore(deps): update dependency org.apache.maven.plugins:maven-release-plugin to v3.3.1 (#201)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-13 14:29:02 +00:00
renovate[bot] d1ff4f7014 fix(deps): update dependency org.mongodb:mongodb-driver-sync to v5.6.2 (#199)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-08 21:33:41 +00:00
renovate[bot] 9f3089566c chore(deps): update dependency org.apache.maven.plugins:maven-release-plugin to v3.3.0 (#198)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-03 20:54:54 +00:00
renovate[bot] 79105bf400 chore(deps): update actions/checkout action to v6 2025-12-01 09:31:45 +08:00
renovate[bot] 2b0b74af92 chore(deps): update dependency org.apache.maven.plugins:maven-source-plugin to v3.4.0 (#197)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-29 05:37:12 +00:00
renovate[bot] c65d164167 chore(deps): update dependency org.apache.maven.plugins:maven-jar-plugin to v3.5.0 (#195)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-15 17:30:30 +00:00
renovate[bot] 74bde0c7ea chore(deps): update dependency org.apache.maven.plugins:maven-release-plugin to v3.2.0 (#194)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-09 00:57:07 +00:00
carm 7fba61cb64 docs: Use english version issues templates. 2025-11-06 03:07:02 +08:00
renovate[bot] b609e1d174 chore(deps): update actions/upload-artifact action to v5 2025-10-30 10:54:38 +08:00
renovate[bot] bdbd484690 fix(deps): update kotlin monorepo to v2.2.21 (#191)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-23 14:08:33 +00:00
renovate[bot] cc5383b0f2 chore(deps): update github/codeql-action action to v4 2025-10-23 10:37:05 +08:00
renovate[bot] 35d2653f56 chore(deps): update dependency org.jetbrains.dokka:dokka-maven-plugin to v2.1.0 (#190)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-15 18:54:14 +00:00
carm d6fa7710dc fix: Try to ignore errors when applying replacer 2025-10-09 02:58:21 +08:00
renovate[bot] fdb6d81bf0 fix(deps): update dependency org.mongodb:mongodb-driver-sync to v5.6.1 (#186)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-06 14:26:30 +00:00
huanmeng-qwq 6a03d446a3 fix: https://github.com/CarmJos/configured/pull/185#pullrequestreview-3273500562 2025-09-27 15:56:09 +08:00
huanmeng-qwq 4a0e6b0676 refactor deserialize, add set collection dsl 2025-09-27 15:56:09 +08:00
carm fc4a11bc3e docs: Add more wiki files. 2025-09-27 02:29:58 +08:00
carm e95abd6b37 docs: Add more wiki files. 2025-09-27 02:27:29 +08:00
carm 0b4304474e docs: Add more wiki files. 2025-09-27 02:20:07 +08:00
carm f36fb81249 feat: Add "getOr" function for values. 2025-09-27 02:19:48 +08:00
carm b17c157e18 refactor(collection): Refactor builders of collection types (including List and Set). 2025-09-27 02:09:42 +08:00
carm c86985017f refactor(builder): Refactor builder functions to support custom adapters. 2025-09-27 00:55:38 +08:00
renovate[bot] cb7562cd8c chore(deps): update dependency org.sonatype.central:central-publishing-maven-plugin to v0.9.0 2025-09-24 09:19:25 +08:00
renovate[bot] ae6aaa0461 chore(deps): update log4j2 monorepo to v2.25.2 (#183)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-22 12:25:53 +00:00
renovate[bot] c96a6c7e49 chore(deps): update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.14.1 (#182)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-22 09:14:52 +00:00
renovate[bot] 74b5e80cbc chore(deps): update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.12.0 (#181)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-21 08:55:00 +00:00
renovate[bot] 51c5c333e9 chore(deps): update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.5.4 (#180)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-14 02:59:18 +00:00
renovate[bot] f09ed5bbc5 chore(deps): update dependency org.apache.maven.plugins:maven-shade-plugin to v3.6.1 (#179)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-13 23:59:11 +00:00
dependabot[bot] f0abdd87e3 build(deps): bump com.typesafe:config from 1.4.4 to 1.4.5
Bumps [com.typesafe:config](https://github.com/lightbend/config) from 1.4.4 to 1.4.5.
- [Release notes](https://github.com/lightbend/config/releases)
- [Changelog](https://github.com/lightbend/config/blob/main/NEWS.md)
- [Commits](https://github.com/lightbend/config/compare/v1.4.4...v1.4.5)

---
updated-dependencies:
- dependency-name: com.typesafe:config
  dependency-version: 1.4.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-12 08:52:17 +08:00
renovate[bot] 7f091669c7 fix(deps): update dependency org.mongodb:mongodb-driver-sync to v5.6.0 2025-09-12 08:52:10 +08:00
carm 8dbee35757 ci: Update renovate.json 2025-09-12 08:19:16 +08:00
dependabot[bot] 1a2eaff1e6 build(deps): bump kotlin.version from 2.2.10 to 2.2.20
Bumps `kotlin.version` from 2.2.10 to 2.2.20.

Updates `org.jetbrains.kotlin:kotlin-stdlib-jdk8` from 2.2.10 to 2.2.20
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v2.2.10...v2.2.20)

Updates `org.jetbrains.kotlin:kotlin-maven-plugin` from 2.2.10 to 2.2.20

---
updated-dependencies:
- dependency-name: org.jetbrains.kotlin:kotlin-stdlib-jdk8
  dependency-version: 2.2.20
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.jetbrains.kotlin:kotlin-maven-plugin
  dependency-version: 2.2.20
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-11 10:52:07 +08:00
renovate[bot] 36364bc09b fix(deps): update dependency com.google.code.gson:gson to v2.13.2 2025-09-11 10:51:58 +08:00
carm fcb4ced610 feat: Make function interface "serializable" 2025-09-10 08:22:37 +08:00
carm 5df66e59d2 docs: Add Community Standards pages 2025-09-02 18:03:42 +08:00
carm 809cd5b268 docs: Add Community Standards pages 2025-09-02 18:00:38 +08:00
carm 661527a80f docs: Add more pages 2025-09-02 17:40:59 +08:00
carm 9883e75f05 docs: Add more pages 2025-09-02 17:09:40 +08:00
carm c3297d168f docs: Add donation link. 2025-09-02 16:56:46 +08:00
renovate[bot] 627e0ba391 fix(deps): update dependency org.yaml:snakeyaml to v2.5 2025-09-02 16:44:23 +08:00
renovate[bot] b29935ae47 fix(deps): update dependency org.jetbrains:annotations to v26.0.2-1 2025-09-02 16:44:15 +08:00
carm e1a907203e docs: Add wiki module. 2025-09-02 16:43:20 +08:00
carm 3cd1ddb3ad docs: Add wiki module. 2025-09-02 16:42:36 +08:00
renovate[bot] b46e116712 chore(deps): update actions/setup-java action to v5 2025-08-21 23:41:56 +08:00
dependabot[bot] 44194d6055 build(deps): bump org.apache.maven.plugins:maven-javadoc-plugin
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.11.2 to 3.11.3.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.11.2...maven-javadoc-plugin-3.11.3)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-javadoc-plugin
  dependency-version: 3.11.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-21 23:15:49 +08:00
renovate[bot] 47fd058f44 chore(deps): update actions/checkout action to v5 2025-08-15 19:29:18 +08:00
renovate[bot] c73fcafb15 fix(deps): update kotlin monorepo to v2.2.10 2025-08-15 19:28:11 +08:00
carm beb6d93f7b build: Fixed wrong scm connection. 2025-07-28 15:50:46 +08:00
dependabot[bot] d62aa14ca7 build(deps): bump org.apache.maven.plugins:maven-gpg-plugin
Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.2.7 to 3.2.8.
- [Release notes](https://github.com/apache/maven-gpg-plugin/releases)
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.7...maven-gpg-plugin-3.2.8)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-gpg-plugin
  dependency-version: 3.2.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-21 03:32:51 +08:00
dependabot[bot] a439ca5cde build(deps): bump com.typesafe:config from 1.4.3 to 1.4.4
Bumps [com.typesafe:config](https://github.com/lightbend/config) from 1.4.3 to 1.4.4.
- [Release notes](https://github.com/lightbend/config/releases)
- [Changelog](https://github.com/lightbend/config/blob/main/NEWS.md)
- [Commits](https://github.com/lightbend/config/compare/v1.4.3...v1.4.4)

---
updated-dependencies:
- dependency-name: com.typesafe:config
  dependency-version: 1.4.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-21 03:32:45 +08:00
renovate[bot] 0736153fd6 chore(deps): update log4j2 monorepo to v2.25.1 2025-07-21 03:32:27 +08:00
carm 0bce5f1a22 build: Add project module names 2025-07-21 02:31:27 +08:00
carm feb43bb382 fix(list): Fixed error when getting the section list 2025-07-09 15:41:31 +08:00
carm 0bfd15aaad feat(record): Support record type values adapter. 2025-07-02 11:04:27 +08:00
carm 15f395a8e0 test(record): Add testcase for nullable values. 2025-06-26 03:04:21 +08:00
carm a61040a0e2 ci(jdk): Using JDK 21. 2025-06-26 02:28:32 +08:00
carm 8766b4d77b feat(adapter): Support complex ParameterizedType's serialize & deserialize. 2025-06-26 02:24:42 +08:00
carm 8c1214612a feat(adapter): Support complex ParameterizedType's serialize & deserialize. 2025-06-25 09:31:07 +08:00
carm 608d92f834 feat(record): Support record type values adapter. 2025-06-25 07:10:26 +08:00
carm ad6ab9eb36 feat(temp): Add a "temporary source" for Testing/FastDev cases. (Use default config in codes first.) 2025-06-25 07:10:04 +08:00
dependabot[bot] 0eda8d8a0f build(deps-dev): bump log4j.version from 2.24.3 to 2.25.0
Bumps `log4j.version` from 2.24.3 to 2.25.0.

Updates `org.apache.logging.log4j:log4j-api` from 2.24.3 to 2.25.0

Updates `org.apache.logging.log4j:log4j-core` from 2.24.3 to 2.25.0

Updates `org.apache.logging.log4j:log4j-slf4j-impl` from 2.24.3 to 2.25.0

---
updated-dependencies:
- dependency-name: org.apache.logging.log4j:log4j-api
  dependency-version: 2.25.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
- dependency-name: org.apache.logging.log4j:log4j-core
  dependency-version: 2.25.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
- dependency-name: org.apache.logging.log4j:log4j-slf4j-impl
  dependency-version: 2.25.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-25 06:29:38 +08:00
dependabot[bot] b19691b5a4 build(deps): bump org.sonatype.central:central-publishing-maven-plugin
Bumps [org.sonatype.central:central-publishing-maven-plugin](https://github.com/sonatype/central-publishing-maven-plugin) from 0.7.0 to 0.8.0.
- [Commits](https://github.com/sonatype/central-publishing-maven-plugin/commits)

---
updated-dependencies:
- dependency-name: org.sonatype.central:central-publishing-maven-plugin
  dependency-version: 0.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-25 06:29:28 +08:00
renovate[bot] c7331aa556 fix(deps): update kotlin monorepo to v2.2.0 2025-06-25 06:29:18 +08:00
carm a440c050e5 feat(type): Add ofMap(K,V) method for ValueType 2025-06-23 15:27:52 +08:00
renovate[bot] b9d45a9bb9 fix(deps): update dependency org.mongodb:mongodb-driver-sync to v5.5.1 2025-06-10 22:45:19 +08:00
carm 67482de7a9 docs: drop visitors counter 2025-05-14 04:25:23 +08:00
carm 04bedbef07 style: Reformatted code with .editorconfig 2025-05-14 04:24:56 +08:00
carm a4abfb733a style: Reformatted code with .editorconfig 2025-05-14 04:22:48 +08:00
carm 76d276436b ci(deploy): Skip deployment for demo project. 2025-05-14 03:55:54 +08:00
carm e7198f22d5 ci(deploy): Skip deployment for demo project. 2025-05-14 03:48:54 +08:00
carm 5bd20e173f ci(deploy): Skip deployment for demo project. 2025-05-14 03:41:15 +08:00
carm 15c4bb13e8 build(repo): Use official repositories. 2025-05-14 03:33:45 +08:00
dependabot[bot] b74eb5c035 build(deps): bump com.google.code.gson:gson from 2.13.0 to 2.13.1
Bumps [com.google.code.gson:gson](https://github.com/google/gson) from 2.13.0 to 2.13.1.
- [Release notes](https://github.com/google/gson/releases)
- [Changelog](https://github.com/google/gson/blob/main/CHANGELOG.md)
- [Commits](https://github.com/google/gson/compare/gson-parent-2.13.0...gson-parent-2.13.1)

---
updated-dependencies:
- dependency-name: com.google.code.gson:gson
  dependency-version: 2.13.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-14 03:27:17 +08:00
renovate[bot] ed3a68af1e fix(deps): update kotlin monorepo to v2.1.21 2025-05-14 03:25:58 +08:00
dependabot[bot] 447b82c880 build(deps): bump org.mongodb:mongodb-driver-sync from 5.4.0 to 5.5.0
Bumps [org.mongodb:mongodb-driver-sync](https://github.com/mongodb/mongo-java-driver) from 5.4.0 to 5.5.0.
- [Release notes](https://github.com/mongodb/mongo-java-driver/releases)
- [Commits](https://github.com/mongodb/mongo-java-driver/compare/r5.4.0...r5.5.0)

---
updated-dependencies:
- dependency-name: org.mongodb:mongodb-driver-sync
  dependency-version: 5.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-14 03:25:49 +08:00
carm 5700f8c1c6 Merge remote-tracking branch 'origin/master' 2025-04-18 00:53:01 +08:00
carm 1cf230d6b6 chore: Bump to 4.1.4 2025-04-18 00:52:51 +08:00
carm 1ffd4b2f0b build(checks): Bye codacy. 2025-04-18 00:31:42 +08:00
dependabot[bot] 92ce780d6f build(deps): bump kotlin.version from 1.9.22 to 2.1.20
Bumps `kotlin.version` from 1.9.22 to 2.1.20.

Updates `org.jetbrains.kotlin:kotlin-stdlib-jdk8` from 1.9.22 to 2.1.20
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v1.9.22...v2.1.20)

Updates `org.jetbrains.kotlin:kotlin-maven-plugin` from 1.9.22 to 2.1.20

---
updated-dependencies:
- dependency-name: org.jetbrains.kotlin:kotlin-stdlib-jdk8
  dependency-version: 2.1.20
  dependency-type: direct:production
  update-type: version-update:semver-major
- dependency-name: org.jetbrains.kotlin:kotlin-maven-plugin
  dependency-version: 2.1.20
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-18 00:30:08 +08:00
carm a2de3303e8 feat(section): Add more section functions 2025-04-17 23:55:15 +08:00
renovate[bot] 47a1981002 fix(deps): update dependency com.google.code.gson:gson to v2.13.0 2025-04-17 22:06:46 +08:00
renovate[bot] b97bc5d1a9 chore(deps): update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.5.3 2025-04-17 22:05:43 +08:00
carm cc927fdc0e Merge pull request #134 from huanmeng-qwq/language/kotlin
feat: Support kotlin dsl
2025-04-17 22:05:28 +08:00
carm 5dc2693106 build(doc): Removed javadoc generation for demo project. 2025-04-17 18:44:48 +08:00
carm 472ce66ca7 build(kotlin): Fixed version 2025-04-17 18:13:00 +08:00
carm 796771554f Merge branch 'master' into language/kotlin 2025-04-17 17:48:38 +08:00
carm 28cb5d4c83 refactor(demo): Move all tests to demo. 2025-04-17 17:43:29 +08:00
carm a670aec986 fix(deps): Fixed the missing kotlin version. 2025-03-30 22:48:19 +08:00
renovate[bot] 51c54b9b53 fix(deps): update dependency org.mongodb:mongodb-driver-sync to v5.4.0 2025-03-23 01:10:53 +08:00
huanmeng-qwq fa99385ff0 feat: Support kotlin dsl 2025-03-22 17:43:48 +08:00
carm 70a3b893a6 chore(text): Add missing text functions 2025-03-21 03:30:47 +08:00
carm c32a941906 docs: Edit logo size 2025-03-21 02:32:33 +08:00
carm 8b597d10f9 feat: Optimized ContentHandler with Replacer & Inserter. 2025-03-21 02:31:04 +08:00
carm cedfcfd262 docs: Update banners and icons 2025-03-21 02:30:35 +08:00
carm 12add75232 feat: Enhanced text content replacer 2025-03-20 20:28:33 +08:00
carm 4d29a24768 docs: Edited readme 2025-03-20 17:16:33 +08:00
carm 8626b86961 chore: Change logo 2025-03-20 16:08:17 +08:00
carm 754dc1de1f feat: Change logo 2025-03-20 16:04:50 +08:00
carm 3d1d4ca609 chore: Add logo & icon. 2025-03-20 15:32:27 +08:00
carm 990b10b6f0 chore: Add logo & icon. 2025-03-20 15:30:34 +08:00
carm 7462cd720e chore: Optimize code format & functions. 2025-03-19 18:36:08 +08:00
carm 6bc83eb3b3 chore: Optimize code format & functions. 2025-03-19 18:35:45 +08:00
carm dbec551c84 chore: Fixed the param errors. 2025-03-17 01:39:08 +08:00
carm 82cca5eca2 feat(exception): Supported ConfigExceptionHandler for holders. 2025-03-17 01:06:57 +08:00
carm 65f3cc1b3d feat(validator): Support validators for config values.
BREAKING CHANGE: `ValueManifest` and `ConfigValue` added a new type "UNIT" to mark the minimal unit value of this instance.

link #132
2025-03-17 00:26:47 +08:00
carm fae048dd69 feat(validator): Support validators for config values.
BREAKING CHANGE: `ValueManifest` and `ConfigValue` added a new type "UNIT" to mark the minimal unit value of this instance.

link #132
2025-03-16 23:56:36 +08:00
carm 854e3df49f feat: Upgrade configured to v4.1.0 2025-03-15 01:52:52 +08:00
carm f6167c3b5e docs: Update license [skip ci] 2025-03-15 01:51:07 +08:00
carm ffe3e88b3b docs: Translated to English 2025-03-14 19:34:06 +08:00
carm caa3077f48 chore: Add missing @Nullable 2025-03-14 19:33:30 +08:00
carm 05dbf0b504 docs: Redesign readme 2025-03-14 19:20:31 +08:00
carm 810e95198e docs: Redesign readme 2025-03-14 19:17:26 +08:00
carm 10004f16b4 docs(logo): Add project banner & logo 2025-03-14 19:09:43 +08:00
carm 8e19748c7c feat(map): Add more builder functions 2025-03-12 04:04:00 +08:00
carm 17762a2e70 refactor(proj): Change project name to "configured" 2025-03-12 03:27:35 +08:00
carm 7dbd607a3f refactor(proj): Change project name to "configured" 2025-03-12 03:22:40 +08:00
carm 035e8a227e test(parse): Add more tests 2025-03-06 20:12:33 +08:00
carm 04eaf6606d feat: Jump to 4.0.11 2025-03-06 18:19:25 +08:00
carm e558e93410 feat(sql): Support custom sql table schema 2025-03-06 18:19:06 +08:00
flowerinsnow e55fe3a8d5 feat: hocon supported 2025-03-06 18:03:27 +08:00
carm 8f075b99b5 chore(deps): use parent dependencies' version 2025-03-04 11:58:01 +08:00
carm 09a0b3c373 chore(deps): use parent dependencies' version 2025-03-04 11:34:16 +08:00
carm 4df4977733 feat(msg): add enhanced text support 2025-03-04 04:21:58 +08:00
carm 6434feb980 fix(sql): Fixed sql table format 2025-03-04 01:57:04 +08:00
carm bc3e4b3e6f fix(comment): Fixed yaml comments 2025-03-04 01:24:12 +08:00
carm c2a9e2254c feat(section): Add ConfigureSection#asMap function 2025-03-04 01:06:21 +08:00
carm 251dd208af feat(sql): Support SQL sources 2025-03-03 19:00:28 +08:00
carm afd1bbfc0f feat(sql): Support SQL sources 2025-03-03 18:52:41 +08:00
carm a699f6c164 feat(sql): Support SQL sources 2025-03-03 18:51:21 +08:00
carm 844cbfab53 feat(sql): Try to implement sql source 2025-02-27 13:32:12 +08:00
carm f74d5d29f9 feat(mongo): Finished source for MongoDB #105 2025-02-27 00:46:44 +08:00
carm 6f28abebb9 feat(section): Add #path and #fullPath for sections 2025-02-25 00:04:24 +08:00
LSeng 842cd78ce3 feat(section): Implement createSection() for ShadedSection 2025-02-22 23:56:45 +08:00
carm 11f1f36a15 docs: Change logo file 2025-02-22 10:13:54 +08:00
renovate[bot] ee9f29ba30 chore(deps): update dependency org.apache.maven.plugins:maven-compiler-plugin to v3.14.0 2025-02-22 09:57:51 +08:00
carm f5bccdaad5 chore: Upgraded to 4.0.6 2025-02-22 09:57:24 +08:00
carm f5f70ff69b chore(source): Add more pre implemented functions 2025-02-22 09:56:59 +08:00
carm 3e221740bc feat(section): Implement shaded sections 2025-02-22 09:55:28 +08:00
LSeng 96d09be977 feat(section): support ShadedSection 2025-02-21 20:48:37 +08:00
carm 5d7c946db5 feat(section): Implement more sections 2025-02-21 18:45:15 +08:00
carm 9e008ff4cd feat(section): Add shaded section 2025-02-21 17:31:05 +08:00
carm df19da170b feat(section): Add #contains and #containsValue methods 2025-02-21 17:15:16 +08:00
carm 3473ef2247 feat: Implement more sections functions 2025-02-21 16:17:12 +08:00
carm d543530305 feat: Implement more sections functions 2025-02-21 16:09:58 +08:00
carm d81855697c feat: Implement more sections functions 2025-02-21 11:27:03 +08:00
carm 5c16e98f30 feat(section): Implement more sections 2025-02-21 03:20:11 +08:00
carm 3f1ffadeff feat(section): Implement more sections 2025-02-21 03:07:43 +08:00
carm d8191b7c6d feat(section): Add original method 2025-02-21 02:00:36 +08:00
carm ba66220f92 docs(sponsor): Add sponsors banner 2025-02-21 01:00:27 +08:00
carm 730d6d7e9c docs(sponsor): Add sponsors banner 2025-02-21 00:58:32 +08:00
carm 4523190cb0 feat: Upgraded to 4.0.5 2025-02-20 16:50:07 +08:00
carm 2a49e2ee6b docs: Fixed quantity usage 2025-02-20 16:49:36 +08:00
carm 77b223b2cb feat: Add stream functions 2025-02-20 16:38:49 +08:00
carm 8e7ac263e7 feat: Split MapSection and MemorySection 2025-02-20 03:01:45 +08:00
carm 80f03ec501 feat: Split MapSection and MemorySection 2025-02-20 02:52:19 +08:00
carm 1c002ae535 feat: Split MapSection and MemorySection 2025-02-20 02:50:00 +08:00
carm a4659c5c9f docs: Englished documents 2025-02-20 00:11:06 +08:00
carm 1c27c2f881 fix: Fixed the missing implements of #remove 2025-02-19 00:57:17 +08:00
carm 476cb79e2f feat: Support standard "pre-load" option 2025-02-18 21:47:58 +08:00
carm bf716b06ae docs: Add more javadocs 2025-02-18 17:33:28 +08:00
carm 00170e6d77 feat: Simplify the ConfigureSection functions to support more different usages. 2025-02-18 17:08:12 +08:00
carm 1bac201427 chore: Add more limitations for inline comments 2025-02-18 14:12:28 +08:00
carm cd77639df5 docs: Add examples 2025-02-17 18:37:16 +08:00
renovate[bot] 5ae756929a fix(deps): update dependency cc.carm.lib:yamlcommentwriter to v1.2.0 2025-02-17 18:28:00 +08:00
carm a9e80aecce fix(text): Fixed wrong type of text 2025-02-17 18:28:00 +08:00
carm 477f0d11bc fix(text): Fixed wrong type of text 2025-02-17 06:43:30 +08:00
renovate[bot] 53ff38a76f fix(deps): update dependency cc.carm.lib:yamlcommentwriter to v1.2.0 2025-02-17 05:24:09 +08:00
carm c32bea3864 fix(builder): Fixed wrong type of serializer 2025-02-17 04:48:15 +08:00
carm 15823bb076 fix(builder): Fixed wrong type of serializer 2025-02-17 04:47:23 +08:00
renovate[bot] f303f56199 fix(deps): update dependency cc.carm.lib:yamlcommentwriter to v1.2.0 2025-02-17 04:27:50 +08:00
carm 22f2674e7c feat(text): Separated the text handler 2025-02-17 04:26:22 +08:00
carm 9eb9c9e13d feat(parser): Supported more insert functions 2025-02-17 03:14:40 +08:00
carm 616314c7f0 feat(parser): Supported more insert functions 2025-02-17 03:13:35 +08:00
carm 05f504a347 feat(parser): Supported parse functions 2025-02-17 02:46:18 +08:00
carm bf6ea97b99 feaT(unit): Add unit meta 2025-02-17 01:40:41 +08:00
carm 9847399e56 feat: Version update to 4.0.1 2025-02-17 00:33:41 +08:00
carm 18515d4a78 refactor(comment): Extract common comment functions 2025-02-17 00:12:29 +08:00
carm 9f1fc5bf90 refactor(comment): Extract common comment functions 2025-02-17 00:11:56 +08:00
carm e7847b2166 feat: Version update to 4.0.1 2025-02-16 23:51:18 +08:00
carm 69cec281be feat: Version update to 4.0.1 2025-02-16 23:47:22 +08:00
carm 28dc9b9e55 feat(text): Implement the ConfiguredText for simply text/msg functions. 2025-02-16 23:46:31 +08:00
LSeng c60ba074d9 fix(comment): Fixed wrong behavior of inline regex comments 2025-02-16 21:59:03 +08:00
carm e88bf301cc ci(javadoc): Fixed javadoc deployment 2025-02-16 02:31:10 +08:00
carm f2c9750c35 chore: Remove wip modules 2025-02-16 02:19:52 +08:00
carm c0f0e989c6 docs: Add missing javadocs 2025-02-16 02:17:49 +08:00
carm 6490edf65e docs: Add missing javadocs 2025-02-16 02:17:31 +08:00
carm 14a5f41649 docs: Add missing javadocs 2025-02-16 02:14:15 +08:00
renovate[bot] 0b16ae08db fix(deps): update dependency org.mongodb:mongodb-driver-sync to v5.3.1 2025-02-16 02:07:12 +08:00
renovate[bot] 020d0df3a3 fix(deps): update dependency cc.carm.lib:yamlcommentwriter to v1.1.0 2025-02-16 02:07:02 +08:00
carm f3bdff1560 ci(deploy): Update central deployment ci 2025-02-16 02:06:11 +08:00
carm d3ec93cef2 feat(source): Update sources' original type 2025-02-16 02:04:31 +08:00
carm 96ed604cd9 feat(source): Update sources' original type 2025-02-16 02:04:14 +08:00
carm eff91b0496 feat(db): Add databased providers assumptions 2025-02-16 01:36:37 +08:00
carm 8db7ecf539 chore(yaml): Simply the yaml dumper 2025-02-15 23:35:21 +08:00
renovate[bot] 1b49e466a9 fix(deps): update dependency org.yaml:snakeyaml to v2.4 2025-02-15 23:12:25 +08:00
carm 6df9f2ce42 feat(factory): Add more options 2025-02-15 07:32:34 +08:00
carm aedc6cb439 feat(map): Finished Map value builders. 2025-02-15 07:20:59 +08:00
carm c79b94b719 feat: Comment resources support #104 2025-02-15 06:06:31 +08:00
carm 3a3533ce81 feat: Optimized comments & sections behavior 2025-02-15 05:56:00 +08:00
carm 4cdd184fe6 feat(yaml): Try implement yaml comments 2025-02-13 22:12:08 +08:00
carm 18199cd1cf feat(yaml): Try implement yaml comments 2025-02-13 07:12:55 +08:00
carm 47e2a4854c feat(yaml): Finished YAML Provider 2025-02-13 06:48:58 +08:00
carm 5b95824bb0 Merge branch '4.0.0'
# Conflicts:
#	providers/yaml/pom.xml
2025-02-13 04:49:17 +08:00
carm 2cda4ae11c chore(sql): Add readme descriptions 2025-02-13 04:46:27 +08:00
carm e840f6bd50 feat(versioned): Add versioned feature 2025-02-13 04:42:49 +08:00
carm 90407dcd0d feat(json): Finished json version's provider 2025-02-13 04:34:52 +08:00
carm 79f59bafe6 feat(json): Finished json version's provider 2025-02-13 01:30:10 +08:00
carm 05ff61a9d9 feat(json): Implement json sources 2025-02-12 04:25:29 +08:00
carm c68d2371ee feat(comment): Support regex inline comments 2025-02-12 02:35:59 +08:00
carm 2093091923 feat!(core): Update files sources 2025-02-10 03:16:48 +08:00
carm 45ca8b02d4 feat!(core): Finished the design of core module 2025-02-09 03:49:37 +08:00
dependabot[bot] 7f09e6cdf7 chore(deps): Bump com.google.code.gson:gson from 2.11.0 to 2.12.1
Bumps [com.google.code.gson:gson](https://github.com/google/gson) from 2.11.0 to 2.12.1.
- [Release notes](https://github.com/google/gson/releases)
- [Changelog](https://github.com/google/gson/blob/main/CHANGELOG.md)
- [Commits](https://github.com/google/gson/compare/gson-parent-2.11.0...gson-parent-2.12.1)

---
updated-dependencies:
- dependency-name: com.google.code.gson:gson
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-06 16:33:49 +08:00
carm 205db6e5b9 feat!(value): Finished the standard configured values 2025-02-02 23:59:13 +08:00
carm 8ac1faf300 feat!(value): Finished the standard configured values 2025-02-02 23:11:16 +08:00
carm 374a6198d8 feat!(value): Redesigned the Configuration api 2025-02-02 22:29:18 +08:00
renovate[bot] 6ee23ded3b fix(deps): update dependency org.jetbrains:annotations to v26.0.2 2025-01-23 03:46:31 +08:00
renovate[bot] 0c7cc5c156 chore(deps): update actions/upload-artifact action to v4 2025-01-18 05:58:43 +08:00
renovate[bot] 4988bb15ae chore(deps): update github/codeql-action action to v3 2025-01-18 05:58:40 +08:00
renovate[bot] 8b24e8dbff chore(deps): update actions/checkout action to v4 2025-01-18 03:54:31 +08:00
renovate[bot] ce9d858f6c chore(deps): update actions/setup-java action to v4 2025-01-18 03:54:28 +08:00
renovate[bot] efc837b6f0 chore(deps): update codacy/codacy-analysis-cli-action digest to 0991600 2025-01-18 03:38:40 +08:00
renovate[bot] 44e864ef0f fix(deps): update dependency org.bspfsystems:yamlconfiguration to v3.0.2 2025-01-18 03:38:36 +08:00
renovate[bot] ce33d8ff9d Add renovate.json 2025-01-18 00:00:45 +08:00
dependabot[bot] de70c11f21 chore(deps): Bump org.apache.maven.plugins:maven-surefire-plugin
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.5.1 to 3.5.2.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.5.1...surefire-3.5.2)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-03 22:41:24 +08:00
dependabot[bot] a182b9af99 chore(deps): Bump org.apache.maven.plugins:maven-javadoc-plugin
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.10.1 to 3.11.2.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.10.1...maven-javadoc-plugin-3.11.2)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-javadoc-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-03 22:41:16 +08:00
dependabot[bot] c56499c0e9 chore(deps-dev): Bump log4j.version from 2.24.2 to 2.24.3
Bumps `log4j.version` from 2.24.2 to 2.24.3.

Updates `org.apache.logging.log4j:log4j-api` from 2.24.2 to 2.24.3

Updates `org.apache.logging.log4j:log4j-core` from 2.24.2 to 2.24.3

Updates `org.apache.logging.log4j:log4j-slf4j-impl` from 2.24.2 to 2.24.3

---
updated-dependencies:
- dependency-name: org.apache.logging.log4j:log4j-api
  dependency-type: direct:development
  update-type: version-update:semver-patch
- dependency-name: org.apache.logging.log4j:log4j-core
  dependency-type: direct:development
  update-type: version-update:semver-patch
- dependency-name: org.apache.logging.log4j:log4j-slf4j-impl
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-23 23:22:15 +08:00
dependabot[bot] c9150ecb50 chore(deps-dev): Bump log4j.version from 2.24.1 to 2.24.2
Bumps `log4j.version` from 2.24.1 to 2.24.2.

Updates `org.apache.logging.log4j:log4j-api` from 2.24.1 to 2.24.2

Updates `org.apache.logging.log4j:log4j-core` from 2.24.1 to 2.24.2

Updates `org.apache.logging.log4j:log4j-slf4j-impl` from 2.24.1 to 2.24.2

---
updated-dependencies:
- dependency-name: org.apache.logging.log4j:log4j-api
  dependency-type: direct:development
  update-type: version-update:semver-patch
- dependency-name: org.apache.logging.log4j:log4j-core
  dependency-type: direct:development
  update-type: version-update:semver-patch
- dependency-name: org.apache.logging.log4j:log4j-slf4j-impl
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-25 02:28:51 +08:00
dependabot[bot] 5075a4c96d chore(deps): Bump org.apache.maven.plugins:maven-gpg-plugin
Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.2.6 to 3.2.7.
- [Release notes](https://github.com/apache/maven-gpg-plugin/releases)
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.6...maven-gpg-plugin-3.2.7)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-gpg-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-23 16:43:42 +08:00
dependabot[bot] 30a9f3634f chore(deps-dev): Bump log4j.version from 2.24.0 to 2.24.1
Bumps `log4j.version` from 2.24.0 to 2.24.1.

Updates `org.apache.logging.log4j:log4j-api` from 2.24.0 to 2.24.1

Updates `org.apache.logging.log4j:log4j-core` from 2.24.0 to 2.24.1

Updates `org.apache.logging.log4j:log4j-slf4j-impl` from 2.24.0 to 2.24.1

---
updated-dependencies:
- dependency-name: org.apache.logging.log4j:log4j-api
  dependency-type: direct:development
  update-type: version-update:semver-patch
- dependency-name: org.apache.logging.log4j:log4j-core
  dependency-type: direct:development
  update-type: version-update:semver-patch
- dependency-name: org.apache.logging.log4j:log4j-slf4j-impl
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-23 16:42:40 +08:00
dependabot[bot] 022acb97a5 chore(deps): Bump org.apache.maven.plugins:maven-javadoc-plugin
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.10.0 to 3.10.1.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.10.0...maven-javadoc-plugin-3.10.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-javadoc-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-23 16:39:43 +08:00
dependabot[bot] 97eda55ec7 chore(deps): Bump org.apache.maven.plugins:maven-surefire-plugin
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.5.0 to 3.5.1.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.5.0...surefire-3.5.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-23 16:38:00 +08:00
dependabot[bot] 7fe77b1363 chore(deps): Bump org.jetbrains:annotations from 25.0.0 to 26.0.1
Bumps [org.jetbrains:annotations](https://github.com/JetBrains/java-annotations) from 25.0.0 to 26.0.1.
- [Release notes](https://github.com/JetBrains/java-annotations/releases)
- [Changelog](https://github.com/JetBrains/java-annotations/blob/master/CHANGELOG.md)
- [Commits](https://github.com/JetBrains/java-annotations/compare/25.0.0...26.0.1)

---
updated-dependencies:
- dependency-name: org.jetbrains:annotations
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-18 16:08:06 +08:00
dependabot[bot] 9f9f02df51 chore(deps): Bump org.jetbrains:annotations from 24.1.0 to 25.0.0
Bumps [org.jetbrains:annotations](https://github.com/JetBrains/java-annotations) from 24.1.0 to 25.0.0.
- [Release notes](https://github.com/JetBrains/java-annotations/releases)
- [Changelog](https://github.com/JetBrains/java-annotations/blob/master/CHANGELOG.md)
- [Commits](https://github.com/JetBrains/java-annotations/compare/24.1.0...25.0.0)

---
updated-dependencies:
- dependency-name: org.jetbrains:annotations
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-27 21:21:58 +08:00
dependabot[bot] 41a53b1c89 chore(deps): Bump org.apache.maven.plugins:maven-gpg-plugin
Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.2.5 to 3.2.6.
- [Release notes](https://github.com/apache/maven-gpg-plugin/releases)
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.5...maven-gpg-plugin-3.2.6)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-gpg-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-19 20:05:09 +08:00
dependabot[bot] 9626ed8f49 chore(deps): Bump org.apache.maven.plugins:maven-gpg-plugin
Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.2.4 to 3.2.5.
- [Release notes](https://github.com/apache/maven-gpg-plugin/releases)
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.4...maven-gpg-plugin-3.2.5)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-gpg-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-14 22:50:32 +08:00
dependabot[bot] 119f93f234 chore(deps-dev): Bump log4j.version from 2.23.1 to 2.24.0
Bumps `log4j.version` from 2.23.1 to 2.24.0.

Updates `org.apache.logging.log4j:log4j-api` from 2.23.1 to 2.24.0

Updates `org.apache.logging.log4j:log4j-core` from 2.23.1 to 2.24.0

Updates `org.apache.logging.log4j:log4j-slf4j-impl` from 2.23.1 to 2.24.0

---
updated-dependencies:
- dependency-name: org.apache.logging.log4j:log4j-api
  dependency-type: direct:development
  update-type: version-update:semver-minor
- dependency-name: org.apache.logging.log4j:log4j-core
  dependency-type: direct:development
  update-type: version-update:semver-minor
- dependency-name: org.apache.logging.log4j:log4j-slf4j-impl
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-14 22:49:11 +08:00
dependabot[bot] f2b6069389 chore(deps): Bump org.bspfsystems:yamlconfiguration from 2.0.2 to 3.0.1
Bumps [org.bspfsystems:yamlconfiguration](https://github.com/bspfsystems/YamlConfiguration) from 2.0.2 to 3.0.1.
- [Release notes](https://github.com/bspfsystems/YamlConfiguration/releases)
- [Commits](https://github.com/bspfsystems/YamlConfiguration/compare/v2.0.2...v3.0.1)

---
updated-dependencies:
- dependency-name: org.bspfsystems:yamlconfiguration
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-14 22:49:04 +08:00
dependabot[bot] 6e2808380a chore(deps): Bump org.apache.maven.plugins:maven-javadoc-plugin
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.8.0 to 3.10.0.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.8.0...maven-javadoc-plugin-3.10.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-javadoc-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-14 22:48:45 +08:00
dependabot[bot] 3ca44aa233 chore(deps): Bump org.apache.maven.plugins:maven-surefire-plugin
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.3.1 to 3.5.0.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.3.1...surefire-3.5.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-11 15:25:09 +08:00
dependabot[bot] 4de9ebd118 chore(deps): Bump org.apache.maven.plugins:maven-javadoc-plugin
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.7.0 to 3.8.0.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.7.0...maven-javadoc-plugin-3.8.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-javadoc-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-31 07:29:56 +08:00
dependabot[bot] 217cd66bfd chore(deps): Bump org.apache.maven.plugins:maven-release-plugin (#83) 2024-07-16 23:00:30 +00:00
dependabot[bot] f1f9a55e01 chore(deps): Bump org.apache.maven.plugins:maven-release-plugin
Bumps [org.apache.maven.plugins:maven-release-plugin](https://github.com/apache/maven-release) from 3.0.1 to 3.1.0.
- [Release notes](https://github.com/apache/maven-release/releases)
- [Commits](https://github.com/apache/maven-release/compare/maven-release-3.0.1...maven-release-3.1.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-release-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-12 00:14:31 +08:00
dependabot[bot] 530d7b3391 chore(deps): Bump org.apache.maven.plugins:maven-surefire-plugin
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.2.5 to 3.3.1.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.2.5...surefire-3.3.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-12 00:05:47 +08:00
dependabot[bot] 2d381c3ce4 chore(deps): Bump org.apache.maven.plugins:maven-jar-plugin
Bumps [org.apache.maven.plugins:maven-jar-plugin](https://github.com/apache/maven-jar-plugin) from 3.4.1 to 3.4.2.
- [Release notes](https://github.com/apache/maven-jar-plugin/releases)
- [Commits](https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-3.4.1...maven-jar-plugin-3.4.2)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-jar-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-22 07:58:29 +08:00
dependabot[bot] 08626ae8c2 chore(deps): Bump org.bspfsystems:yamlconfiguration from 2.0.1 to 2.0.2
Bumps [org.bspfsystems:yamlconfiguration](https://github.com/bspfsystems/YamlConfiguration) from 2.0.1 to 2.0.2.
- [Release notes](https://github.com/bspfsystems/YamlConfiguration/releases)
- [Commits](https://github.com/bspfsystems/YamlConfiguration/compare/v2.0.1...v2.0.2)

---
updated-dependencies:
- dependency-name: org.bspfsystems:yamlconfiguration
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-04 12:21:34 +08:00
dependabot[bot] 7fe2e74582 chore(deps): Bump org.apache.maven.plugins:maven-shade-plugin
Bumps [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.5.3 to 3.6.0.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.5.3...maven-shade-plugin-3.6.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-shade-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-04 12:21:07 +08:00
dependabot[bot] a49180bb1d chore(deps): Bump org.apache.maven.plugins:maven-javadoc-plugin
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.6.3 to 3.7.0.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.6.3...maven-javadoc-plugin-3.7.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-javadoc-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-04 12:20:11 +08:00
dependabot[bot] 69a4b5e918 chore(deps): Bump com.google.code.gson:gson from 2.10.1 to 2.11.0
Bumps [com.google.code.gson:gson](https://github.com/google/gson) from 2.10.1 to 2.11.0.
- [Release notes](https://github.com/google/gson/releases)
- [Changelog](https://github.com/google/gson/blob/main/CHANGELOG.md)
- [Commits](https://github.com/google/gson/compare/gson-parent-2.10.1...gson-parent-2.11.0)

---
updated-dependencies:
- dependency-name: com.google.code.gson:gson
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-21 00:36:37 +08:00
dependabot[bot] 27c3c7803c chore(deps): Bump org.apache.maven.plugins:maven-jar-plugin
Bumps [org.apache.maven.plugins:maven-jar-plugin](https://github.com/apache/maven-jar-plugin) from 3.4.0 to 3.4.1.
- [Release notes](https://github.com/apache/maven-jar-plugin/releases)
- [Commits](https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-3.4.0...maven-jar-plugin-3.4.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-jar-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-25 08:52:18 +08:00
dependabot[bot] c95b1ae4d4 chore(deps): Bump org.apache.maven.plugins:maven-gpg-plugin
Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.2.3 to 3.2.4.
- [Release notes](https://github.com/apache/maven-gpg-plugin/releases)
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.3...maven-gpg-plugin-3.2.4)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-gpg-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-25 08:52:10 +08:00
dependabot[bot] c7f928686d chore(deps): Bump org.apache.maven.plugins:maven-shade-plugin
Bumps [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.5.2 to 3.5.3.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.5.2...maven-shade-plugin-3.5.3)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-shade-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-25 08:50:00 +08:00
dependabot[bot] 4ab84cfc71 chore(deps): Bump org.apache.maven.plugins:maven-jar-plugin
Bumps [org.apache.maven.plugins:maven-jar-plugin](https://github.com/apache/maven-jar-plugin) from 3.3.0 to 3.4.0.
- [Release notes](https://github.com/apache/maven-jar-plugin/releases)
- [Commits](https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-3.3.0...maven-jar-plugin-3.4.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-jar-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-16 16:15:41 +08:00
dependabot[bot] d347d3de23 chore(deps): Bump org.apache.maven.plugins:maven-gpg-plugin
Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.2.2 to 3.2.3.
- [Release notes](https://github.com/apache/maven-gpg-plugin/releases)
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.2...maven-gpg-plugin-3.2.3)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-gpg-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-16 16:11:16 +08:00
dependabot[bot] 2b48e3146b chore(deps): Bump org.apache.maven.plugins:maven-source-plugin
Bumps [org.apache.maven.plugins:maven-source-plugin](https://github.com/apache/maven-source-plugin) from 3.3.0 to 3.3.1.
- [Commits](https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-3.3.0...maven-source-plugin-3.3.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-source-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-11 11:48:11 +08:00
dependabot[bot] d35958a943 chore(deps): Bump org.apache.maven.plugins:maven-gpg-plugin (#68)
Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.2.1 to 3.2.2.
- [Release notes](https://github.com/apache/maven-gpg-plugin/releases)
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.1...maven-gpg-plugin-3.2.2)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-gpg-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-28 09:03:53 +08:00
dependabot[bot] b7990d4de3 chore(deps): Bump org.apache.maven.plugins:maven-compiler-plugin (#66)
Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.12.1 to 3.13.0.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.12.1...maven-compiler-plugin-3.13.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-compiler-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-20 00:11:23 +08:00
dependabot[bot] f01a15a19d chore(deps): Bump org.apache.maven.plugins:maven-gpg-plugin (#67)
Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.2.0 to 3.2.1.
- [Release notes](https://github.com/apache/maven-gpg-plugin/releases)
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.0...maven-gpg-plugin-3.2.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-gpg-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-20 00:11:15 +08:00
dependabot[bot] 85625bfe05 chore(deps-dev): Bump log4j.version from 2.23.0 to 2.23.1 (#64)
Bumps `log4j.version` from 2.23.0 to 2.23.1.

Updates `org.apache.logging.log4j:log4j-api` from 2.23.0 to 2.23.1

Updates `org.apache.logging.log4j:log4j-core` from 2.23.0 to 2.23.1

Updates `org.apache.logging.log4j:log4j-slf4j-impl` from 2.23.0 to 2.23.1

---
updated-dependencies:
- dependency-name: org.apache.logging.log4j:log4j-api
  dependency-type: direct:development
  update-type: version-update:semver-patch
- dependency-name: org.apache.logging.log4j:log4j-core
  dependency-type: direct:development
  update-type: version-update:semver-patch
- dependency-name: org.apache.logging.log4j:log4j-slf4j-impl
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-12 09:36:09 +08:00
dependabot[bot] cb59471f9b chore(deps): Bump org.apache.maven.plugins:maven-gpg-plugin (#65)
Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.1.0 to 3.2.0.
- [Release notes](https://github.com/apache/maven-gpg-plugin/releases)
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.1.0...maven-gpg-plugin-3.2.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-gpg-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-12 09:35:52 +08:00
dependabot[bot] 112803342a chore(deps): Bump org.apache.maven.plugins:maven-shade-plugin (#63)
Bumps [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.5.1 to 3.5.2.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.5.1...maven-shade-plugin-3.5.2)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-shade-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-22 01:37:24 +08:00
dependabot[bot] fc1792113d chore(deps-dev): Bump log4j.version from 2.22.1 to 2.23.0 (#62)
Bumps `log4j.version` from 2.22.1 to 2.23.0.

Updates `org.apache.logging.log4j:log4j-api` from 2.22.1 to 2.23.0

Updates `org.apache.logging.log4j:log4j-core` from 2.22.1 to 2.23.0

Updates `org.apache.logging.log4j:log4j-slf4j-impl` from 2.22.1 to 2.23.0

---
updated-dependencies:
- dependency-name: org.apache.logging.log4j:log4j-api
  dependency-type: direct:development
  update-type: version-update:semver-minor
- dependency-name: org.apache.logging.log4j:log4j-core
  dependency-type: direct:development
  update-type: version-update:semver-minor
- dependency-name: org.apache.logging.log4j:log4j-slf4j-impl
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-22 01:37:12 +08:00
carm da3d4d1fd2 feat(loader): Refactor loaders and metadata. 2024-01-30 18:01:36 +08:00
carm b912ea369c feat(loader): Refactor loaders and metadata. 2024-01-16 23:25:21 +08:00
carm 2df33e3458 feat(adapter): Finished adapters registry 2024-01-16 03:50:08 +08:00
carm d041828717 feat(adapter): Use registry to manage value adapters 2024-01-16 02:59:21 +08:00
carm c7fb51d6b2 feat(adapter): Use registry to manage value adapters 2024-01-16 02:45:27 +08:00
carm 2ef1471f59 feat(parser): abstract value processor and parsers 2024-01-15 23:32:18 +08:00
carm 20a6eaefcd docs(url): Fixed url 2024-01-14 01:44:05 +08:00
dependabot[bot] e419e2498f chore(deps): Bump org.apache.maven.plugins:maven-surefire-plugin (#61)
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.2.3 to 3.2.5.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.2.3...surefire-3.2.5)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-11 22:33:46 +08:00
dependabot[bot] 6ef4f9aebd chore(deps): Bump org.bspfsystems:yamlconfiguration from 2.0.0 to 2.0.1 (#60)
Bumps [org.bspfsystems:yamlconfiguration](https://github.com/bspfsystems/YamlConfiguration) from 2.0.0 to 2.0.1.
- [Release notes](https://github.com/bspfsystems/YamlConfiguration/releases)
- [Commits](https://github.com/bspfsystems/YamlConfiguration/compare/v2.0.0...v2.0.1)

---
updated-dependencies:
- dependency-name: org.bspfsystems:yamlconfiguration
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-07 00:05:52 +08:00
carm 21a8906ad9 chore(map): Optimize Map builders. 2024-01-05 01:26:50 +08:00
carm c91794c611 chore: optimize some codes 2024-01-04 22:38:45 +08:00
carm 3769cf4438 chore: optimize some codes 2024-01-04 22:08:12 +08:00
carm 34bc7601ee docs(sample): Add sample codes. 🍎 2024-01-04 21:29:06 +08:00
carm 0d19dc236e docs(sample): Add sample codes. 🥚 2024-01-04 21:20:56 +08:00
carm 9647591b0d docs(sample): Add sample codes. 🥚 2024-01-04 21:18:26 +08:00
carm 97db8204dc docs(sample): Add sample codes. 🥚 2024-01-03 23:33:39 +08:00
carm 48050a52a2 docs(sample): Add sample codes. 🥚 2024-01-03 23:28:36 +08:00
carm e42de0eee7 docs(sample): Add sample codes. 🥚 2024-01-03 23:24:59 +08:00
carm 814dae2278 docs(sample): Add sample codes. 🥚 2024-01-03 23:13:25 +08:00
carm db19531c13 docs(sample): Add sample codes. 🥚 2024-01-03 23:09:28 +08:00
dependabot[bot] d0af3e436f chore(deps-dev): Bump log4j.version from 2.22.0 to 2.22.1 (#58)
Bumps `log4j.version` from 2.22.0 to 2.22.1.

Updates `org.apache.logging.log4j:log4j-api` from 2.22.0 to 2.22.1

Updates `org.apache.logging.log4j:log4j-core` from 2.22.0 to 2.22.1

Updates `org.apache.logging.log4j:log4j-slf4j-impl` from 2.22.0 to 2.22.1

---
updated-dependencies:
- dependency-name: org.apache.logging.log4j:log4j-api
  dependency-type: direct:development
  update-type: version-update:semver-patch
- dependency-name: org.apache.logging.log4j:log4j-core
  dependency-type: direct:development
  update-type: version-update:semver-patch
- dependency-name: org.apache.logging.log4j:log4j-slf4j-impl
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-28 01:11:02 +08:00
dependabot[bot] 1252baab76 chore(deps): Bump org.apache.maven.plugins:maven-compiler-plugin (#57)
Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.12.0 to 3.12.1.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.12.0...maven-compiler-plugin-3.12.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-compiler-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-26 11:34:16 +08:00
carm 83037baf10 build(plugin): Fixed build plugins missing. 2023-12-24 21:10:27 +08:00
carm adf90a983b build(plugin): Fixed build plugins missing. 2023-12-24 21:09:13 +08:00
carm 02d816cd8d docs(readme): Relocated contents. 2023-12-24 21:01:09 +08:00
carm 5d5626bff2 build(plugin): Fixed build plugins missing. 2023-12-24 20:59:50 +08:00
carm 363c1e7ed8 docs(readme): listed all supported formats. 2023-12-24 05:16:59 +08:00
carm 7884d49309 docs(readme): listed all supported formats. 2023-12-24 05:11:56 +08:00
carm b77e64e6e6 docs(readme): listed all supported formats. 2023-12-24 05:02:59 +08:00
carm 505b86ec9c feat(sql): Support sql based configuration provider. 2023-12-24 04:52:56 +08:00
carm 374f646f9e feat(sql): Support sql based configuration provider. 2023-12-24 04:52:28 +08:00
carm aa50345329 feat(interface): Support interface root configurations. 2023-12-23 22:25:16 +08:00
carm db8b227317 feat(interface): Support interface root configurations. 2023-12-23 22:24:34 +08:00
carm 60eed8a14d docs(readme): Add English version of README files. 2023-12-23 21:24:45 +08:00
carm d41630be72 docs(readme): Add English version of README files. 2023-12-23 21:24:15 +08:00
carm 1c3a2b01ea docs(readme): Add English version of README files. 2023-12-23 21:18:50 +08:00
carm 1ede74c692 docs(readme): Add English version of README files. 2023-12-23 21:18:20 +08:00
carm 67456a8aac docs(readme): Add English version of README files. 2023-12-23 21:17:43 +08:00
carm f422900fb5 docs(readme): Add English version of README files. 2023-12-23 21:16:00 +08:00
carm b3e0007eba docs(readme): Add English version of README files. 2023-12-23 21:15:15 +08:00
carm 89c8ec8adf fix(type): 修复部分原生类型无法转换的问题。#54 2023-12-21 20:47:13 +08:00
huanmeng_qwq e8f49bf8bc fix(core): 解决 #54 的问题 (#55) 2023-12-21 20:43:15 +08:00
dependabot[bot] 8ac980fdbb chore(deps): Bump org.apache.maven.plugins:maven-compiler-plugin (#53)
Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.11.0 to 3.12.0.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.11.0...maven-compiler-plugin-3.12.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-compiler-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-19 22:51:35 +08:00
dependabot[bot] 9f2e4bc0cb chore(deps): Bump org.apache.maven.plugins:maven-surefire-plugin (#52)
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.2.2 to 3.2.3.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.2.2...surefire-3.2.3)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-15 18:16:48 +08:00
dependabot[bot] ae16d131c3 chore(deps): Bump org.apache.maven.plugins:maven-javadoc-plugin (#51)
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.6.2 to 3.6.3.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.6.2...maven-javadoc-plugin-3.6.3)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-javadoc-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-05 08:24:39 +08:00
dependabot[bot] bd8470a6e8 chore(deps): Bump org.jetbrains:annotations from 24.0.1 to 24.1.0 (#50)
Bumps [org.jetbrains:annotations](https://github.com/JetBrains/java-annotations) from 24.0.1 to 24.1.0.
- [Release notes](https://github.com/JetBrains/java-annotations/releases)
- [Changelog](https://github.com/JetBrains/java-annotations/blob/master/CHANGELOG.md)
- [Commits](https://github.com/JetBrains/java-annotations/compare/24.0.1...24.1.0)

---
updated-dependencies:
- dependency-name: org.jetbrains:annotations
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-16 23:32:53 +08:00
dependabot[bot] 6af2d3fef5 chore(deps): Bump org.apache.maven.plugins:maven-javadoc-plugin (#48)
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.6.0 to 3.6.2.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.6.0...maven-javadoc-plugin-3.6.2)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-javadoc-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-09 14:17:49 +08:00
dependabot[bot] 00f83002c5 chore(deps): Bump org.apache.maven.plugins:maven-surefire-plugin (#49)
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.2.1 to 3.2.2.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.2.1...surefire-3.2.2)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-09 14:17:24 +08:00
dependabot[bot] 0aa548cbbf chore(deps): Bump org.bspfsystems:yamlconfiguration from 1.4.0 to 2.0.0 (#47)
Bumps [org.bspfsystems:yamlconfiguration](https://github.com/bspfsystems/YamlConfiguration) from 1.4.0 to 2.0.0.
- [Release notes](https://github.com/bspfsystems/YamlConfiguration/releases)
- [Commits](https://github.com/bspfsystems/YamlConfiguration/compare/v1.4.0...v2.0.0)

---
updated-dependencies:
- dependency-name: org.bspfsystems:yamlconfiguration
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-02 15:23:03 +08:00
dependabot[bot] 9c0ed1c5c2 chore(deps): Bump org.apache.maven.plugins:maven-surefire-plugin (#46)
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.1.2 to 3.2.1.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.1.2...surefire-3.2.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-25 22:49:50 +08:00
dependabot[bot] bb0998cbac chore(deps): Bump com.typesafe:config from 1.4.2 to 1.4.3 (#45)
Bumps [com.typesafe:config](https://github.com/lightbend/config) from 1.4.2 to 1.4.3.
- [Release notes](https://github.com/lightbend/config/releases)
- [Changelog](https://github.com/lightbend/config/blob/main/NEWS.md)
- [Commits](https://github.com/lightbend/config/compare/v1.4.2...v1.4.3)

---
updated-dependencies:
- dependency-name: com.typesafe:config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-17 23:40:40 +08:00
dependabot[bot] 1eb16f00b6 chore(deps): Bump org.bspfsystems:yamlconfiguration from 1.3.3 to 1.4.0 (#44)
Bumps [org.bspfsystems:yamlconfiguration](https://github.com/bspfsystems/YamlConfiguration) from 1.3.3 to 1.4.0.
- [Release notes](https://github.com/bspfsystems/YamlConfiguration/releases)
- [Commits](https://github.com/bspfsystems/YamlConfiguration/compare/v1.3.3...v1.4.0)

---
updated-dependencies:
- dependency-name: org.bspfsystems:yamlconfiguration
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-14 15:19:19 +08:00
dependabot[bot] 5ccf63b423 chore(deps): Bump org.apache.maven.plugins:maven-shade-plugin (#43)
Bumps [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.5.0 to 3.5.1.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.5.0...maven-shade-plugin-3.5.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-shade-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-26 12:48:04 +08:00
dependabot[bot] f1c0c74574 chore(deps): Bump org.apache.maven.plugins:maven-javadoc-plugin (#42)
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.5.0 to 3.6.0.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.5.0...maven-javadoc-plugin-3.6.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-javadoc-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-19 12:16:10 +08:00
carm 8ee074474c fix(init): 添加文件初始化测试 #40 2023-08-29 02:39:38 +08:00
carm 27a68ead7c feat(map): 支持通过ConfigurationSection创建MapValue。 2023-08-28 17:00:56 +08:00
carm c6cce5208f fix(init): 尝试修复初始化创建无用文件的问题 #40 2023-08-10 02:00:46 +08:00
carm bc67de06f6 fix(init): 尝试修复初始化创建无用文件的问题 #40 2023-08-10 01:57:15 +08:00
carm b668794f5d feat(parse): 新增两种忽略默认值的parseValue方法。 2023-08-07 22:06:03 +08:00
carm 07424284b7 fix(file): 修复 FileConfigProvider#saveResource 文件创建异常的问题。#39 2023-07-18 00:25:40 +08:00
carm 81e024e309 fix(file): 修复 FileConfigProvider#saveResource 文件创建异常的问题。#39 2023-07-18 00:20:31 +08:00
carm 763fc7c758 fix(file): 修复 FileConfigProvider#saveResource 文件创建异常的问题。#39 2023-07-18 00:20:20 +08:00
carm 56557221a4 feat(list): 添加快速获取副本列表的方法 2023-07-17 17:34:34 +08:00
冬花ice e4435bf883 修复路径截取错误导致无法拥有内部object类型的问题 (#38)
* 修复路径截取错误导致无法拥有内部object类型的问题

* 移除测试输出
2023-07-10 12:32:24 +08:00
carm eee4a278d9 feat(value): 支持对Enum对象的快速解析 2023-06-23 14:06:56 +08:00
冬花ice 3a0a8e79b9 feat(hocon): 完成对 HOCON 格式的支持 (#36) 2023-06-21 19:54:30 +08:00
dependabot[bot] 3b2b1b27cc chore(deps): Bump maven-shade-plugin from 3.4.1 to 3.5.0 (#35)
Bumps [maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.4.1 to 3.5.0.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.4.1...maven-shade-plugin-3.5.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-shade-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-20 01:35:02 +08:00
dependabot[bot] d84ea1b7da chore(deps): Bump maven-surefire-plugin from 3.1.0 to 3.1.2 (#34)
Bumps [maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.1.0 to 3.1.2.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.1.0...surefire-3.1.2)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-09 13:37:21 +08:00
dependabot[bot] a1f2cdca04 chore(deps): Bump yamlconfiguration from 1.3.2 to 1.3.3 (#33)
Bumps [yamlconfiguration](https://github.com/bspfsystems/YamlConfiguration) from 1.3.2 to 1.3.3.
- [Release notes](https://github.com/bspfsystems/YamlConfiguration/releases)
- [Commits](https://github.com/bspfsystems/YamlConfiguration/compare/v1.3.2...v1.3.3)

---
updated-dependencies:
- dependency-name: org.bspfsystems:yamlconfiguration
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-09 13:37:12 +08:00
dependabot[bot] c52183aadd chore(deps): Bump maven-release-plugin from 3.0.0 to 3.0.1 (#32)
Bumps [maven-release-plugin](https://github.com/apache/maven-release) from 3.0.0 to 3.0.1.
- [Release notes](https://github.com/apache/maven-release/releases)
- [Commits](https://github.com/apache/maven-release/compare/maven-release-3.0.0...maven-release-3.0.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-release-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-06 03:44:21 +08:00
dependabot[bot] d71aabad2d chore(deps): Bump maven-source-plugin from 3.2.1 to 3.3.0 (#31)
Bumps [maven-source-plugin](https://github.com/apache/maven-source-plugin) from 3.2.1 to 3.3.0.
- [Commits](https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-3.2.1...maven-source-plugin-3.3.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-source-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-23 02:51:34 +08:00
carm 6a007c5187 refactor(api): 🤖 修改部分构造方法名称(破坏性更新) 2023-05-20 09:37:15 +08:00
carm 43b00f2b69 refactor(api): 🤖 优化代码命名逻辑,补充部分Javadoc。 2023-05-20 09:34:30 +08:00
carm 2e61e66cdb refactor(api): 🤖 优化代码命名逻辑,补充部分Javadoc。 2023-05-20 09:21:49 +08:00
dependabot[bot] 39f946c28e chore(deps): Bump maven-gpg-plugin from 3.0.1 to 3.1.0 (#30)
Bumps [maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.0.1 to 3.1.0.
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.0.1...maven-gpg-plugin-3.1.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-gpg-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-09 00:24:43 +08:00
dependabot[bot] 25931ffd7e chore(deps): Bump maven-surefire-plugin from 3.0.0 to 3.1.0 (#29)
Bumps [maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.0.0 to 3.1.0.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.0.0...surefire-3.1.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-09 00:12:17 +08:00
dependabot[bot] de103da879 chore(deps): Bump yamlconfiguration from 1.3.1 to 1.3.2 (#28)
Bumps [yamlconfiguration](https://github.com/bspfsystems/YamlConfiguration) from 1.3.1 to 1.3.2.
- [Release notes](https://github.com/bspfsystems/YamlConfiguration/releases)
- [Commits](https://github.com/bspfsystems/YamlConfiguration/compare/v1.3.1...v1.3.2)

---
updated-dependencies:
- dependency-name: org.bspfsystems:yamlconfiguration
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-15 12:39:03 +08:00
dependabot[bot] 457c22d461 chore(deps): Bump maven-release-plugin from 2.5.3 to 3.0.0 (#27)
Bumps [maven-release-plugin](https://github.com/apache/maven-release) from 2.5.3 to 3.0.0.
- [Release notes](https://github.com/apache/maven-release/releases)
- [Commits](https://github.com/apache/maven-release/compare/maven-release-2.5.3...maven-release-3.0.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-release-plugin
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-22 11:57:50 +08:00
carm aa4225dbba build: 修改Java版本的标签名 2023-03-20 20:17:23 +08:00
carm ddd33154be chore(yaml): 独立 YAMLCommentWriter 项目 2023-03-20 20:11:23 +08:00
carm 727c26a2fb feat(value): 单独提出 ”ValueManifest“ 以解决每个实现类中初始参数复杂的问题,方便后续开发。 2023-03-15 22:24:08 +08:00
dependabot[bot] 9c95a16d90 chore(deps): Bump maven-surefire-plugin from 2.22.2 to 3.0.0 (#26)
Bumps [maven-surefire-plugin](https://github.com/apache/maven-surefire) from 2.22.2 to 3.0.0.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-2.22.2...surefire-3.0.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-15 14:01:18 +08:00
dependabot[bot] 92c05f1a59 chore(deps): Bump annotations from 24.0.0 to 24.0.1 (#25)
Bumps [annotations](https://github.com/JetBrains/java-annotations) from 24.0.0 to 24.0.1.
- [Release notes](https://github.com/JetBrains/java-annotations/releases)
- [Changelog](https://github.com/JetBrains/java-annotations/blob/master/CHANGELOG.md)
- [Commits](https://github.com/JetBrains/java-annotations/commits)

---
updated-dependencies:
- dependency-name: org.jetbrains:annotations
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-05 12:09:12 +08:00
dependabot[bot] 739ed41885 chore(deps): Bump maven-compiler-plugin from 3.10.1 to 3.11.0 (#24)
Bumps [maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.10.1 to 3.11.0.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.10.1...maven-compiler-plugin-3.11.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-compiler-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-01 00:07:08 +08:00
carm a66da01996 style: improve code readability. 2023-02-19 19:54:08 +08:00
carm 6dc0447502 test(map): 添加新版ConfiguredMap测试 2023-02-19 17:19:39 +08:00
carm c49d904665 feat(value): 为ConfiguredList 与 ConfiguredMap 实现相关基础方法 2023-02-19 17:17:33 +08:00
冬花ice b756074ddc fix(list): 允许出现长度为0的List (#23) 2023-02-19 16:49:25 +08:00
dependabot[bot] 9e3dff3e95 chore(deps): Bump maven-javadoc-plugin from 3.4.1 to 3.5.0 (#22)
Bumps [maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.4.1 to 3.5.0.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.4.1...maven-javadoc-plugin-3.5.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-javadoc-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-16 23:59:23 +08:00
carm fd01d9b7ef feat(builder): 为 ConfiguredMap 提供更便利的defaults方法。 2023-02-11 21:45:00 +08:00
carm 0f8383bbf3 Merge remote-tracking branch 'origin/master' 2023-01-16 19:26:13 +08:00
carm 1232c7c4da feat(builder): 提供Functional形式提供defaultValue的方法。 2023-01-16 19:26:07 +08:00
dependabot[bot] 7ac39da4e9 chore(deps): Bump annotations from 23.1.0 to 24.0.0 (#21)
Bumps [annotations](https://github.com/JetBrains/java-annotations) from 23.1.0 to 24.0.0.
- [Release notes](https://github.com/JetBrains/java-annotations/releases)
- [Changelog](https://github.com/JetBrains/java-annotations/blob/master/CHANGELOG.md)
- [Commits](https://github.com/JetBrains/java-annotations/compare/23.1.0...24.0.0)

---
updated-dependencies:
- dependency-name: org.jetbrains:annotations
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-12 22:16:19 +08:00
dependabot[bot] bf89f583db chore(deps): Bump gson from 2.10 to 2.10.1 (#20)
Bumps [gson](https://github.com/google/gson) from 2.10 to 2.10.1.
- [Release notes](https://github.com/google/gson/releases)
- [Changelog](https://github.com/google/gson/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/gson/compare/gson-parent-2.10...gson-parent-2.10.1)

---
updated-dependencies:
- dependency-name: com.google.code.gson:gson
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-10 01:02:32 +08:00
dependabot[bot] 03c69ba3a2 chore(deps): Bump yamlconfiguration from 1.3.0 to 1.3.1 (#19)
Bumps [yamlconfiguration](https://github.com/bspfsystems/YamlConfiguration) from 1.3.0 to 1.3.1.
- [Release notes](https://github.com/bspfsystems/YamlConfiguration/releases)
- [Commits](https://github.com/bspfsystems/YamlConfiguration/compare/v1.3.0...v1.3.1)

---
updated-dependencies:
- dependency-name: org.bspfsystems:yamlconfiguration
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-30 23:07:40 +08:00
dependabot[bot] d9cbd1a283 chore(deps): Bump annotations from 23.0.0 to 23.1.0 (#18)
Bumps [annotations](https://github.com/JetBrains/java-annotations) from 23.0.0 to 23.1.0.
- [Release notes](https://github.com/JetBrains/java-annotations/releases)
- [Changelog](https://github.com/JetBrains/java-annotations/blob/master/CHANGELOG.md)
- [Commits](https://github.com/JetBrains/java-annotations/compare/23.0.0...23.1.0)

---
updated-dependencies:
- dependency-name: org.jetbrains:annotations
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-12 22:49:54 +08:00
carm 96e90dd71b chore 2022-12-11 19:10:50 +08:00
carm a9f3d829bd build(javadoc): 修复Demo项目缺失的javadoc 2022-12-11 02:30:47 +08:00
carm 8eefba5159 feat(init): 支持针对于实体类的初始化 #9 2022-12-11 02:17:30 +08:00
carm 01e20df559 feat(init): 支持针对于实体类的初始化 #9 2022-12-11 02:04:23 +08:00
carm 35398ab741 feat(init): 支持针对于实体类的初始化 #9 2022-12-11 02:02:16 +08:00
carm 6f97166192 fix(parse): 修复Number基础类型转型丢失的问题。 fix #17 2022-12-06 21:53:05 +08:00
dependabot[bot] ccd239ad6b chore(deps): Bump yamlconfiguration from 1.2.2 to 1.3.0 (#16)
Bumps [yamlconfiguration](https://github.com/bspfsystems/YamlConfiguration) from 1.2.2 to 1.3.0.
- [Release notes](https://github.com/bspfsystems/YamlConfiguration/releases)
- [Commits](https://github.com/bspfsystems/YamlConfiguration/compare/v1.2.2...v1.3.0)

---
updated-dependencies:
- dependency-name: org.bspfsystems:yamlconfiguration
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-03 19:50:13 +08:00
dependabot[bot] 69b27476bc chore(deps): Bump maven-shade-plugin from 3.4.0 to 3.4.1 (#15)
Bumps [maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.4.0 to 3.4.1.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.4.0...maven-shade-plugin-3.4.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-shade-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-02 18:31:07 +08:00
dependabot[bot] 0651cac6b0 chore(deps): Bump gson from 2.9.1 to 2.10 (#14)
Bumps [gson](https://github.com/google/gson) from 2.9.1 to 2.10.
- [Release notes](https://github.com/google/gson/releases)
- [Changelog](https://github.com/google/gson/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/gson/compare/gson-parent-2.9.1...gson-parent-2.10)

---
updated-dependencies:
- dependency-name: com.google.code.gson:gson
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-27 00:00:49 +08:00
dependabot[bot] 1a1efad283 Bump maven-shade-plugin from 3.3.0 to 3.4.0 (#11)
Bumps [maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.3.0 to 3.4.0.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.3.0...maven-shade-plugin-3.4.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-shade-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-20 00:12:03 +08:00
dependabot[bot] 3c1ba61b61 Bump yamlconfiguration from 1.2.1 to 1.2.2 (#10)
Bumps [yamlconfiguration](https://github.com/bspfsystems/YamlConfiguration) from 1.2.1 to 1.2.2.
- [Release notes](https://github.com/bspfsystems/YamlConfiguration/releases)
- [Commits](https://github.com/bspfsystems/YamlConfiguration/compare/v1.2.1...v1.2.2)

---
updated-dependencies:
- dependency-name: org.bspfsystems:yamlconfiguration
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-20 00:11:44 +08:00
dependabot[bot] 1a3e84a787 Bump maven-jar-plugin from 3.2.2 to 3.3.0 (#12)
Bumps [maven-jar-plugin](https://github.com/apache/maven-jar-plugin) from 3.2.2 to 3.3.0.
- [Release notes](https://github.com/apache/maven-jar-plugin/releases)
- [Commits](https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-3.2.2...maven-jar-plugin-3.3.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-jar-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-20 00:11:31 +08:00
carm 00228db2c4 chore(dev): 取消开发中模块的部署 2022-09-10 01:11:04 +08:00
carm 0fddfe28af feat(source): 为 ConfigurationWrapper 添加 getSource() 方法以获取源实现内容。
BREAKING-CHANGE: ConfigurationWrapper 更改为泛型类,并新增 “getSource” 方法需要实现。
2022-09-10 00:36:46 +08:00
dependabot[bot] 4a17089da0 Bump gson from 2.9.0 to 2.9.1 (#6)
Bumps [gson](https://github.com/google/gson) from 2.9.0 to 2.9.1.
- [Release notes](https://github.com/google/gson/releases)
- [Changelog](https://github.com/google/gson/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/gson/compare/gson-parent-2.9.0...gson-parent-2.9.1)

---
updated-dependencies:
- dependency-name: com.google.code.gson:gson
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-09 21:54:36 +08:00
dependabot[bot] 8faa7b1c24 Bump yamlconfiguration from 1.2.0 to 1.2.1 (#7)
Bumps [yamlconfiguration](https://github.com/bspfsystems/YamlConfiguration) from 1.2.0 to 1.2.1.
- [Release notes](https://github.com/bspfsystems/YamlConfiguration/releases)
- [Commits](https://github.com/bspfsystems/YamlConfiguration/compare/v1.2.0...v1.2.1)

---
updated-dependencies:
- dependency-name: org.bspfsystems:yamlconfiguration
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-09 21:54:25 +08:00
dependabot[bot] 5e525428fe Bump maven-javadoc-plugin from 3.4.0 to 3.4.1 (#8)
Bumps [maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.4.0 to 3.4.1.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.4.0...maven-javadoc-plugin-3.4.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-javadoc-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-09 21:54:16 +08:00
carm bc0dfd5698 feat(source): 为 ConfigurationWrapper 添加 getSource() 方法以获取源实现内容。
BREAKING-CHANGE: ConfigurationWrapper 更改为泛型类,并新增 “getSource” 方法需要实现。
2022-09-09 21:54:05 +08:00
carm dc28d743db feat(source): 为 ConfigurationWrapper 添加 getSource() 方法以获取源实现内容。
BREAKING-CHANGE: ConfigurationWrapper 更改为泛型类,并新增 “getSource” 方法需要实现。
2022-09-09 21:52:26 +08:00
carm f61294c5f3 feat(sql): 优化数据表结构 2022-08-11 17:43:42 +08:00
carm 6883a464db feat(sql): 添加数据库存储支持 2022-08-11 16:02:12 +08:00
carm bcdf0d9bd1 refactor(comments): 优化注释的存储方式 2022-08-11 16:01:27 +08:00
carm 5f89ff4db7 Merge remote-tracking branch 'origin/master' 2022-05-20 18:18:47 +08:00
carm d6f4970277 [3.1.0] fix(api): configuration reload problem
BREAKING CHANGES: Now we override "onReload()" method to define ConfigurationProvider how to reload the configs.

Fix the problem that when the configuration file is read, the "reload()" method not working.
2022-05-20 18:16:44 +08:00
carm c045ca1489 Merge pull request #5 from CarmJos/dependabot/maven/org.bspfsystems-yamlconfiguration-1.2.0
Bump yamlconfiguration from 1.1.0 to 1.2.0
2022-05-20 10:10:38 +08:00
dependabot[bot] ceea900b08 Bump yamlconfiguration from 1.1.0 to 1.2.0
Bumps [yamlconfiguration](https://github.com/bspfsystems/YamlConfiguration) from 1.1.0 to 1.2.0.
- [Release notes](https://github.com/bspfsystems/YamlConfiguration/releases)
- [Commits](https://github.com/bspfsystems/YamlConfiguration/compare/v1.1.0...v1.2.0)

---
updated-dependencies:
- dependency-name: org.bspfsystems:yamlconfiguration
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-19 14:41:47 +00:00
carm 85bacb24f3 Merge remote-tracking branch 'origin/master' 2022-05-18 23:23:25 +08:00
carm 6b3a353fcc [3.0.0] (breaking-update) update comments usage. 2022-05-18 23:23:11 +08:00
carm 2c026fc0b0 Merge pull request #4 from CarmJos/dependabot/maven/org.bspfsystems-yamlconfiguration-1.1.0
Bump yamlconfiguration from 1.0.11 to 1.1.0
2022-04-25 22:59:37 +08:00
dependabot[bot] f8b4bbd3a9 Bump yamlconfiguration from 1.0.11 to 1.1.0
Bumps [yamlconfiguration](https://github.com/bspfsystems/YamlConfiguration) from 1.0.11 to 1.1.0.
- [Release notes](https://github.com/bspfsystems/YamlConfiguration/releases)
- [Commits](https://github.com/bspfsystems/YamlConfiguration/compare/v1.0.11...v1.1.0)

---
updated-dependencies:
- dependency-name: org.bspfsystems:yamlconfiguration
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-25 14:45:52 +00:00
carm e9a0f0ff30 [ci skip] 补充README介绍 2022-04-23 21:37:25 +08:00
carm e3fe6e7c80 [ci skip] 补充README介绍 2022-04-23 21:37:18 +08:00
carm c179fa2ccd 添加部分注释 2022-04-23 20:52:08 +08:00
carm 390815b790 [2.3.0] 版本更新
- [U] 基于 tchristofferson/ConfigUpdater 项目重写YAML相关配置文件的注释部分。
- [A] 为 @ConfigComment 注解添加 ”statWrap“ 与 "endWrap" 两个选项,用于实现不同样式的注释。
2022-04-23 20:35:48 +08:00
carm 760ac815df [skip ci] 修改协议 2022-04-22 17:54:59 +08:00
carm 216050a701 [skip ci] 修改部分代码格式 2022-04-22 17:50:28 +08:00
carm 6d0ee35197 [skip ci] 修改开源协议 2022-04-22 17:46:28 +08:00
carm 494491cf94 [skip-ci] 修改开源协议 2022-04-22 17:44:21 +08:00
carm 00e88b50ff 修改开源协议 2022-04-22 17:41:34 +08:00
carm 033236c89b 修改开源协议 2022-04-22 17:40:28 +08:00
carm 791fa6e5b4 [2.2.0] 实现内部静态类的自动注册。 2022-04-22 17:29:47 +08:00
carm 51c287a0a7 [2.2.0] 实现内部静态类的自动注册。 2022-04-22 17:16:06 +08:00
carm ab2f898164 [skip ci] 修改CI名 2022-04-22 13:12:25 +08:00
carm 4f4b203240 [skip ci] 移除JSON示例中的注释 2022-04-22 13:11:18 +08:00
carm c94fef893f 修正示例位置 2022-04-22 13:06:48 +08:00
carm c2a08c6c72 Merge remote-tracking branch 'origin/master' 2022-04-22 12:57:21 +08:00
carm dd7a6c819f [2.1.0] 实现JSON版本的数据格式 2022-04-22 12:57:10 +08:00
carm e9c010981e Merge pull request #3 from CarmJos/dependabot/maven/org.apache.maven.plugins-maven-javadoc-plugin-3.4.0
Bump maven-javadoc-plugin from 3.3.2 to 3.4.0
2022-04-22 01:24:28 +08:00
dependabot[bot] 78d52e1aae Bump maven-javadoc-plugin from 3.3.2 to 3.4.0
Bumps [maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.3.2 to 3.4.0.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.3.2...maven-javadoc-plugin-3.4.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-javadoc-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-21 14:35:46 +00:00
carm 42ccc23347 更新版本号 2022-04-21 21:56:45 +08:00
carm 85578e3d8c 修改项目介绍 2022-04-21 19:10:24 +08:00
carm dc4d3664d3 修改项目介绍 2022-04-21 19:09:03 +08:00
carm 2e4cb5480a [1.2.0] 版本更新
- `[R]` 独立 bungee 和 bukkit 平台版本到 MineConfiguration 项目。
- `[U]` 重写Initializer逻辑,并支持根据成员变量顺序加载配置文件。
2022-04-21 18:55:56 +08:00
carm 4b7a7aeae7 完成新Initializer,以支持配置文件内容的顺序加载。 2022-04-21 06:40:32 +08:00
carm 132ca81635 放弃Unsafe包操作 2022-04-19 23:20:40 +08:00
carm 80747ac922 测试Unsafe包操作 2022-04-19 21:43:49 +08:00
carm 0d10a06547 测试抽象类继承获取 2022-04-18 22:38:49 +08:00
carm 0bda97d82a [1.1.0] 实现 ConfigurationSerializable 相关数据的加载、获取与写入。 2022-04-18 05:19:06 +08:00
carm a13ea7569c [skip ci] 修复标签丢失的问题 2022-04-17 23:46:40 +08:00
carm c9f488c932 [skip ci] 修复标签丢失的问题 2022-04-17 23:46:14 +08:00
235 changed files with 15210 additions and 4565 deletions
+6
View File
@@ -0,0 +1,6 @@
# configured Javadoc
Based
on [Github Pages](https://pages.github.com/),
please
see [JavaDoc](https://carmjos.github.io/configured) 。
+3
View File
@@ -0,0 +1,3 @@
# Documentation
See [wiki](https://github.com/CarmJos/configured/wiki).
Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 23 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

-9
View File
@@ -1,9 +0,0 @@
# EasyConfiguration Javadoc
基于 [Github Pages](https://pages.github.com/) 搭建,请访问 [JavaDoc](https://carmjos.github.io/EasyConfiguration) 。
## 如何实现?
若您也想通过 [Github Actions](https://docs.github.com/en/actions/learn-github-actions)
自动部署项目的Javadoc到 [Github Pages](https://pages.github.com/)
可以参考我的文章 [《自动部署Javadoc到Github Pages》](https://pages.carm.cc/doc/javadoc-in-github.html) 。
+346
View File
@@ -0,0 +1,346 @@
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
tab_width = 4
[*.java]
indent_size = 4
max_line_length = 120
ij_java_align_consecutive_assignments = false
ij_java_align_consecutive_variable_declarations = false
ij_java_align_group_field_declarations = false
ij_java_align_multiline_annotation_parameters = false
ij_java_align_multiline_array_initializer_expression = false
ij_java_align_multiline_assignment = false
ij_java_align_multiline_binary_operation = false
ij_java_align_multiline_chained_methods = false
ij_java_align_multiline_deconstruction_list_components = true
ij_java_align_multiline_extends_list = false
ij_java_align_multiline_for = true
ij_java_align_multiline_method_parentheses = false
ij_java_align_multiline_parameters = true
ij_java_align_multiline_parameters_in_calls = false
ij_java_align_multiline_parenthesized_expression = false
ij_java_align_multiline_records = true
ij_java_align_multiline_resources = true
ij_java_align_multiline_ternary_operation = false
ij_java_align_multiline_text_blocks = false
ij_java_align_multiline_throws_list = false
ij_java_align_subsequent_simple_methods = false
ij_java_align_throws_keyword = false
ij_java_align_types_in_multi_catch = true
ij_java_annotation_new_line_in_record_component = false
ij_java_annotation_parameter_wrap = off
ij_java_array_initializer_new_line_after_left_brace = false
ij_java_array_initializer_right_brace_on_new_line = false
ij_java_array_initializer_wrap = off
ij_java_assert_statement_colon_on_next_line = false
ij_java_assert_statement_wrap = off
ij_java_assignment_wrap = off
ij_java_binary_operation_sign_on_next_line = false
ij_java_binary_operation_wrap = off
ij_java_blank_lines_after_anonymous_class_header = 0
ij_java_blank_lines_after_class_header = 0
ij_java_blank_lines_after_imports = 1
ij_java_blank_lines_after_package = 1
ij_java_blank_lines_around_class = 1
ij_java_blank_lines_around_field = 0
ij_java_blank_lines_around_field_in_interface = 0
ij_java_blank_lines_around_field_with_annotations = 0
ij_java_blank_lines_around_initializer = 1
ij_java_blank_lines_around_method = 1
ij_java_blank_lines_around_method_in_interface = 1
ij_java_blank_lines_before_class_end = 0
ij_java_blank_lines_before_imports = 1
ij_java_blank_lines_before_method_body = 0
ij_java_blank_lines_before_package = 0
ij_java_blank_lines_between_record_components = 0
ij_java_block_brace_style = end_of_line
ij_java_block_comment_add_space = false
ij_java_block_comment_at_first_column = true
ij_java_builder_methods =
ij_java_call_parameters_new_line_after_left_paren = false
ij_java_call_parameters_right_paren_on_new_line = false
ij_java_call_parameters_wrap = off
ij_java_case_statement_on_separate_line = true
ij_java_catch_on_new_line = false
ij_java_class_annotation_wrap = split_into_lines
ij_java_class_brace_style = end_of_line
ij_java_class_count_to_use_import_on_demand = 5
ij_java_class_names_in_javadoc = 1
ij_java_deconstruction_list_wrap = normal
ij_java_do_not_indent_top_level_class_members = false
ij_java_do_not_wrap_after_single_annotation = false
ij_java_do_not_wrap_after_single_annotation_in_parameter = false
ij_java_do_while_brace_force = never
ij_java_doc_add_blank_line_after_description = true
ij_java_doc_add_blank_line_after_param_comments = false
ij_java_doc_add_blank_line_after_return = false
ij_java_doc_add_p_tag_on_empty_lines = true
ij_java_doc_align_exception_comments = true
ij_java_doc_align_param_comments = true
ij_java_doc_do_not_wrap_if_one_line = false
ij_java_doc_enable_formatting = true
ij_java_doc_enable_leading_asterisks = true
ij_java_doc_indent_on_continuation = false
ij_java_doc_keep_empty_lines = true
ij_java_doc_keep_empty_parameter_tag = true
ij_java_doc_keep_empty_return_tag = true
ij_java_doc_keep_empty_throws_tag = true
ij_java_doc_keep_invalid_tags = true
ij_java_doc_param_description_on_new_line = false
ij_java_doc_preserve_line_breaks = false
ij_java_doc_use_throws_not_exception_tag = true
ij_java_else_on_new_line = false
ij_java_entity_dd_prefix =
ij_java_entity_dd_suffix = EJB
ij_java_entity_eb_prefix =
ij_java_entity_eb_suffix = Bean
ij_java_entity_hi_prefix =
ij_java_entity_hi_suffix = Home
ij_java_entity_lhi_prefix = Local
ij_java_entity_lhi_suffix = Home
ij_java_entity_li_prefix = Local
ij_java_entity_li_suffix =
ij_java_entity_pk_class = java.lang.String
ij_java_entity_ri_prefix =
ij_java_entity_ri_suffix =
ij_java_entity_vo_prefix =
ij_java_entity_vo_suffix = VO
ij_java_enum_constants_wrap = off
ij_java_enum_field_annotation_wrap = off
ij_java_extends_keyword_wrap = off
ij_java_extends_list_wrap = off
ij_java_field_annotation_wrap = split_into_lines
ij_java_field_name_prefix =
ij_java_field_name_suffix =
ij_java_filter_class_prefix =
ij_java_filter_class_suffix =
ij_java_filter_dd_prefix =
ij_java_filter_dd_suffix =
ij_java_finally_on_new_line = false
ij_java_for_brace_force = never
ij_java_for_statement_new_line_after_left_paren = false
ij_java_for_statement_right_paren_on_new_line = false
ij_java_for_statement_wrap = off
ij_java_generate_final_locals = false
ij_java_generate_final_parameters = false
ij_java_generate_use_type_annotation_before_type = true
ij_java_if_brace_force = never
ij_java_imports_layout = @*, *, |, javax.**, java.**, |, $*
ij_java_indent_case_from_switch = true
ij_java_insert_inner_class_imports = false
ij_java_insert_override_annotation = true
ij_java_keep_blank_lines_before_right_brace = 2
ij_java_keep_blank_lines_between_package_declaration_and_header = 2
ij_java_keep_blank_lines_in_code = 2
ij_java_keep_blank_lines_in_declarations = 2
ij_java_keep_builder_methods_indents = false
ij_java_keep_control_statement_in_one_line = true
ij_java_keep_first_column_comment = true
ij_java_keep_indents_on_empty_lines = false
ij_java_keep_line_breaks = true
ij_java_keep_multiple_expressions_in_one_line = false
ij_java_keep_simple_blocks_in_one_line = false
ij_java_keep_simple_classes_in_one_line = false
ij_java_keep_simple_lambdas_in_one_line = false
ij_java_keep_simple_methods_in_one_line = false
ij_java_label_indent_absolute = false
ij_java_label_indent_size = 0
ij_java_lambda_brace_style = end_of_line
ij_java_layout_on_demand_import_from_same_package_first = true
ij_java_layout_static_imports_separately = true
ij_java_line_comment_add_space = false
ij_java_line_comment_add_space_on_reformat = false
ij_java_line_comment_at_first_column = true
ij_java_listener_class_prefix =
ij_java_listener_class_suffix =
ij_java_local_variable_name_prefix =
ij_java_local_variable_name_suffix =
ij_java_message_dd_prefix =
ij_java_message_dd_suffix = EJB
ij_java_message_eb_prefix =
ij_java_message_eb_suffix = Bean
ij_java_method_annotation_wrap = split_into_lines
ij_java_method_brace_style = end_of_line
ij_java_method_call_chain_wrap = off
ij_java_method_parameters_new_line_after_left_paren = false
ij_java_method_parameters_right_paren_on_new_line = false
ij_java_method_parameters_wrap = off
ij_java_modifier_list_wrap = false
ij_java_multi_catch_types_wrap = normal
ij_java_names_count_to_use_import_on_demand = 3
ij_java_new_line_after_lparen_in_annotation = false
ij_java_new_line_after_lparen_in_deconstruction_pattern = true
ij_java_new_line_after_lparen_in_record_header = false
ij_java_new_line_when_body_is_presented = false
ij_java_packages_to_use_import_on_demand = java.awt.*, javax.swing.*
ij_java_parameter_annotation_wrap = off
ij_java_parameter_name_prefix =
ij_java_parameter_name_suffix =
ij_java_parentheses_expression_new_line_after_left_paren = false
ij_java_parentheses_expression_right_paren_on_new_line = false
ij_java_place_assignment_sign_on_next_line = false
ij_java_prefer_longer_names = true
ij_java_prefer_parameters_wrap = false
ij_java_preserve_module_imports = true
ij_java_record_components_wrap = normal
ij_java_repeat_annotations =
ij_java_repeat_synchronized = true
ij_java_replace_instanceof_and_cast = false
ij_java_replace_null_check = true
ij_java_replace_sum_lambda_with_method_ref = true
ij_java_resource_list_new_line_after_left_paren = false
ij_java_resource_list_right_paren_on_new_line = false
ij_java_resource_list_wrap = off
ij_java_rparen_on_new_line_in_annotation = false
ij_java_rparen_on_new_line_in_deconstruction_pattern = true
ij_java_rparen_on_new_line_in_record_header = false
ij_java_servlet_class_prefix =
ij_java_servlet_class_suffix =
ij_java_servlet_dd_prefix =
ij_java_servlet_dd_suffix =
ij_java_session_dd_prefix =
ij_java_session_dd_suffix = EJB
ij_java_session_eb_prefix =
ij_java_session_eb_suffix = Bean
ij_java_session_hi_prefix =
ij_java_session_hi_suffix = Home
ij_java_session_lhi_prefix = Local
ij_java_session_lhi_suffix = Home
ij_java_session_li_prefix = Local
ij_java_session_li_suffix =
ij_java_session_ri_prefix =
ij_java_session_ri_suffix =
ij_java_session_si_prefix =
ij_java_session_si_suffix = Service
ij_java_space_after_closing_angle_bracket_in_type_argument = false
ij_java_space_after_colon = true
ij_java_space_after_comma = true
ij_java_space_after_comma_in_type_arguments = true
ij_java_space_after_for_semicolon = true
ij_java_space_after_quest = true
ij_java_space_after_type_cast = true
ij_java_space_before_annotation_array_initializer_left_brace = false
ij_java_space_before_annotation_parameter_list = false
ij_java_space_before_array_initializer_left_brace = false
ij_java_space_before_catch_keyword = true
ij_java_space_before_catch_left_brace = true
ij_java_space_before_catch_parentheses = true
ij_java_space_before_class_left_brace = true
ij_java_space_before_colon = true
ij_java_space_before_colon_in_foreach = true
ij_java_space_before_comma = false
ij_java_space_before_deconstruction_list = false
ij_java_space_before_do_left_brace = true
ij_java_space_before_else_keyword = true
ij_java_space_before_else_left_brace = true
ij_java_space_before_finally_keyword = true
ij_java_space_before_finally_left_brace = true
ij_java_space_before_for_left_brace = true
ij_java_space_before_for_parentheses = true
ij_java_space_before_for_semicolon = false
ij_java_space_before_if_left_brace = true
ij_java_space_before_if_parentheses = true
ij_java_space_before_method_call_parentheses = false
ij_java_space_before_method_left_brace = true
ij_java_space_before_method_parentheses = false
ij_java_space_before_opening_angle_bracket_in_type_parameter = false
ij_java_space_before_quest = true
ij_java_space_before_switch_left_brace = true
ij_java_space_before_switch_parentheses = true
ij_java_space_before_synchronized_left_brace = true
ij_java_space_before_synchronized_parentheses = true
ij_java_space_before_try_left_brace = true
ij_java_space_before_try_parentheses = true
ij_java_space_before_type_parameter_list = false
ij_java_space_before_while_keyword = true
ij_java_space_before_while_left_brace = true
ij_java_space_before_while_parentheses = true
ij_java_space_inside_one_line_enum_braces = false
ij_java_space_within_empty_array_initializer_braces = false
ij_java_space_within_empty_method_call_parentheses = false
ij_java_space_within_empty_method_parentheses = false
ij_java_spaces_around_additive_operators = true
ij_java_spaces_around_annotation_eq = true
ij_java_spaces_around_assignment_operators = true
ij_java_spaces_around_bitwise_operators = true
ij_java_spaces_around_equality_operators = true
ij_java_spaces_around_lambda_arrow = true
ij_java_spaces_around_logical_operators = true
ij_java_spaces_around_method_ref_dbl_colon = false
ij_java_spaces_around_multiplicative_operators = true
ij_java_spaces_around_relational_operators = true
ij_java_spaces_around_shift_operators = true
ij_java_spaces_around_type_bounds_in_type_parameters = true
ij_java_spaces_around_unary_operator = false
ij_java_spaces_inside_block_braces_when_body_is_present = false
ij_java_spaces_within_angle_brackets = false
ij_java_spaces_within_annotation_parentheses = false
ij_java_spaces_within_array_initializer_braces = false
ij_java_spaces_within_braces = false
ij_java_spaces_within_brackets = false
ij_java_spaces_within_cast_parentheses = false
ij_java_spaces_within_catch_parentheses = false
ij_java_spaces_within_deconstruction_list = false
ij_java_spaces_within_for_parentheses = false
ij_java_spaces_within_if_parentheses = false
ij_java_spaces_within_method_call_parentheses = false
ij_java_spaces_within_method_parentheses = false
ij_java_spaces_within_parentheses = false
ij_java_spaces_within_record_header = false
ij_java_spaces_within_switch_parentheses = false
ij_java_spaces_within_synchronized_parentheses = false
ij_java_spaces_within_try_parentheses = false
ij_java_spaces_within_while_parentheses = false
ij_java_special_else_if_treatment = true
ij_java_static_field_name_prefix =
ij_java_static_field_name_suffix =
ij_java_subclass_name_prefix =
ij_java_subclass_name_suffix = Impl
ij_java_switch_expressions_wrap = normal
ij_java_ternary_operation_signs_on_next_line = false
ij_java_ternary_operation_wrap = off
ij_java_test_name_prefix =
ij_java_test_name_suffix = Test
ij_java_throws_keyword_wrap = off
ij_java_throws_list_wrap = off
ij_java_use_external_annotations = false
ij_java_use_fq_class_names = false
ij_java_use_relative_indents = false
ij_java_use_single_class_imports = true
ij_java_variable_annotation_wrap = off
ij_java_visibility = public
ij_java_while_brace_force = never
ij_java_while_on_new_line = false
ij_java_wrap_comments = false
ij_java_wrap_first_method_in_call_chain = false
ij_java_wrap_long_lines = false
ij_java_wrap_semicolon_after_call_chain = false
[*.xml]
indent_style = space
indent_size = 4
tab_width = 4
max_line_length = 120
[*.json]
indent_style = space
indent_size = 2
tab_width = 2
max_line_length = 120
[*.{yml,yaml}]
indent_style = space
indent_size = 2
tab_width = 2
max_line_length = 120
[*.md]
max_line_length = 500
trim_trailing_whitespace = false
-1
View File
@@ -1,2 +1 @@
github: [ CarmJos ]
custom: [ 'https://donate.carm.cc' ]
+20 -23
View File
@@ -1,37 +1,34 @@
---
name: 问题提交
about: 描述问题并提交,帮助我们对其进行检查与修复。
title: ''
labels: bug
name: Submit bugs&issues
about: Describe the problem and submit it to help us review and fix it.
title: 'fix: '
labels: bug
assignees: ''
---
### **问题简述**
### **Description**
用简短的话语描述一下大概问题。
<!-- Describe the general problem in short words.-->
### **问题来源**
### **Operations**
描述一下通过哪些操作才发现的问题,如:
<!--
Describe the problem discovered through what operations, such as:
1. 使用了 '...'
2. 输入了 '....'
3. 出现了报错 '....'
1. Clicked '...'
2. Typed '....'
3. Error says '....'
-->
### **预期结果** (可选)
### **Expected result** _(Optional)_
如果问题不发生,应该是什么情况
### **Screenshots & Error Logs**
### **问题截图/问题报错**
### **Environment**
如果有报错或输出,请提供截图。
- System: `Windows 10` / `Ubuntu` / `...`
- Java version: `JDK11` / `OPENJDK8` / `JRE8` / `...`
### **操作环境**
### **Anything else...**
- 系统环境: `Windows 10` / `Ubuntu` / `...`
- Java版本: `JDK11` / `OPENJDK8` / `JRE8` / `...`
### **其他补充**
如有其他补充,可以在这里描述。
<!-- If there are other supplements, they can be described here. -->
+11 -11
View File
@@ -1,23 +1,23 @@
---
name: 功能需求
about: 希望我们提供更多的功能。
title: ''
name: Features
about: Ask for new features.
title: 'feat: '
labels: enhancement
assignees: ''
---
### **功能简述**
### **Description**
简单的描述一下你想要的功能
<!-- Describe the features in short words.-->
### **需求来源**
### **Source**
简单的描述一下为什么需要这个功能。
<!-- Describe the reason that you need this feature in short words.-->
### **功能参考**(可选)
### **Examples** _(Optional)_
如果有相关功能的参考,如文本、截图,请提供给我们。
<!--Any screenshots or example codes please.-->
### **附加内容**
### **Additional details**
如果有什么小细节需要重点注意,请在这里告诉我们。
<!--If there are any small details that need to be highlighted, please let us know here.-->
-54
View File
@@ -1,54 +0,0 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow checks out code, performs a Codacy security scan
# and integrates the results with the
# GitHub Advanced Security code scanning feature. For more information on
# the Codacy security scan action usage and parameters, see
# https://github.com/codacy/codacy-analysis-cli-action.
# For more information on Codacy Analysis CLI in general, see
# https://github.com/codacy/codacy-analysis-cli.
name: "Codacy Security Scan"
on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '27 16 * * 5'
jobs:
codacy-security-scan:
name: Codacy Security Scan
runs-on: ubuntu-latest
steps:
# Checkout the repository to the GitHub Actions runner
- name: Checkout code
uses: actions/checkout@v2
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
- name: Run Codacy Analysis CLI
uses: codacy/codacy-analysis-cli-action@d840f886c4bd4edc059706d09c6a1586111c540b
with:
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
# You can also omit the token and run the tools that support default configurations
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
verbose: true
output: results.sarif
format: sarif
# Adjust severity of non-security issues
gh-code-scanning-compat: true
# Force 0 exit code to allow SARIF file generation
# This will handover control about PR rejection to the GitHub side
max-allowed-issues: 2147483647
# Upload the SARIF file generated in the previous step
- name: Upload SARIF results file
uses: github/codeql-action/upload-sarif@v1
with:
sarif_file: results.sarif
+4 -4
View File
@@ -38,11 +38,11 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v6
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -53,7 +53,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
uses: github/codeql-action/autobuild@v4
# ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -67,4 +67,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v4
+14 -14
View File
@@ -1,7 +1,7 @@
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
name: "Project Deploy"
name: "Deploy & Publish"
on:
# 支持手动触发构建
@@ -16,11 +16,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v6
- name: "Set up JDK"
uses: actions/setup-java@v2
uses: actions/setup-java@v5
with:
java-version: '11'
java-version: '21'
distribution: 'adopt'
cache: maven
server-id: github
@@ -40,14 +40,14 @@ jobs:
run: |
rm -rf docs
mkdir -vp docs
cp -vrf core/target/apidocs/* docs/
cp -vrf .documentation/JAVADOC-README.md docs/README.md
cp -vrf core/target/reports/apidocs/* docs/
cp -vrf .doc/JAVADOC-README.md docs/README.md
- name: "Generate the Javadoc sitemap"
id: sitemap
uses: cicirello/generate-sitemap@v1
with:
base-url-path: https://CarmJos.github.io/EasyConfiguration
base-url-path: https://CarmJos.github.io/configured
path-to-root: docs
- name: "Output stats"
@@ -72,7 +72,7 @@ jobs:
run: |
cd docs
git init
git remote add origin git@github.com:CarmJos/EasyConfiguration.git
git remote add origin git@github.com:CarmJos/configured.git
git checkout -b gh-pages
git add -A
git commit -m "API Document generated."
@@ -87,22 +87,22 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v6
- name: "Set up JDK"
uses: actions/setup-java@v2
uses: actions/setup-java@v5
with:
java-version: '11'
java-version: '21'
distribution: 'adopt'
cache: maven
server-id: ossrh
server-id: central
server-username: MAVEN_USERNAME
server-password: MAVEN_PASSWORD
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} # Value of the GPG private key to import
gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase
- name: "Central Deploy"
run: mvn -B -Possrh deploy --file pom.xml -DskipTests
run: mvn -B -Pcentral deploy --file pom.xml -DskipTests
env:
MAVEN_USERNAME: ${{ secrets.OSSRH_USER }}
MAVEN_PASSWORD: ${{ secrets.OSSRH_PASS }}
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
+5 -5
View File
@@ -1,7 +1,7 @@
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
name: Project Build & Tests
name: Build & Tests
on:
# 支持手动触发构建
@@ -15,18 +15,18 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v6
- name: "Set up JDK"
uses: actions/setup-java@v2
uses: actions/setup-java@v5
with:
java-version: '11'
java-version: '21'
distribution: 'adopt'
- name: "Package"
run: mvn -B package --file pom.xml -Dgpg.skip
- name: "Target Stage"
run: mkdir staging && cp */target/*.jar staging
- name: "Upload artifact"
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v7
with:
name: Artifact
path: staging
+2 -1
View File
@@ -1,3 +1,4 @@
/.idea/
.idea/*
!.idea/icon.svg
**/target/
**.iml
+3
View File
@@ -0,0 +1,3 @@
[submodule ".wiki"]
path = .wiki
url = https://github.com/CarmJos/configured.wiki.git
+36
View File
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 23 KiB

Submodule
+1
Submodule .wiki added at c79c6f4a43
+75
View File
@@ -0,0 +1,75 @@
# Code of Conduct
(English primary version a brief Chinese note may follow. 中文提示:本文件英文为主,若理解存在困难可联系维护者。)
This project adopts the principles of the Contributor Covenant v2.1 (https://www.contributor-covenant.org/version/2/1/code_of_conduct/) with projectspecific clarifications below. By participating you agree to uphold this Code.
## Our Pledge
We strive to provide a harassmentfree, inclusive, friendly, and productive environment for everyone, regardless of age, body, disability, ethnicity, sex characteristics, gender identity or expression, level of experience, education, socioeconomic status, nationality, personal appearance, race, caste, religion (or lack thereof), sexual identity or orientation, or technical choices.
## Our Standards
Examples of behavior that contributes to a positive environment:
- Showing empathy and respect to all participants
- Giving and gracefully accepting constructive feedback
- Focusing on what is best for the project and community
- Being honest about mistakes and seeking improvement
- Using welcoming and inclusive language
Examples of unacceptable behavior include:
- Harassment, discrimination, or derogatory comments
- Trolling, insulting or antagonistic remarks, personal or political attacks
- Public or private harassment or sustained disruption of activities
- Publishing others private information without explicit permission
- Sexualized language, imagery, or unwelcome advances
- Any other conduct reasonably deemed inappropriate or unsafe
## Scope
This Code applies within all project spaces (repository code, issues, pull requests, discussions, wiki, CI logs) and in public spaces whenever an individual is representing the project or community.
## Responsibilities & Enforcement
Project maintainers ("maintainers") are responsible for clarifying standards and taking appropriate, fair, and consistent corrective action.
Maintainers may remove or edit contributions that violate this Code (comments, commits, code, wiki edits, issues, discussions) and may temporarily or permanently ban any contributor for abusive, harassing, or otherwise harmful behavior.
## Reporting
Report violations privately via:
- Email: carm@carm.cc
Please include (if possible):
- Links, timestamps, or message IDs
- Description of what happened and why it is a concern
- Screenshots or logs (if relevant)
- Preferred or suggested resolution
We aim to acknowledge reports within 72 hours and provide an initial assessment within 7 days. All goodfaith reports will be treated confidentially and only shared with individuals who need the information to resolve the issue.
## Enforcement Guidelines
Maintainers will use these guidelines to determine the impact of an incident and consequences:
1. Correction
- Impact: Use of inappropriate language or other unprofessional conduct.
- Consequence: Private or public warning, request for change.
2. Warning
- Impact: A single severe incident or repeated inappropriate behavior.
- Consequence: Official warning; continued misconduct leads to escalation.
3. Temporary Suspension
- Impact: Persistent violations despite previous warnings.
- Consequence: Temporary participation suspension (issues/PRs/discussions). Conditions for reinstatement communicated.
4. Permanent Ban
- Impact: Demonstrated pattern of harassment, hate, or threats; refusal to reform.
- Consequence: Permanent removal from community spaces.
## Conflicts of Interest
Maintainers will recuse themselves from enforcement decisions where they have a personal conflict. A neutral maintainer or external trusted community member may be asked to assist when appropriate.
## Appeals
If you believe an enforcement action was made in error or was unfair, you may appeal by emailing the same reporting address within 14 days, providing context and justification.
## Attribution
Portions adapted from Contributor Covenant v2.1 and other open source community best practices.
## Changes & Versioning
Substantive changes to this Code will be announced in the repository (Release Notes / CHANGELOG / Discussions). Historical versions will remain accessible via Git history.
---
If unsure whether something is acceptable: choose respect, transparency, and ask a maintainer before acting.
+210
View File
@@ -0,0 +1,210 @@
# Contributing Guide
> English is the primary language. A brief Chinese hint: 若需中文协助可在 Issue 中说明。
Thank you for investing time in contributing! This document describes how to propose changes and how we maintain quality and consistency across the project.
## Quick Links
- Code of Conduct: ./CODE_OF_CONDUCT.md
- Security Policy: ./SECURITY.md
- Issues: https://github.com/CarmJos/configured/issues
- Discussions / Q&A: (open an Issue if Discussions are disabled)
## Table of Contents
1. Principles
2. Scope of Contributions
3. Getting Started (Environment & Build)
4. Project Structure
5. Branching & Workflow
6. Issue Workflow
7. Pull Request Guidelines
8. Commit Message Convention
9. Coding Standards
10. Testing Guidelines
11. Documentation & JavaDoc
12. Dependency Policy
13. Versioning & Releases
14. Performance Expectations
15. Internationalization / Language
16. FAQ for Contributors
17. Attribution
---
## 1. Principles
We value: correctness, clarity, minimalism, maintainability, security-by-default, and performance without premature complexity. Every contribution should move at least one of these forward while not regressing the others.
## 2. Scope of Contributions
Acceptable contributions include (but are not limited to):
- Bug fixes & test coverage improvements
- Performance optimizations with measurable benefit
- New configuration providers (storage backends) with generic value
- Validation or serialization helpers
- Documentation, examples, or tutorials
- Tooling that improves developer productivity or release robustness
Out-of-scope (likely to be declined):
- Vendor lockin features narrowly targeting one proprietary platform (unless optional & isolated)
- Large feature branches without prior design discussion
- Unbounded abstraction that increases complexity with unclear user value
## 3. Getting Started (Environment & Build)
Requirements:
- JDK 8 (minimum). Later JDKs may work but target bytecode is 1.8.
- Maven 3.8+ (Wrapper optional; project assumes standard mvn).
Build all modules:
```bash
mvn -q clean verify
```
Skip tests (NOT recommended for PR validation):
```bash
mvn -q clean install -DskipTests
```
Run a single module:
```bash
mvn -q -pl core -am test
```
Generate JavaDoc (already bound in build):
```bash
mvn -q javadoc:javadoc
```
## 4. Project Structure (High-level)
- core/ : Fundamental abstractions (Configuration, Value types, factories)
- features/ : Optional, orthogonal enhancements (validators, section, text, etc.)
- providers/ : Concrete persistence / parsing backends (yaml, gson, hocon, sql, mongodb, temp)
- demo/ : Usage demonstrations & sample scenarios
Rules:
- Core must not depend on feature or provider modules.
- Features must not form cycles; prefer depending only on core.
- Providers should keep external dependencies minimal and shaded/isolated only if necessary.
## 5. Branching & Workflow
- main (or master): Stable; only fastforward / squash from reviewed PRs.
- feature/<short-name>: New feature work. Open draft PR early for feedback.
- fix/<issue-id>-<slug>: Bug fix referencing an Issue.
- chore/<topic>: Build, infra, docs improvements.
Never force push to main. Force pushes allowed only to your own feature branches.
## 6. Issue Workflow
1. Search existing issues first to avoid duplication.
2. Provide reproduction steps (minimal code or config) for bugs.
3. Label suggestions as enhancement; performance items as perf.
4. For larger features, open a design issue summarizing: Problem, Motivation, Proposed API, Alternatives.
## 7. Pull Request Guidelines
Checklist before opening a PR:
- Linked to at least one Issue (unless trivial doc fix)
- Passes `mvn verify`
- Adds or updates tests covering new behavior / bug
- Includes JavaDoc / README / CHANGELOG fragment if user-facing
- No unrelated refactors or formatting churn
- Minimal diff: avoid reordering imports unless enforced by style
Review expectations:
- Maintainers strive to respond within 5 business days.
- Use constructive, actionoriented comments.
- Resolve conversations or explain why not.
- Squash commits if they are noisy; retain meaningful logical grouping.
## 8. Commit Message Convention
Use Conventional Commits (https://www.conventionalcommits.org/) with optional scope:
```
<type>(<scope>): <short imperative summary>
<body>(optional)
<footer>(breaking changes, issue references)
```
Types used:
- feat: New feature (user visible)
- fix: Bug fix
- perf: Performance improvement
- refactor: Internal restructuring without behavior change
- docs: Documentation only
- test: Add or fix tests
- build: Build system or dependency changes
- ci: Continuous integration changes
- chore: Maintenance tasks
- style: Formatting (rare; avoid large styleonly changes)
Breaking changes: add `!` after type/scope or include `BREAKING CHANGE:` footer.
## 9. Coding Standards
- Java: Follow effective Java principles; prefer explicit types over inference for public APIs.
- Nullability: Use JetBrains annotations (`@NotNull`, `@Nullable`) where helpful.
- Immutability: Favor immutable value objects; avoid exposing mutable internal state.
- Exceptions: Use specific exception types; no swallowing silently. Validate inputs early.
- Logging: Keep core logging minimal; let consumers decide verbosity. Avoid println.
- APIs: Minimize surface; avoid exposing prematurely general interfaces.
- Annotations: Provide meaningful config path / comments metadata clearly.
### Style
- Indentation: 4 spaces.
- Line length guideline: ≤ 140 chars (soft limit).
- Avoid wildcard imports.
## 10. Testing Guidelines
- Use JUnit (current: JUnit 4). Prefer deterministic, isolated tests.
- Each bug fix must include a regression test failing before the fix.
- Avoid timesensitive sleeps; prefer deterministic constructs.
- Keep provider-specific integration tests under provider module.
- Use random data cautiously; if used, log seed for reproduction.
Command:
```bash
mvn -q test
```
## 11. Documentation & JavaDoc
- Public classes & methods: brief JavaDoc describing contract, thread-safety, nullability.
- Add code examples when clarifying complex usage.
- Update README or module README for new feature flags or environment variables.
- Keep demo module aligned with latest recommended usage.
## 12. Dependency Policy
- Keep transitive dependency footprint lean.
- No large frameworks for simple utilities.
- Justify each new dependency in PR description (purpose, size, maintenance risk).
- Prefer stable, well-adopted libraries with permissive licenses compatible with LGPL.
- Security-sensitive libs (parsers, DB drivers) should be periodically updated.
## 13. Versioning & Releases
- Follows Semantic Versioning (MAJOR.MINOR.PATCH).
- Public API additions => MINOR bump.
- Backwards-compatible bug fix => PATCH.
- Backwards-incompatible change => MAJOR (document rationale & migration).
- Release steps (maintainers):
1. Ensure main is green (CI all passing)
2. Update CHANGELOG (if present) or Release Notes draft
3. Bump versions via maven-release-plugin (ensure GPG & staging configured)
4. Tag + push; verify publication (Central / GitHub Packages)
5. Publish GitHub Release with highlights + migration notes
## 14. Performance Expectations
- Avoid unnecessary object churn in hot paths.
- Profile before large rewrites. Provide benchmark or allocation stats if claiming improvement.
- Defer I/O and heavy parsing until needed (lazy loading pattern).
## 15. Internationalization / Language
- Primary language: English for code, comments, issues, PRs.
- Chinese clarifications acceptable if accompanied by English.
## 16. FAQ for Contributors
Q: Can I add a new provider?
A: Yes—open a design Issue first summarizing data model, external dependencies, and test strategy.
Q: How do I mark experimental APIs?
A: Add JavaDoc: `@apiNote Experimental: subject to change without notice.` and avoid wide promotion.
Q: Why Java 8 target?
A: Maximizes compatibility across server & embedded environments.
## 17. Attribution
Portions inspired by widely adopted open-source guidelines (Kotlin, Spring, Apache projects) and Conventional Commits.
---
Thank you for helping build a robust configuration ecosystem!
+162 -17
View File
@@ -1,21 +1,166 @@
MIT License
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (c) 2022 Carm
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
+171 -123
View File
@@ -1,40 +1,139 @@
```text
____ _____ ____ __ _
/ __/__ ____ __ __ / ___/__ ___ / _(_)__ ___ _________ _/ /_(_)__ ___
/ _// _ `(_-</ // / / /__/ _ \/ _ \/ _/ / _ `/ // / __/ _ `/ __/ / _ \/ _ \
/___/\_,_/___/\_, / \___/\___/_//_/_//_/\_, /\_,_/_/ \_,_/\__/_/\___/_//_/
/___/ /___/
<div align=center>
<img src=".doc/images/banner.png" alt="Banner"/>
[![version](https://img.shields.io/github/v/release/CarmJos/configured)](https://github.com/CarmJos/configured/releases)
[![License](https://img.shields.io/github/license/CarmJos/configured)](https://www.gnu.org/licenses/lgpl-3.0.html)
[![workflow](https://github.com/CarmJos/configured/actions/workflows/maven.yml/badge.svg?branch=master)](https://github.com/CarmJos/configured/actions/workflows/maven.yml)
[![CodeFactor](https://www.codefactor.io/repository/github/carmjos/configured/badge)](https://www.codefactor.io/repository/github/carmjos/configured)
![CodeSize](https://img.shields.io/github/languages/code-size/CarmJos/configured)
README LANGUAGES [ [**English**](README.md) | [中文](README_CN.md) ]
</div>
# configured _(config framework)_
<img src=".doc/images/logo-bg.svg" width="150px" alt="logo" align="right" style="float: right"/>
_**"Once set, Simple get."**_
A simple, easy-to-use and universal solution for managing, loading, reading,
and updating configuration files.
Supported **JSON**, **YAML**, **Hocon**, **TOML**, **SQL**, **MongoDB**... and much more!
## Features & Advantages
Supported [YAML](providers/yaml), [JSON](providers/json), [HOCON](providers/hocon) and [SQL](providers/sql)
based configuration files format.
- Class-based mechanism for initializing, loading, retrieving, and updating configuration files, ensuring convenience
and efficiency.
- Supports manual serialization and deserialization of complex configurations.
- Offers multiple builder forms for rapid construction of `ConfigValue<?>` objects.
- Enables specification of configuration paths, comments, and more via annotations.
## Development
For the latest JavaDoc release, [CLICK HERE](https://CarmJos.github.io/configured).
For a detailed development guide, see [wiki](https://github.com/CarmJos/configured/wiki).
### Preview
To quickly demonstrate the applicability of the project, here are a few practical demonstrations:
- [Database configuration.](demo/src/main/java/cc/carm/lib/configuration/demo/DatabaseConfiguration.java)
- [Demonstration of configurations instance classes.](demo/src/main/java/cc/carm/lib/configuration/demo/tests/conf/DemoConfiguration.java)
Check out all code demonstrations [HERE](demo/src/main/java/cc/carm/lib/configuration/demo/DatabaseConfiguration.java).
For more examples, see the [Development Guide](.doc/README.md).
```java
@ConfigPath(root = true)
@HeaderComments("Configurations for sample")
public interface SampleConfig extends Configuration {
@InlineComment("Enabled?") // Inline comment
ConfiguredValue<Boolean> ENABLED = ConfiguredValue.of(true);
@HeaderComments("Server configurations") // Header comment
ConfiguredValue<Integer> PORT = ConfiguredValue.of(Integer.class);
@HeaderComments({"[ UUID >-----------------------------------", "A lot of UUIDs"})
@FooterComments("[ UUID >-----------------------------------")
ConfiguredList<UUID> UUIDS = ConfiguredList.builderOf(UUID.class).fromString()
.parse(UUID::fromString).serialize(UUID::toString)
.defaults(
UUID.fromString("00000000-0000-0000-0000-000000000000"),
UUID.fromString("00000000-0000-0000-0000-000000000001")
).build();
@ConfigPath("info") // Custom path
interface INFO extends Configuration {
@HeaderComments("Configure your name!") // Header comment
ConfiguredValue<String> NAME = ConfiguredValue.of("Joker");
@ConfigPath("how-old-are-you") // Custom path
ConfiguredValue<Integer> AGE = ConfiguredValue.of(24);
}
}
```
# EasyConfiguration
```java
public class Sample {
public static void main(String[] args) {
// 1. Make a configuration provider from a file.
ConfigurationHolder<?> holder = YAMLConfigFactory.from("target/config.yml")
.resourcePath("configs/sample.yml")
.indent(4) // Optional: Set the indentation of the configuration file.
.build();
[![version](https://img.shields.io/github/v/release/CarmJos/EasyConfiguration)](https://github.com/CarmJos/EasyConfiguration/releases)
[![License](https://img.shields.io/github/license/CarmJos/EasyConfiguration)](https://opensource.org/licenses/MIT)
[![workflow](https://github.com/CarmJos/EasyConfiguration/actions/workflows/maven.yml/badge.svg?branch=master)](https://github.com/CarmJos/EasyConfiguration/actions/workflows/maven.yml)
[![CodeFactor](https://www.codefactor.io/repository/github/carmjos/easyconfiguration/badge)](https://www.codefactor.io/repository/github/carmjos/easyconfiguration)
![CodeSize](https://img.shields.io/github/languages/code-size/CarmJos/EasyConfiguration)
![](https://visitor-badge.glitch.me/badge?page_id=EasyConfiguration.readme)
// 2. Initialize the configuration classes or instances.
holder.initialize(SampleConfig.class);
// 3. Enjoy using the configuration!
System.out.println("Enabled? -> " + SampleConfig.ENABLED.resolve()); // true
SampleConfig.ENABLED.set(false);
System.out.println("And now? -> " + SampleConfig.ENABLED.resolve()); // false
// p.s. Changes not save so enable value will still be true in the next run.
轻松(做)配置,简单便捷的通用配置文件加载、读取与更新工具,可自定义配置格式。
System.out.println("Your name is " + SampleConfig.INFO.NAME.resolve() + " (age=" + SampleConfig.INFO.AGE.resolve() + ")!");
}
}
## 优势
```
- 基于类的配置文件初始化、加载、获取与更新机制,方便快捷。
```yaml
# Configurations for sample
## 开发
enabled: true #Enabled?
详细开发介绍请 [点击这里](.documentation/README.md) , JavaDoc(最新Release) 请 [点击这里](https://carmjos.github.io/EasyConfiguration) 。
# Server configurations
port:
### 示例代码
# [ UUID >-----------------------------------
# A lot of UUIDs
uuids:
- 00000000-0000-0000-0000-000000000000
- 00000000-0000-0000-0000-000000000001
# [ UUID >-----------------------------------
您可以 [点击这里](impl/yaml/src/test/java/config/source/TestConfiguration.java) 查看部分代码演示,更多演示详见 [开发介绍](.documentation/README.md) 。
info:
# Configure your name!
name: Joker
how-old-are-you: 24
```
### 依赖方式
### Dependencies
#### Maven 依赖
#### Maven Dependency
<details>
<summary>远程库配置</summary>
<summary>Remote Repository Configuration</summary>
```xml
@@ -42,24 +141,17 @@
<repositories>
<repository>
<!--采用Maven中心库,安全稳定,但版本更新需要等待同步-->
<!-- Using Maven Central Repository for secure and stable updates, though synchronization might be needed. -->
<id>maven</id>
<name>Maven Central</name>
<url>https://repo1.maven.org/maven2</url>
</repository>
<repository>
<!--采用github依赖库,实时更新,但需要配置 (推荐) -->
<id>EasyConfiguration</id>
<name>GitHub Packages</name>
<url>https://maven.pkg.github.com/CarmJos/EasyConfiguration</url>
</repository>
<repository>
<!--采用我的私人依赖库,简单方便,但可能因为变故而无法使用-->
<id>carm-repo</id>
<name>Carm's Repo</name>
<url>https://repo.carm.cc/repository/maven-public/</url>
<!-- Using GitHub dependencies for real-time updates, configuration required (recommended). -->
<id>configured</id>
<name>GitHub Packages</name>
<url>https://maven.pkg.github.com/CarmJos/configured</url>
</repository>
</repositories>
@@ -69,24 +161,32 @@
</details>
<details>
<summary>通用原生依赖</summary>
<summary>Generic Native Dependency</summary>
```xml
<project>
<dependencies>
<!--基础实现部分,需要自行实现“Provider”“Wrapper”-->
<!-- Basic implementation part, requiring custom implementation of “Provider” and “Wrapper”. -->
<dependency>
<groupId>cc.carm.lib</groupId>
<artifactId>easyconfiguration-core</artifactId>
<artifactId>configured-core</artifactId>
<version>[LATEST RELEASE]</version>
<scope>compile</scope>
</dependency>
<!--基于YAML文件的实现版本,可用于全部Java环境。-->
<!-- YAML file-based implementation, compatible with all Java environments. -->
<dependency>
<groupId>cc.carm.lib</groupId>
<artifactId>easyconfiguration-yaml</artifactId>
<artifactId>configured-yaml</artifactId>
<version>[LATEST RELEASE]</version>
<scope>compile</scope>
</dependency>
<!-- JSON file-based implementation, compatible with all Java environments. -->
<dependency>
<groupId>cc.carm.lib</groupId>
<artifactId>configured-gson</artifactId>
<version>[LATEST RELEASE]</version>
<scope>compile</scope>
</dependency>
@@ -97,125 +197,73 @@
</details>
**基于Spigot实现的版本**
```xml
<project>
<dependencies>
<dependency>
<groupId>cc.carm.lib</groupId>
<artifactId>easyconfiguration-spigot</artifactId>
<version>[LATEST RELEASE]</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
```
**基于Bungee实现的版本 (不支持自动注释)**
```xml
<project>
<dependencies>
<dependency>
<groupId>cc.carm.lib</groupId>
<artifactId>easyconfiguration-bungee</artifactId>
<version>[LATEST RELEASE]</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
```
</details>
#### Gradle 依赖
#### Gradle Dependency
<details>
<summary>远程库配置</summary>
<summary>Remote Repository Configuration</summary>
```groovy
repositories {
// 采用Maven中心库,安全稳定,但版本更新需要等待同步
// Using Maven Central Repository for secure and stable updates, though synchronization might be needed.
mavenCentral()
// 采用github依赖库,实时更新,但需要配置 (推荐)
maven { url 'https://maven.pkg.github.com/CarmJos/EasyConfiguration' }
// 采用我的私人依赖库,简单方便,但可能因为变故而无法使用
maven { url 'https://repo.carm.cc/repository/maven-public/' }
// Using GitHub dependencies for real-time updates, configuration required (recommended).
maven { url 'https://maven.pkg.github.com/CarmJos/configured' }
}
```
</details>
<details>
<summary>通用原生依赖</summary>
<summary>Generic Native Dependency</summary>
```groovy
dependencies {
//基础实现部分,需要自行实现“Provider”“Wrapper”
api "cc.carm.lib:easyconfiguration-core:[LATEST RELEASE]"
// Basic implementation part, requiring custom implementation of “Provider” and “Wrapper”.
api "cc.carm.lib:configured-core:[LATEST RELEASE]"
//基于YAML文件的实现版本,可用于全部Java环境。
api "cc.carm.lib:easyconfiguration-yaml:[LATEST RELEASE]"
// YAML file-based implementation, compatible with all Java environments.
api "cc.carm.lib:configured-yaml:[LATEST RELEASE]"
// JSON file-based implementation, compatible with all Java environments.
api "cc.carm.lib:configured-gson:[LATEST RELEASE]"
}
```
</details>
<details>
<summary>平台依赖版本</summary>
## Derived Projects
```groovy
### [**MineConfiguration**](https://github.com/CarmJos/MineConfiguration) (by @CarmJos)
dependencies {
configured for MineCraft!
Easily manage configurations on MineCraft-related server platforms.
// 用于Spigot服务端的版本
api "cc.carm.lib:easyconfiguration-spigot:[LATEST RELEASE]"
Currently, it supports BungeeCord, Velocity, Bukkit (Spigot) servers,
with more platforms to be supported soon.
// 用于BungeeCord服务端的版本,不支持注解。
// 如需注解,可选择使用 `easyconfiguration-yaml` 并打包。
api "cc.carm.lib:easyconfiguration-bungee:[LATEST RELEASE]"
## Support and Donation
}
```
If you appreciate this plugin, consider supporting me with a [donation](https://github.com/sponsors/CarmJos)!
</details>
Thank you for supporting open-source projects!
## 支持与捐赠
Many thanks to Jetbrains for kindly providing a license for us to work on this and other open-source projects.
若您觉得本插件做的不错,您可以通过捐赠支持我!
[![](https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.svg)](https://www.jetbrains.com/?from=https://github.com/CarmJos/configured)
感谢您对开源项目的支持!
Many thanks to [ArtformGames](https://github.com/ArtformGames) for their
strong support and active contribution to this project!
<img height=25% width=25% src="https://raw.githubusercontent.com/CarmJos/CarmJos/main/img/donate-code.jpg" alt=""/>
<img src="https://raw.githubusercontent.com/ArtformGames/.github/master/logo/logo_full.svg" width="317px" height="117px" alt="ArtformGames">
## 开源协议
## Open Source License
本项目源码采用 [The MIT License](https://opensource.org/licenses/MIT) 开源协议。
This project's source code is licensed under
the [GNU LESSER GENERAL PUBLIC LICENSE](https://www.gnu.org/licenses/lgpl-3.0.html).
<details>
<summary>关于 MIT 协议</summary>
> MIT 协议可能是几大开源协议中最宽松的一个,核心条款是:
>
> 该软件及其相关文档对所有人免费,可以任意处置,包括使用,复制,修改,合并,发表,分发,再授权,或者销售。唯一的限制是,软件中必须包含上述版 权和许可提示。
>
> 这意味着:
>
> - 你可以自由使用,复制,修改,可以用于自己的项目。
> - 可以免费分发或用来盈利。
> - 唯一的限制是必须包含许可声明。
>
> MIT 协议是所有开源许可中最宽松的一个,除了必须包含许可声明外,再无任何限制。
>
> *以上文字来自 [五种开源协议GPL,LGPL,BSD,MIT,Apache](https://www.oschina.net/question/54100_9455) 。*
</details>
+285
View File
@@ -0,0 +1,285 @@
<div align=center>
<img src=".doc/images/banner.png" alt="Banner"/>
[![version](https://img.shields.io/github/v/release/CarmJos/configured)](https://github.com/CarmJos/configured/releases)
[![License](https://img.shields.io/github/license/CarmJos/configured)](https://www.gnu.org/licenses/lgpl-3.0.html)
[![workflow](https://github.com/CarmJos/configured/actions/workflows/maven.yml/badge.svg?branch=master)](https://github.com/CarmJos/configured/actions/workflows/maven.yml)
[![CodeFactor](https://www.codefactor.io/repository/github/carmjos/configured/badge)](https://www.codefactor.io/repository/github/carmjos/configured)
![CodeSize](https://img.shields.io/github/languages/code-size/CarmJos/configured)
README LANGUAGES [ [English](README.md) | [**中文**](README_CN.md) ]
</div>
# configured _(配置文件框架)_
<img src=".doc/images/logo-bg.svg" width="150px" alt="logo" align="right" style="float: right"/>
**一次配置,轻松读取!**
一款简单便捷的通用配置文件加载、读取与更新工具,可自定义配置的格式。
## 特性 & 优势
支持 [YAML](providers/yaml), [JSON](providers/gson), [HOCON](providers/hocon) 和 [SQL](providers/sql) 等多种配置文件格式。
- 基于类的配置文件初始化、加载、获取与更新机制,方便快捷。
- 支持复杂配置的手动序列化、反序列化。
- 提供多种builder形式,快速构建 `ConfigValue<?>` 对象。
- 支持通过注解规定配置对应的路径、注释等信息。
## 开发
详细开发介绍请 [点击这里](.doc/README.md) , JavaDoc(最新Release)
请 [点击这里](https://CarmJos.github.io/configured) 。
### 示例代码
为快速的展示该项目的适用性,这里有几个实际演示:
- [数据库配置文件实例](demo/src/main/java/cc/carm/lib/configuration/demo/DatabaseConfiguration.java)
- [全种类配置实例类演示](demo/src/main/java/cc/carm/lib/configuration/demo/tests/conf/DemoConfiguration.java)
您可以 [点击这里](demo/src/main/java/cc/carm/lib/configuration/demo)
直接查看现有的代码演示,更多复杂情况演示详见 [开发介绍](https://github.com/CarmJos/configured/wiki) 。
```java
@ConfigPath(root = true)
@HeaderComments("Configurations for sample")
public interface SampleConfig extends Configuration {
@InlineComment("Enabled?") // 行后注释
ConfiguredValue<Boolean> ENABLED = ConfiguredValue.of(true);
@HeaderComments("Server configurations") // 头部注释
ConfiguredValue<Integer> PORT = ConfiguredValue.of(Integer.class);
@HeaderComments({"[ UUID >-----------------------------------", "A lot of UUIDs"})
@FooterComments("[ UUID >-----------------------------------")
ConfiguredList<UUID> UUIDS = ConfiguredList.builderOf(UUID.class).fromString()
.parse(UUID::fromString).serialize(UUID::toString)
.defaults(
UUID.fromString("00000000-0000-0000-0000-000000000000"),
UUID.fromString("00000000-0000-0000-0000-000000000001")
).build();
interface INFO extends Configuration {
@HeaderComments("Configure your name!") // Header comment
ConfiguredValue<String> NAME = ConfiguredValue.of("Joker");
@ConfigPath("how-old-are-you") // 自定义路径
ConfiguredValue<Integer> AGE = ConfiguredValue.of(24);
}
}
```
```java
public class Sample {
public static void main(String[] args) {
// 1. 生成一个 “holder” 用于给配置类提供源配置的文件。
ConfigurationHolder<?> holder = YAMLConfigFactory.from("target/config.yml")
.resourcePath("configs/sample.yml")
.indent(4) // Optional: Set the indentation of the configuration file.
.build();
// 2. 通过 “holder” 初始化配置类或配置实例。
holder.initialize(SampleConfig.class);
// 3. 现在可以享受快捷方便的配置文件使用方式了~
System.out.println("Enabled? -> " + SampleConfig.ENABLED.resolve());
SampleConfig.ENABLED.set(false);
System.out.println("And now? -> " + SampleConfig.ENABLED.resolve());
// p.s. 在本示例里的更改未保存,因此启用值在下次运行中仍将为 true。
}
}
```
```yaml
# Configurations for sample
enabled: true #Enabled?
# Server configurations
port:
# [ UUID >-----------------------------------
# A lot of UUIDs
uuids:
- 00000000-0000-0000-0000-000000000000
- 00000000-0000-0000-0000-000000000001
# [ UUID >-----------------------------------
info:
# Configure your name!
name: Joker
how-old-are-you: 24
```
### 依赖方式
#### Maven 依赖
<details>
<summary>远程库配置</summary>
```xml
<project>
<repositories>
<repository>
<!--采用Maven中心库,安全稳定,但版本更新需要等待同步-->
<id>maven</id>
<name>Maven Central</name>
<url>https://repo1.maven.org/maven2</url>
</repository>
<repository>
<!--采用github依赖库,实时更新,但需要配置 (推荐) -->
<id>configured</id>
<name>GitHub Packages</name>
<url>https://maven.pkg.github.com/CarmJos/configured</url>
</repository>
<repository>
<!--采用我的私人依赖库,简单方便,但可能因为变故而无法使用-->
<id>carm-repo</id>
<name>Carm's Repo</name>
<url>https://repo.carm.cc/repository/maven-public/</url>
</repository>
</repositories>
</project>
```
</details>
<details>
<summary>通用原生依赖</summary>
```xml
<project>
<dependencies>
<!--基础实现部分,需要自行实现“Provider”与“Wrapper”。-->
<dependency>
<groupId>cc.carm.lib</groupId>
<artifactId>configured-core</artifactId>
<version>[LATEST RELEASE]</version>
<scope>compile</scope>
</dependency>
<!--基于YAML文件的实现版本,可用于全部Java环境。-->
<dependency>
<groupId>cc.carm.lib</groupId>
<artifactId>configured-yaml</artifactId>
<version>[LATEST RELEASE]</version>
<scope>compile</scope>
</dependency>
<!--基于JSON文件的实现版本,可用于全部Java环境。-->
<!--需要注意的是,JSON不支持文件注释。-->
<dependency>
<groupId>cc.carm.lib</groupId>
<artifactId>configured-gson</artifactId>
<version>[LATEST RELEASE]</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cc.carm.lib</groupId>
<artifactId>configured-hocon</artifactId>
<version>[LATEST RELEASE]</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cc.carm.lib</groupId>
<artifactId>configured-sql</artifactId>
<version>[LATEST RELEASE]</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
```
</details>
#### Gradle 依赖
<details>
<summary>远程库配置</summary>
```groovy
repositories {
// 采用Maven中心库,安全稳定,但版本更新需要等待同步
mavenCentral()
// 采用github依赖库,实时更新,但需要配置 (推荐)
maven { url 'https://maven.pkg.github.com/CarmJos/configured' }
// 采用我的私人依赖库,简单方便,但可能因为变故而无法使用
maven { url 'https://repo.carm.cc/repository/maven-public/' }
}
```
</details>
<details>
<summary>通用原生依赖</summary>
```groovy
dependencies {
//基础实现部分,需要自行实现“Provider”与“Wrapper”。
api "cc.carm.lib:configured-core:[LATEST RELEASE]"
//基于YAML文件的实现版本,可用于全部Java环境。
api "cc.carm.lib:configured-yaml:[LATEST RELEASE]"
//基于JSON文件的实现版本,可用于全部Java环境。
//需要注意的是,JSON不支持文件注释。
api "cc.carm.lib:configured-gson:[LATEST RELEASE]"
api "cc.carm.lib:configured-hocon:[LATEST RELEASE]"
api "cc.carm.lib:configured-sql:[LATEST RELEASE]"
}
```
</details>
## 衍生项目
### [**MineConfiguration**](https://github.com/CarmJos/MineConfiguration) (by @CarmJos )
configured for MineCraft!
开始在 MineCraft 相关服务器平台上轻松(做)配置吧!
目前支持 BungeeCord, Bukkit(Spigot) 服务端,后续将支持更多平台。
## 支持与捐赠
若您觉得本插件做的不错,您可以通过[捐赠](https://github.com/sponsors/CarmJos)支持我!
感谢您对开源项目的支持!
万分感谢 Jetbrains 为我们提供了从事此项目和其他开源项目的许可!
[![](https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.svg)](https://www.jetbrains.com/?from=https://github.com/CarmJos/configured)
万分感谢来自 [ArtformGames](https://github.com/ArtformGames) 对本项目的大力支持与积极贡献!
<img src="https://raw.githubusercontent.com/ArtformGames/.github/master/logo/logo_full.svg" width="317px" height="117px" alt="ArtformGames">
## 开源协议
本项目源码采用 [GNU LESSER GENERAL PUBLIC LICENSE](https://www.gnu.org/licenses/lgpl-3.0.html) 开源协议。
+102
View File
@@ -0,0 +1,102 @@
# Security Policy
English is the authoritative language of this document.
## Supported Versions
We generally provide security fixes only for the latest released MINOR version (most recent tag on the default branch). Older versions may receive fixes only if the vulnerability is critical and a patch is low risk.
| Version | Status |
|----------|-------------------------|
| Latest | Security fixes |
| < Latest | Not routinely supported |
If you rely on an older version you are strongly encouraged to upgrade promptly after each release.
## Reporting a Vulnerability
Please DO NOT open a public Issue for suspected security problems.
Instead, email: carm@carm.cc with:
- A clear description of the issue and potential impact
- Steps to reproduce (minimal code / configuration)
- Affected version(s) and environment (JDK, OS)
- Any known workarounds
- Preferred public credit name (optional)
You will receive an acknowledgement within 72 hours (workdays) confirming receipt.
## Assessment & Disclosure Process
1. Triage & validation (attempt reproduction, scope impact)
2. Determine severity (CVSS or qualitative: Low / Moderate / High / Critical)
3. Prepare a private fix / patch + regression tests
4. Coordinate an embargoed release window (typically ≤14 days after validation for High/Critical)
5. Release a new version (and possibly backport if warranted)
6. Publish security advisory (GitHub Security Advisory + Release Notes) including mitigation steps
We may reject reports that are clearly nonsecurity bugs (e.g., feature requests, performance tuning) or issues requiring unreasonable preconditions (e.g., attacker already has full local code execution).
## Non-Qualifying Issues (Examples)
- Missing rate limits on non-authenticated, non-state-changing operations
- Denial-of-service requiring unrealistic resource constraints or already solved via JVM flags
- Vulnerabilities only exploitable on unsupported / EOL Java versions
- Social engineering, SPF/DMARC issues beyond this codebases control
## Coordinated Disclosure
If you plan to blog or speak publicly about the vulnerability prior to patch availability, please coordinate timing so users can upgrade safely.
## Dependency Security
We periodically review dependency versions for CVEs. You can help by:
- Submitting PRs that upgrade vulnerable libraries with changelog & compatibility notes
- Avoiding unnecessary new dependencies
## Cryptographic Material
This project does not bundle custom cryptographic primitives. If you discover misuse of crypto APIs or insecure random number use in security-sensitive areas, treat it as a security report.
## Reporting Format Template (Recommended)
```
Subject: [Security Report] <short title>
Affected Component: (module / class)
Version(s) Tested: x.y.z (and earlier if known)
Environment: JDK x, OS
Summary:
Describe the vulnerability and impact.
Reproduction Steps:
1. ...
2. ...
3. ...
Expected vs Actual:
Potential Impact:
Workarounds / Mitigations (if any):
Credit: (name / handle / anonymous)
```
## Credit & Acknowledgement
We will list (with permission) reporters who submit valid, first responsibly disclosed security issues in the release notes / advisory.
## GPG / Integrity
Release artifacts are signed (see project docs). Always verify signatures and checksums when consuming artifacts from Maven Central or GitHub Packages.
## Questions
For general (non-sensitive) questions, open an Issue labeled `question` rather than using the security email.
Thank you for helping keep the ecosystem safe.
+15 -6
View File
@@ -3,19 +3,28 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>easyconfiguration-parent</artifactId>
<artifactId>configured-parent</artifactId>
<groupId>cc.carm.lib</groupId>
<version>1.0.6</version>
<version>4.2.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<properties>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<maven.compiler.source>${project.jdk.version}</maven.compiler.source>
<maven.compiler.target>${project.jdk.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
</properties>
<artifactId>easyconfiguration-core</artifactId>
<artifactId>configured-core</artifactId>
<packaging>jar</packaging>
<name>Configured - Core</name>
<url>https://github.com/CarmJos/configured</url>
<description>
The core module of Configured framework,
providing essential configuration management functionality.
</description>
<build>
<plugins>
<plugin>
@@ -37,4 +46,4 @@
</plugins>
</build>
</project>
</project>
@@ -0,0 +1,8 @@
package cc.carm.lib.configuration;
/**
* The root interface of the configuration file interfaces,
* which is used to label a class as a configuration.
*/
public interface Configuration {
}
@@ -0,0 +1,88 @@
package cc.carm.lib.configuration.adapter;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
/**
* Value adapter, used to convert the value of the configuration file into the objects.
*
* @param <TYPE> The type of the target value
*/
public class ValueAdapter<TYPE>
implements ValueSerializer<TYPE>, ValueParser<TYPE> {
protected final @NotNull ValueType<TYPE> type;
protected @Nullable ValueSerializer<TYPE> serializer;
protected @Nullable ValueParser<TYPE> deserializer;
public ValueAdapter(@NotNull ValueType<TYPE> type) {
this(type, null, null);
}
public ValueAdapter(@NotNull ValueType<TYPE> type,
@Nullable ValueSerializer<TYPE> serializer,
@Nullable ValueParser<TYPE> parser) {
this.type = type;
this.serializer = serializer;
this.deserializer = parser;
}
public @NotNull ValueType<TYPE> type() {
return type;
}
public @Nullable ValueSerializer<TYPE> serializer() {
return serializer;
}
public @Nullable ValueParser<TYPE> parser() {
return deserializer;
}
public ValueAdapter<TYPE> serializer(@Nullable ValueSerializer<TYPE> serializer) {
this.serializer = serializer;
return this;
}
public ValueAdapter<TYPE> parser(@Nullable ValueParser<TYPE> deserializer) {
this.deserializer = deserializer;
return this;
}
@Override
public @Nullable Object serialize(
@NotNull ConfigurationHolder<?> holder,
@NotNull ValueType<? super TYPE> type,
@NotNull TYPE value
) throws Exception {
if (serializer == null) throw new UnsupportedOperationException("Serializer is not supported");
return serializer.serialize(holder, type, value);
}
@Override
public @Nullable TYPE parse(
@NotNull ConfigurationHolder<?> holder,
@NotNull ValueType<? super TYPE> type,
@NotNull Object value
) throws Exception {
if (deserializer == null) throw new UnsupportedOperationException("Deserializer is not supported");
return deserializer.parse(holder, type, value);
}
@Override
public boolean equals(Object o) {
if (!(o instanceof ValueAdapter)) return false;
ValueAdapter<?> that = (ValueAdapter<?>) o;
return Objects.equals(type, that.type);
}
@Override
public int hashCode() {
return Objects.hashCode(type);
}
}
@@ -0,0 +1,308 @@
package cc.carm.lib.configuration.adapter;
import cc.carm.lib.configuration.function.DataFunction;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import cc.carm.lib.configuration.source.section.ConfigureSection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Array;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
public class ValueAdapterRegistry {
protected final Set<ValueAdapter<?>> adapters = new HashSet<>();
protected final Map<ValueType<?>, ValueAdapter<?>> adapterCache = new HashMap<>();
public <FROM, TO> void register(@NotNull Class<FROM> from, @NotNull Class<TO> to,
@Nullable DataFunction<FROM, TO> parser,
@Nullable DataFunction<TO, FROM> serializer) {
register(ValueType.of(from), ValueType.of(to), parser, serializer);
}
public <FROM, TO> void register(@NotNull ValueType<FROM> from, @NotNull ValueType<TO> to,
@Nullable DataFunction<FROM, TO> parser,
@Nullable DataFunction<TO, FROM> serializer) {
ValueAdapter<FROM> fromAdapter = adapterOf(from);
if (fromAdapter == null) throw new IllegalArgumentException("No adapter for type " + from);
register(to,
serializer == null ? null : (provider, type, value) -> fromAdapter.serialize(provider, from, serializer.handle(value)),
parser == null ? null : (provider, type, data) -> parser.handle(fromAdapter.parse(provider, from, data))
);
}
public void register(@NotNull ValueAdapter<?>... adapter) {
adapters.addAll(Arrays.asList(adapter));
adapterCache.clear();
}
public <T> void register(@NotNull Class<T> type, @NotNull ValueSerializer<T> serializer) {
register(ValueType.of(type), serializer);
}
public <T> void register(@NotNull ValueType<T> type, @NotNull ValueSerializer<T> serializer) {
ValueAdapter<T> existing = adapterOf(type);
if (existing != null) {
existing.serializer(serializer);
} else {
register(new ValueAdapter<>(type, serializer, null));
}
}
public <T> void register(@NotNull Class<T> type, @NotNull ValueParser<T> deserializer) {
register(ValueType.of(type), deserializer);
}
public <T> void register(@NotNull ValueType<T> type, @NotNull ValueParser<T> deserializer) {
ValueAdapter<T> existing = adapterOf(type);
if (existing != null) {
existing.parser(deserializer);
} else {
register(new ValueAdapter<>(type, null, deserializer));
}
}
public <T> void register(@NotNull ValueType<T> type,
@Nullable ValueSerializer<T> serializer,
@Nullable ValueParser<T> deserializer) {
if (serializer == null && deserializer == null) return;
ValueAdapter<T> existing = adapterOf(type);
if (existing != null) {
if (serializer != null) existing.serializer(serializer);
if (deserializer != null) existing.parser(deserializer);
} else {
register(new ValueAdapter<>(type, serializer, deserializer));
}
}
public void unregister(@NotNull Class<?> type) {
unregister(ValueType.of(type));
}
public void unregister(@NotNull ValueType<?> type) {
adapters.removeIf(adapter -> adapter.type().equals(type));
adapterCache.clear();
}
@SuppressWarnings("unchecked")
public <T> @Nullable ValueAdapter<T> adapterOf(@NotNull ValueType<T> type) {
if (adapterCache.containsKey(type)) {
return (ValueAdapter<T>) adapterCache.get(type);
}
for (ValueAdapter<?> adapter : adapters) {
if (adapter.type().equals(type)) {
adapterCache.put(type, adapter);
return (ValueAdapter<T>) adapter;
}
}
for (ValueAdapter<?> adapter : adapters) {
if (adapter.type().isSubtypeOf(type)) {
adapterCache.put(type, adapter);
return (ValueAdapter<T>) adapter;
}
}
adapterCache.put(type, null);
return null;
}
public <T> ValueAdapter<T> adapterOf(@NotNull T value) {
return adapterOf(ValueType.of(value));
}
public <T> ValueAdapter<T> adapterOf(@NotNull Class<T> type) {
return adapterOf(ValueType.of(type));
}
public <T> T deserialize(@NotNull ConfigurationHolder<?> holder, @NotNull Class<T> type, @Nullable Object source) throws Exception {
return deserialize(holder, ValueType.of(type), source);
}
public <T> T deserialize(@NotNull ConfigurationHolder<?> holder, @NotNull ValueType<T> type, @Nullable Object source) throws Exception {
if (source == null) return null;
Type typeInstance = type.getType();
if (!(typeInstance instanceof ParameterizedType) && type.isInstance(source)) {
return type.cast(source);
}
ValueAdapter<T> adapter = adapterOf(type);
if (adapter != null) {
return adapter.parse(holder, type, source);
}
return deserializeWithoutAdapter(holder, type, source, typeInstance);
}
private <T> T deserializeWithoutAdapter(@NotNull ConfigurationHolder<?> holder, @NotNull ValueType<T> type,
@NotNull Object source, @NotNull Type typeInstance) throws Exception {
Class<?> rawType = type.getRawType();
if (rawType.isArray()) {
return deserializeArray(holder, type, source, rawType);
}
if (typeInstance instanceof ParameterizedType) {
return deserializeParameterized(holder, type, source, (ParameterizedType) typeInstance);
}
throw new RuntimeException("No adapter for type " + type);
}
private <T> T deserializeArray(@NotNull ConfigurationHolder<?> holder, @NotNull ValueType<T> type,
@NotNull Object source, @NotNull Class<?> rawType) throws Exception {
List<?> list;
if (source instanceof List<?>) {
list = (List<?>) source;
} else {
// For non-list sources, treat as single element array
list = Collections.singletonList(source);
}
int size = list.size();
if (size == 0) {
return type.cast(Array.newInstance(rawType.getComponentType(), 0));
}
Class<?> componentType = rawType.getComponentType();
Object[] array = (Object[]) Array.newInstance(componentType, size);
for (int i = 0; i < size; i++) {
array[i] = deserialize(holder, componentType, list.get(i));
}
return type.cast(array);
}
@SuppressWarnings("unchecked")
private <T> T deserializeParameterized(@NotNull ConfigurationHolder<?> holder, @NotNull ValueType<T> type,
@NotNull Object source, @NotNull ParameterizedType pt) throws Exception {
Type rawType = pt.getRawType();
Type[] typeArgs = pt.getActualTypeArguments();
if (rawType == List.class || rawType == Collection.class || rawType == ArrayList.class) {
return (T) deserializeCollection(holder, source, typeArgs[0], ArrayList::new);
}
if (rawType == Set.class || rawType == HashSet.class) {
return (T) deserializeCollection(holder, source, typeArgs[0], HashSet::new);
}
if (rawType == Map.class || rawType == LinkedHashMap.class) {
return (T) deserializeMap(holder, source, typeArgs[0], typeArgs[1]);
}
throw new RuntimeException("No adapter for parameterized type " + type);
}
private Collection<?> deserializeCollection(@NotNull ConfigurationHolder<?> holder, @NotNull Object source,
@NotNull Type elementType, @NotNull java.util.function.Supplier<Collection<Object>> collectionFactory) throws Exception {
ValueType<?> elementValueType = ValueType.of(elementType);
List<?> sourceList = deserializeList(holder, elementValueType, source);
if (sourceList.isEmpty()) {
return collectionFactory.get();
}
Collection<Object> result = collectionFactory.get();
if (result instanceof ArrayList) {
((ArrayList<Object>) result).ensureCapacity(sourceList.size());
}
for (Object item : sourceList) {
Object deserializedItem = deserialize(holder, elementValueType, item);
if (deserializedItem != null) {
result.add(deserializedItem);
}
}
return result;
}
private Map<Object, Object> deserializeMap(@NotNull ConfigurationHolder<?> holder, @NotNull Object source,
@NotNull Type keyType, @NotNull Type valueType) throws Exception {
Map<?, ?> sourceMap;
if (source instanceof Map<?, ?>) {
sourceMap = (Map<?, ?>) source;
} else if (source instanceof ConfigureSection) {
sourceMap = ((ConfigureSection) source).asMap();
} else {
throw new IllegalArgumentException("Cannot deserialize to Map from " + source.getClass());
}
int mapSize = sourceMap.size();
if (mapSize == 0) {
return new LinkedHashMap<>();
}
ValueType<?> keyValueType = ValueType.of(keyType);
ValueType<?> valueValueType = ValueType.of(valueType);
Map<Object, Object> resultMap = new LinkedHashMap<>(mapSize);
for (Map.Entry<?, ?> entry : sourceMap.entrySet()) {
Object key = deserialize(holder, keyValueType, entry.getKey());
Object value = deserialize(holder, valueValueType, entry.getValue());
resultMap.put(key, value);
}
return resultMap;
}
@Nullable
public <T> Object serialize(@NotNull ConfigurationHolder<?> holder, @Nullable T value) throws Exception {
if (value == null) return null; // Null check
ValueType<T> type = ValueType.of(value);
ValueAdapter<T> adapter = adapterOf(type);
if (adapter != null) return adapter.serialize(holder, type, value);
if (value.getClass().isArray()) {
Object[] array = (Object[]) value;
List<Object> serializedList = new ArrayList<>(array.length);
for (Object item : array) {
serializedList.add(serialize(holder, item));
}
return serializedList;
} else if (value instanceof Collection<?>) {
Collection<?> collection = (Collection<?>) value;
List<Object> serializedList = new ArrayList<>(collection.size());
for (Object item : collection) {
serializedList.add(serialize(holder, item));
}
return serializedList;
} else if (value instanceof Map<?, ?>) {
Map<?, ?> map = (Map<?, ?>) value;
Map<Object, Object> serializedMap = new LinkedHashMap<>(map.size());
for (Map.Entry<?, ?> entry : map.entrySet()) {
Object key = serialize(holder, entry.getKey());
Object val = serialize(holder, entry.getValue());
serializedMap.put(key, val);
}
return serializedMap;
}
return value; // No adapters, and cannot handle, try to return the original value
}
protected <T> List<T> deserializeList(@NotNull ConfigurationHolder<?> holder,
@NotNull ValueType<T> type, @Nullable Object source) throws Exception {
if (source == null) return Collections.emptyList(); // Null check
if (source instanceof List<?>) {
List<?> list = (List<?>) source;
List<T> result = new ArrayList<>(list.size());
for (Object item : list) {
T deserializedItem = deserialize(holder, type, item);
if (deserializedItem != null) {
result.add(deserializedItem);
}
}
return result;
} else { // Maybe singleton? Let's try to deserialize it as a single element list
T deserializedItem = deserialize(holder, type, source);
if (deserializedItem != null) {
return Collections.singletonList(deserializedItem);
} else return Collections.emptyList();
}
}
}
@@ -0,0 +1,20 @@
package cc.carm.lib.configuration.adapter;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Value deserializer, convert base data to target value.
*
* @param <TYPE> The type of target value
*/
@FunctionalInterface
public interface ValueParser<TYPE> {
@Nullable TYPE parse(
@NotNull ConfigurationHolder<?> holder,
@NotNull ValueType<? super TYPE> type, @NotNull Object data
) throws Exception;
}
@@ -0,0 +1,20 @@
package cc.carm.lib.configuration.adapter;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Value serializer, convert target value to base data.
*
* @param <TYPE> The type of value
*/
@FunctionalInterface
public interface ValueSerializer<TYPE> {
@Nullable Object serialize(
@NotNull ConfigurationHolder<?> holder,
@NotNull ValueType<? super TYPE> type, @NotNull TYPE value
) throws Exception;
}
@@ -0,0 +1,249 @@
package cc.carm.lib.configuration.adapter;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* {@link ValueType} used to get the generic type of the value,
* It can be used to check if an object is an instance of a specific type,
* and to cast objects to the correct type.
* <p>
* Java's type system is not capable of retaining generic type information at runtime.
* This class is used to represent a type with its generic parameters.
* </p>
*/
public abstract class ValueType<T> {
public static final ValueType<Object> OBJECT = ofPrimitiveType(Object.class);
public static final ValueType<String> STRING = ofPrimitiveType(String.class);
public static final ValueType<Integer> INTEGER = ofPrimitiveType(Integer.class);
public static final ValueType<Integer> INTEGER_TYPE = ofPrimitiveType(int.class);
public static final ValueType<Long> LONG = ofPrimitiveType(Long.class);
public static final ValueType<Long> LONG_TYPE = ofPrimitiveType(long.class);
public static final ValueType<Double> DOUBLE = ofPrimitiveType(Double.class);
public static final ValueType<Double> DOUBLE_TYPE = ofPrimitiveType(double.class);
public static final ValueType<Float> FLOAT = ofPrimitiveType(Float.class);
public static final ValueType<Float> FLOAT_TYPE = ofPrimitiveType(float.class);
public static final ValueType<Boolean> BOOLEAN = ofPrimitiveType(Boolean.class);
public static final ValueType<Boolean> BOOLEAN_TYPE = ofPrimitiveType(boolean.class);
public static final ValueType<Byte> BYTE = ofPrimitiveType(Byte.class);
public static final ValueType<Byte> BYTE_TYPE = ofPrimitiveType(byte.class);
public static final ValueType<Short> SHORT = ofPrimitiveType(Short.class);
public static final ValueType<Short> SHORT_TYPE = ofPrimitiveType(short.class);
public static final ValueType<Character> CHAR = ofPrimitiveType(Character.class);
public static final ValueType<Character> CHAR_TYPE = ofPrimitiveType(char.class);
public static final ValueType<?>[] PRIMITIVE_TYPES = {
STRING, INTEGER, LONG, DOUBLE, FLOAT, BOOLEAN, BYTE, SHORT, CHAR,
INTEGER_TYPE, LONG_TYPE, DOUBLE_TYPE, FLOAT_TYPE, BOOLEAN_TYPE, BYTE_TYPE, SHORT_TYPE, CHAR_TYPE
};
@SuppressWarnings("unchecked")
public static <T> ValueType<T> of(@NotNull T value) {
return of((Class<T>) value.getClass());
}
@SuppressWarnings("unchecked")
public static <T> ValueType<T> of(final Type type) {
if (type == null) throw new NullPointerException("Type cannot be null");
if (type instanceof Class<?>) { // Try to fast handle primitive types
Class<?> clazz = (Class<?>) type;
for (ValueType<?> valueType : PRIMITIVE_TYPES) {
if (valueType.getRawType() == clazz) {
return (ValueType<T>) valueType;
}
}
}
return new ValueType<T>(type) {
};
}
public static <T> ValueType<T> of(final @NotNull Class<T> clazz) {
return of((Type) clazz);
}
public static <T> ValueType<List<T>> ofList(final @NotNull Class<T> paramType) {
return of(List.class, paramType);
}
public static <T> ValueType<List<T>> ofList(final @NotNull ValueType<T> paramType) {
return of(List.class, paramType.getType());
}
public static <K, V> ValueType<Map<K, V>> ofMap(final @NotNull Class<K> keyType, final @NotNull Class<V> valueType) {
return of(Map.class, keyType, valueType);
}
public static <K, V> ValueType<Map<K, V>> ofMap(final @NotNull ValueType<K> keyType, final @NotNull ValueType<V> valueType) {
return of(Map.class, keyType.getType(), valueType.getType());
}
/**
* Get the generic type of the complex type.
*
* @param rawType The raw type
* @param types The type arguments
* @param <T> The type
* @return The {@link ValueType}
*/
public static <T> ValueType<T> of(final Class<?> rawType, final Type... types) {
ParameterizedType parameterizedType = new ParameterizedType() {
@Override
public @NotNull Type @NotNull [] getActualTypeArguments() {
return types;
}
@Override
public @NotNull Type getRawType() {
return rawType;
}
@Override
public Type getOwnerType() {
return null;
}
};
return of(parameterizedType);
}
@ApiStatus.Internal
private static <T> ValueType<T> ofPrimitiveType(Class<T> clazz) {
return new ValueType<T>(clazz) {
};
}
private final Type type;
protected ValueType() {
this.type = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
private ValueType(Type type) {
this.type = type;
}
public Type getType() {
return type;
}
/**
* Checks if this ValueType is a subtype of the given Class.
*
* @param target The target Class to check against
* @return true if this ValueType is a subtype of the target Class, false otherwise
*/
public boolean isSubtypeOf(Class<?> target) {
Class<?> rawType = getRawType();
return target.isAssignableFrom(rawType);
}
/**
* Checks if this ValueType is a subtype of the given ValueType.
*
* @param target The target ValueType to check against
* @return true if this ValueType is a subtype of the target, false otherwise
*/
public boolean isSubtypeOf(ValueType<?> target) {
return target.isSubtypeOf(getRawType());
}
/**
* Checks if the given object is an instance of the type represented by this ValueType.
*
* @param obj The object to check
* @return true if the object is an instance of the type, false otherwise
*/
public boolean isInstance(Object obj) {
return obj != null && getRawType().isInstance(obj);
}
/**
* Extracts the raw type from the generic type.
*
* @return The raw type of the generic type
* @throws IllegalStateException if the type is not a Class or ParameterizedType
*/
@SuppressWarnings("unchecked")
public Class<T> getRawType() {
if (type instanceof Class<?>) {
return (Class<T>) type;
}
if (type instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) type;
Type raw = pt.getRawType();
if (raw instanceof Class<?>) {
return (Class<T>) raw;
}
}
throw new IllegalStateException("Unsupported type: " + type);
}
/**
* Casts the object to the type represented by this ValueType.
*
* @param obj The object to cast
* @return The object cast to the type represented by this ValueType
*/
@SuppressWarnings("unchecked")
public T cast(Object obj) {
if (!isInstance(obj)) {
throw new ClassCastException("Cannot cast object " + obj + " to type " + this);
}
return (T) obj;
}
/**
* Returns a string representation of the type.
* Like "{@code java.util.List<java.lang.String>}" or "java.lang.Integer".
*
* @return String representation of the type
*/
@Override
public String toString() {
if (type instanceof Class<?>) {
return ((Class<?>) type).getName();
}
if (type instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) type;
Type raw = pt.getRawType();
StringBuilder sb = new StringBuilder();
sb.append(raw.getClass().getName());
sb.append('<');
Type[] args = pt.getActualTypeArguments();
for (int i = 0; i < args.length; i++) {
if (i > 0) {
sb.append(", ");
}
sb.append(args[i].getTypeName());
}
sb.append('>');
return sb.toString();
}
return type.getTypeName();
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj instanceof ValueType) {
return Objects.equals(type, ((ValueType<?>) obj).type);
}
if (obj instanceof Type) {
return Objects.equals(type, obj);
}
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(type);
}
}
@@ -0,0 +1,119 @@
package cc.carm.lib.configuration.adapter.strandard;
import cc.carm.lib.configuration.adapter.ValueAdapter;
import cc.carm.lib.configuration.adapter.ValueParser;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.function.DataFunction;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
public class PrimitiveAdapter<T> extends ValueAdapter<T> {
public static final String[] TRUE_VALUES = new String[]{
"true", "yes", "on", "1", "enabled", "enable", "active"
};
public static final String[] FALSE_VALUES = new String[]{
"false", "no", "off", "0", "disabled", "disable", "inactive"
};
@SuppressWarnings({"unchecked", "rawtypes"})
public static ValueAdapter<Enum<?>> ofEnum() {
ValueAdapter<Enum<?>> adapter = new ValueAdapter<>(new ValueType<Enum<?>>() {
});
adapter.parser((provider, type, data) -> Enum.valueOf((Class<Enum>) type.getRawType(), data.toString()));
adapter.serializer((provider, type, value) -> value.name());
return adapter;
}
public static PrimitiveAdapter<String> ofString() {
return of(String.class, o -> o instanceof String ? (String) o : o.toString());
}
public static PrimitiveAdapter<Boolean> ofBoolean() {
return of(Boolean.class, data -> {
if (data instanceof Boolean) return (Boolean) data;
String v = data.toString().trim();
if (Arrays.stream(TRUE_VALUES).anyMatch(v::equalsIgnoreCase)) return true;
else if (Arrays.stream(FALSE_VALUES).anyMatch(v::equalsIgnoreCase)) return false;
else throw new IllegalArgumentException("Cannot parse boolean from " + data);
});
}
public static PrimitiveAdapter<Boolean> ofBooleanType() {
return of(boolean.class, o -> o instanceof Boolean ? (Boolean) o : Boolean.parseBoolean(o.toString()));
}
public static PrimitiveAdapter<Character> ofCharacter() {
return of(Character.class, o -> o instanceof Character ? (Character) o : o.toString().charAt(0));
}
public static PrimitiveAdapter<Character> ofCharacterType() {
return of(char.class, o -> o instanceof Character ? (Character) o : o.toString().charAt(0));
}
public static PrimitiveAdapter<Integer> ofInteger() {
return ofNumber(Integer.class, Number::intValue, Integer::parseInt);
}
public static PrimitiveAdapter<Integer> ofIntegerType() {
return ofNumber(int.class, Number::intValue, Integer::parseInt);
}
public static PrimitiveAdapter<Long> ofLong() {
return ofNumber(Long.class, Number::longValue, Long::parseLong);
}
public static PrimitiveAdapter<Long> ofLongType() {
return ofNumber(long.class, Number::longValue, Long::parseLong);
}
public static PrimitiveAdapter<Double> ofDouble() {
return ofNumber(Double.class, Number::doubleValue, Double::parseDouble);
}
public static PrimitiveAdapter<Double> ofDoubleType() {
return ofNumber(double.class, Number::doubleValue, Double::parseDouble);
}
public static PrimitiveAdapter<Float> ofFloat() {
return ofNumber(Float.class, Number::floatValue, Float::parseFloat);
}
public static PrimitiveAdapter<Float> ofFloatType() {
return ofNumber(float.class, Number::floatValue, Float::parseFloat);
}
public static PrimitiveAdapter<Short> ofShort() {
return ofNumber(Short.class, Number::shortValue, Short::parseShort);
}
public static PrimitiveAdapter<Short> ofShortType() {
return ofNumber(short.class, Number::shortValue, Short::parseShort);
}
public static PrimitiveAdapter<Byte> ofByte() {
return ofNumber(Byte.class, Number::byteValue, Byte::parseByte);
}
public static PrimitiveAdapter<Byte> ofByteType() {
return ofNumber(byte.class, Number::byteValue, Byte::parseByte);
}
public static <T> PrimitiveAdapter<T> of(@NotNull Class<T> clazz,
@NotNull DataFunction<Object, T> function) {
return new PrimitiveAdapter<>(clazz, (p, type, data) -> function.handle(data));
}
public static <T extends Number> PrimitiveAdapter<T> ofNumber(@NotNull Class<T> numberClass,
@NotNull DataFunction<Number, T> castFunction,
@NotNull DataFunction<String, T> parseFunction) {
return of(numberClass, o -> o instanceof Number ? castFunction.handle((Number) o) : parseFunction.handle(o.toString()));
}
protected PrimitiveAdapter(@NotNull Class<T> valueType, @NotNull ValueParser<T> deserializer) {
super(ValueType.of(valueType), (provider, type, value) -> value, deserializer);
}
}
@@ -0,0 +1,38 @@
package cc.carm.lib.configuration.adapter.strandard;
import cc.carm.lib.configuration.adapter.ValueAdapter;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.source.section.ConfigureSection;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
import static cc.carm.lib.configuration.adapter.strandard.PrimitiveAdapter.*;
public interface StandardAdapters {
@NotNull PrimitiveAdapter<?>[] PRIMITIVES = new PrimitiveAdapter[]{
ofString(), ofBoolean(), ofBooleanType(), ofCharacter(), ofCharacterType(),
ofInteger(), ofIntegerType(), ofLong(), ofLongType(), ofDouble(), ofDoubleType(),
ofFloat(), ofFloatType(), ofShort(), ofShortType(), ofByte(), ofByteType()
};
@NotNull ValueAdapter<Enum<?>> ENUMS = PrimitiveAdapter.ofEnum();
@NotNull ValueAdapter<UUID> UUID = new ValueAdapter<>(
ValueType.of(UUID.class),
(provider, type, value) -> value.toString(),
(provider, type, value) -> java.util.UUID.fromString(value.toString())
);
@NotNull ValueAdapter<ConfigureSection> SECTIONS = new ValueAdapter<>(
ValueType.of(ConfigureSection.class),
(provider, type, value) -> value,
(provider, type, value) -> {
if (value instanceof ConfigureSection) {
return (ConfigureSection) value;
} else throw new IllegalArgumentException("Value is not a ConfigurationSection");
}
);
}
@@ -0,0 +1,32 @@
package cc.carm.lib.configuration.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* The configuration path used to mark the corresponding class or parameter.
*/
@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ConfigPath {
/**
* The path value of the current configuration.
* If not set,will generate the path by {@link cc.carm.lib.configuration.source.loader.PathGenerator}.
*
* @return The path value of the current configuration
*/
String value() default "";
/**
* Whether to start with the root node.
* <br>If false, the previous path (if any) to the node is automatically added.
* <br>If true, the path will be set directly from the root node.
*
* @return Whether to start directly from the root path without inheriting the previous path
*/
boolean root() default false;
}
@@ -0,0 +1,162 @@
package cc.carm.lib.configuration.builder;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.function.DataValidator;
import cc.carm.lib.configuration.function.ValueValidator;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder;
import cc.carm.lib.configuration.source.meta.ConfigurationMetadata;
import cc.carm.lib.configuration.value.ConfigValue;
import cc.carm.lib.configuration.value.ValueManifest;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;
public abstract class AbstractConfigBuilder<
TYPE, UNIT, RESULT extends ConfigValue<TYPE, UNIT>, HOLDER extends ConfigurationHolder<?>,
SELF extends AbstractConfigBuilder<TYPE, UNIT, RESULT, HOLDER, SELF>
> {
protected final Class<? super HOLDER> providerClass;
protected final ValueType<TYPE> type;
protected @Nullable HOLDER holder;
protected @Nullable String path;
protected @NotNull ValueValidator<UNIT> valueValidator = ValueValidator.none();
protected @NotNull Supplier<@Nullable TYPE> defaultValueSupplier = () -> null;
protected @NotNull BiConsumer<ConfigurationHolder<?>, String> initializer = (h, p) -> {
};
protected AbstractConfigBuilder(Class<? super HOLDER> providerClass, ValueType<TYPE> type) {
this.providerClass = providerClass;
this.type = type;
}
public @NotNull ValueType<TYPE> type() {
return type;
}
protected abstract SELF self();
public abstract @NotNull RESULT build();
public SELF holder(@Nullable HOLDER holder) {
this.holder = holder;
return self();
}
public SELF path(@Nullable String path) {
this.path = path;
return self();
}
/**
* Set the {@link ValueValidator} for the value.
*
* @param validator The validator to set.
* @return this builder
*/
public SELF validator(@NotNull ValueValidator<UNIT> validator) {
this.valueValidator = validator;
return self();
}
/**
* Set the {@link DataValidator} for the value.
*
* @param validator The validator to set.
* @return this builder
*/
public SELF validator(@NotNull DataValidator<? super UNIT> validator) {
return validator((h, value) -> validator.validate(value));
}
/**
* Validate the value with the specified condition.
*
* @param validator The validator to append.
* @return this builder
*/
public SELF validate(@NotNull ValueValidator<? super UNIT> validator) {
return validator(this.valueValidator.and(validator));
}
/**
* Validate the value with the specified condition.
*
* @param validator The validator to append.
* @return this builder
*/
public SELF validate(@NotNull DataValidator<? super UNIT> validator) {
return validate((h, value) -> validator.validate(value));
}
/**
* Validate the value with the specified condition.
*
* @param condition The condition to check, if the condition is false, an exception will be thrown.
* @param exception The exception to throw if the condition is false.
* @return this builder
*/
public SELF validate(@NotNull Predicate<? super UNIT> condition, @NotNull Exception exception) {
return validate((h, value) -> {
if (!condition.test(value)) throw exception;
});
}
/**
* Validate the value with the specified condition.
*
* @param condition The condition to check, if the condition is false, an exception will be thrown.
* @param msg The message to throw if the condition is false.
* @return this builder
*/
public SELF validate(@NotNull Predicate<? super UNIT> condition, @NotNull String msg) {
return validate((h, value) -> {
if (!condition.test(value)) throw new IllegalArgumentException(msg);
});
}
public SELF initializer(@NotNull BiConsumer<ConfigurationHolder<?>, String> initializer) {
this.initializer = initializer;
return self();
}
public SELF append(@NotNull BiConsumer<ConfigurationHolder<?>, String> initializer) {
return initializer(initializer.andThen(initializer));
}
public SELF append(@NotNull Consumer<ConfigurationHolder<?>> initializer) {
return append((provider, valuePath) -> initializer.accept(provider));
}
public SELF defaults(@Nullable TYPE defaultValue) {
return defaults(() -> defaultValue);
}
public SELF defaults(@NotNull Supplier<@Nullable TYPE> supplier) {
this.defaultValueSupplier = supplier;
return self();
}
public SELF meta(@NotNull Consumer<@NotNull ConfigurationMetaHolder> metaConsumer) {
return append((h, p) -> metaConsumer.accept(h.metadata(p)));
}
public <M> SELF meta(@NotNull ConfigurationMetadata<M> type, @Nullable M value) {
return meta(h -> h.set(type, value));
}
protected @NotNull ValueManifest<TYPE, UNIT> buildManifest() {
return new ValueManifest<>(
type(), this.defaultValueSupplier, this.valueValidator,
this.initializer, this.holder, this.path
);
}
}
@@ -0,0 +1,17 @@
package cc.carm.lib.configuration.builder;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import cc.carm.lib.configuration.value.ConfigValue;
public abstract class CommonConfigBuilder<
TYPE, UNIT,
RESULT extends ConfigValue<TYPE, UNIT>,
SELF extends CommonConfigBuilder<TYPE, UNIT, RESULT, SELF>
> extends AbstractConfigBuilder<TYPE, UNIT, RESULT, ConfigurationHolder<?>, SELF> {
protected CommonConfigBuilder(ValueType<TYPE> type) {
super(ConfigurationHolder.class, type);
}
}
@@ -0,0 +1,55 @@
package cc.carm.lib.configuration.builder.collection;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.builder.impl.AbstractSectionBuilder;
import cc.carm.lib.configuration.function.ValueHandler;
import cc.carm.lib.configuration.source.section.ConfigureSection;
import cc.carm.lib.configuration.value.impl.CollectionConfigValue;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Supplier;
public abstract class SectionCollectionBuilder<
V, C extends Collection<V>,
RESULT extends CollectionConfigValue<V, C, ?>,
SELF extends SectionCollectionBuilder<V, C, RESULT, SELF>
> extends AbstractSectionBuilder<C, V, RESULT, SELF> {
protected @NotNull Supplier<? extends C> constructor;
public SectionCollectionBuilder(@NotNull Supplier<? extends C> constructor,
@NotNull ValueType<V> paramType,
@NotNull ValueHandler<ConfigureSection, V> parser,
@NotNull ValueHandler<V, ? extends Map<String, Object>> serializer) {
super(new ValueType<C>() {
}, paramType, parser, serializer);
this.constructor = constructor;
}
@SafeVarargs
public final @NotNull SELF defaults(@NotNull V... values) {
return defaults(c -> c.addAll(Arrays.asList(values)));
}
public final @NotNull SELF defaults(@NotNull Consumer<C> constructor) {
return defaults(() -> {
C collection = this.constructor.get();
constructor.accept(collection);
return collection;
});
}
public SELF constructor(@NotNull Supplier<? extends C> constructor) {
this.constructor = constructor;
return self();
}
public SELF construct(@NotNull C collection) {
return constructor(() -> collection);
}
}
@@ -0,0 +1,138 @@
package cc.carm.lib.configuration.builder.collection;
import cc.carm.lib.configuration.adapter.ValueAdapter;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.function.ValueHandler;
import cc.carm.lib.configuration.source.section.ConfigureSection;
import cc.carm.lib.configuration.value.ValueManifest;
import cc.carm.lib.configuration.value.impl.CollectionConfigValue;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Map;
import java.util.function.Supplier;
public class SimpleCollectionCreator<V, C extends Collection<V>, RESULT extends CollectionConfigValue<V, C, ?>> {
public static <V, C extends Collection<V>, RESULT extends CollectionConfigValue<V, C, ?>>
@NotNull SimpleCollectionCreator<V, C, RESULT> create(
@NotNull ValueType<V> type,
@NotNull Supplier<? extends C> defaultConstructor,
@NotNull CollectionValueFactory<V, C, RESULT> factory) {
return new SimpleCollectionCreator<>(type, defaultConstructor, factory);
}
protected final @NotNull Supplier<? extends C> defaultConstructor;
protected final @NotNull ValueType<V> type;
protected final @NotNull CollectionValueFactory<V, C, RESULT> factory;
public SimpleCollectionCreator(@NotNull ValueType<V> type,
@NotNull Supplier<? extends C> defaultConstructor,
@NotNull CollectionValueFactory<V, C, RESULT> factory) {
this.defaultConstructor = defaultConstructor;
this.type = type;
this.factory = factory;
}
public <S> @NotNull Source<S, V, C, RESULT> from(@NotNull Class<S> sourceType) {
return from(ValueType.of(sourceType));
}
public <S> @NotNull Source<S, V, C, RESULT> from(@NotNull ValueType<S> sourceType) {
return new Source<S, V, C, RESULT>(
defaultConstructor, sourceType, type,
ValueHandler.required(type),
ValueHandler.required(sourceType),
factory
);
}
public @NotNull SimpleCollectionCreator.Source<Object, V, C, RESULT> fromObject() {
return new Source<Object, V, C, RESULT>(
defaultConstructor, ValueType.OBJECT, type,
ValueHandler.deserialize(type), ValueHandler.toObject(),
factory
);
}
public @NotNull SimpleCollectionCreator.Source<String, V, C, RESULT> fromString() {
return new Source<String, V, C, RESULT>(
defaultConstructor, ValueType.STRING, type,
ValueHandler.required(type), ValueHandler.stringValue(),
factory
);
}
public @NotNull SimpleCollectionCreator.Section<V, C, RESULT> fromSection() {
return new Section<V, C, RESULT>(
defaultConstructor, type,
ValueHandler.required(type), ValueHandler.required(),
factory
);
}
@FunctionalInterface
public interface CollectionValueFactory<V, C, RESULT> {
@NotNull RESULT build(
@NotNull ValueManifest<C, V> manifest,
@NotNull Supplier<? extends C> constructor,
@NotNull ValueAdapter<V> paramAdapter
);
}
public static class Source<SOURCE, V, C extends Collection<V>, RESULT extends CollectionConfigValue<V, C, ?>>
extends SourceCollectionBuilder<SOURCE, V, C, RESULT, Source<SOURCE, V, C, RESULT>> {
protected final @NotNull CollectionValueFactory<V, C, RESULT> factory;
public Source(
@NotNull Supplier<? extends C> constructor,
@NotNull ValueType<SOURCE> sourceType,
@NotNull ValueType<V> paramType,
@NotNull ValueHandler<SOURCE, V> parser,
@NotNull ValueHandler<V, SOURCE> serializer,
@NotNull CollectionValueFactory<V, C, RESULT> factory) {
super(constructor, sourceType, paramType, parser, serializer);
this.factory = factory;
}
@Override
protected @NotNull SimpleCollectionCreator.Source<SOURCE, V, C, RESULT> self() {
return this;
}
@Override
public @NotNull RESULT build() {
return factory.build(buildManifest(), constructor, buildAdapter());
}
}
public static class Section<V, C extends Collection<V>, RESULT extends CollectionConfigValue<V, C, ?>>
extends SectionCollectionBuilder<V, C, RESULT, Section<V, C, RESULT>> {
protected final @NotNull CollectionValueFactory<V, C, RESULT> factory;
public Section(
@NotNull Supplier<? extends C> constructor,
@NotNull ValueType<V> paramType,
@NotNull ValueHandler<ConfigureSection, V> parser,
@NotNull ValueHandler<V, ? extends Map<String, Object>> serializer,
@NotNull CollectionValueFactory<V, C, RESULT> factory) {
super(constructor, paramType, parser, serializer);
this.factory = factory;
}
@Override
protected @NotNull SimpleCollectionCreator.Section<V, C, RESULT> self() {
return this;
}
@Override
public @NotNull RESULT build() {
return factory.build(buildManifest(), constructor, buildAdapter());
}
}
}
@@ -0,0 +1,53 @@
package cc.carm.lib.configuration.builder.collection;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.builder.impl.AbstractSourceBuilder;
import cc.carm.lib.configuration.function.ValueHandler;
import cc.carm.lib.configuration.value.impl.CollectionConfigValue;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.Collection;
import java.util.function.Consumer;
import java.util.function.Supplier;
public abstract class SourceCollectionBuilder<
SOURCE, V, C extends Collection<V>,
RESULT extends CollectionConfigValue<V, C, ?>,
SELF extends SourceCollectionBuilder<SOURCE, V, C, RESULT, SELF>
>
extends AbstractSourceBuilder<C, SOURCE, V, RESULT, SELF> {
protected @NotNull Supplier<? extends C> constructor;
public SourceCollectionBuilder(@NotNull Supplier<? extends C> constructor,
@NotNull ValueType<SOURCE> sourceType, @NotNull ValueType<V> paramType,
@NotNull ValueHandler<SOURCE, V> parser, @NotNull ValueHandler<V, SOURCE> serializer) {
super(new ValueType<C>() {
}, sourceType, paramType, parser, serializer);
this.constructor = constructor;
}
@SafeVarargs
public final @NotNull SELF defaults(@NotNull V... values) {
return defaults(c -> c.addAll(Arrays.asList(values)));
}
public final @NotNull SELF defaults(@NotNull Consumer<C> constructor) {
return defaults(() -> {
C collection = this.constructor.get();
constructor.accept(collection);
return collection;
});
}
public SELF constructor(@NotNull Supplier<? extends C> constructor) {
this.constructor = constructor;
return self();
}
public SELF construct(@NotNull C collection) {
return constructor(() -> collection);
}
}
@@ -0,0 +1,76 @@
package cc.carm.lib.configuration.builder.impl;
import cc.carm.lib.configuration.adapter.ValueAdapter;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.builder.CommonConfigBuilder;
import cc.carm.lib.configuration.function.DataFunction;
import cc.carm.lib.configuration.function.ValueComposer;
import cc.carm.lib.configuration.function.ValueHandler;
import cc.carm.lib.configuration.source.section.ConfigureSection;
import cc.carm.lib.configuration.value.ConfigValue;
import org.jetbrains.annotations.NotNull;
import java.util.LinkedHashMap;
import java.util.Map;
public abstract class AbstractSectionBuilder<
TYPE, UNIT,
RESULT extends ConfigValue<TYPE, UNIT>,
SELF extends AbstractSectionBuilder<TYPE, UNIT, RESULT, SELF>
> extends CommonConfigBuilder<TYPE, UNIT, RESULT, SELF> {
protected final @NotNull ValueType<UNIT> paramType;
protected @NotNull ValueHandler<ConfigureSection, UNIT> parser;
protected @NotNull ValueHandler<UNIT, ? extends Map<String, Object>> serializer;
protected AbstractSectionBuilder(@NotNull ValueType<TYPE> type, @NotNull ValueType<UNIT> paramType,
@NotNull ValueHandler<ConfigureSection, UNIT> parser,
@NotNull ValueHandler<UNIT, ? extends Map<String, Object>> serializer) {
super(type);
this.paramType = paramType;
this.parser = parser;
this.serializer = serializer;
}
public @NotNull SELF parse(@NotNull DataFunction<ConfigureSection, UNIT> valueParser) {
return parse((p, section) -> valueParser.handle(section));
}
public @NotNull SELF parse(@NotNull ValueHandler<ConfigureSection, UNIT> valueParser) {
this.parser = valueParser;
return self();
}
public @NotNull SELF serialize(@NotNull ValueHandler<UNIT, ? extends Map<String, Object>> serializer) {
this.serializer = serializer;
return self();
}
public @NotNull SELF serialize(@NotNull DataFunction<UNIT, ? extends Map<String, Object>> serializer) {
return serialize((p, value) -> serializer.handle(value));
}
public @NotNull SELF serialize(@NotNull ValueComposer<Map<String, Object>, UNIT> serializer) {
return serialize((h, value) -> {
Map<String, Object> map = new LinkedHashMap<>();
serializer.accept(h, map, value);
return map;
});
}
protected ValueAdapter<UNIT> buildAdapter() {
return new ValueAdapter<>(this.paramType)
.parser((p, type, data) -> {
ConfigureSection section = p.deserialize(ConfigureSection.class, data);
if (section == null) return null;
return this.parser.handle(p, section);
})
.serializer((p, type, data) -> {
Map<String, Object> map = this.serializer.handle(p, data);
return map == null || map.isEmpty() ? null : map;
});
}
}
@@ -0,0 +1,74 @@
package cc.carm.lib.configuration.builder.impl;
import cc.carm.lib.configuration.adapter.ValueAdapter;
import cc.carm.lib.configuration.adapter.ValueParser;
import cc.carm.lib.configuration.adapter.ValueSerializer;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.builder.CommonConfigBuilder;
import cc.carm.lib.configuration.function.DataFunction;
import cc.carm.lib.configuration.function.ValueHandler;
import cc.carm.lib.configuration.value.ConfigValue;
import org.jetbrains.annotations.NotNull;
public abstract class AbstractSourceBuilder<
V, SOURCE, UNIT, RESULT extends ConfigValue<V, UNIT>,
SELF extends AbstractSourceBuilder<V, SOURCE, UNIT, RESULT, SELF>
> extends CommonConfigBuilder<V, UNIT, RESULT, SELF> {
protected final @NotNull ValueType<SOURCE> sourceType;
protected final @NotNull ValueType<UNIT> paramType;
@SuppressWarnings("NotNullFieldNotInitialized") // Already initialized in constructor
protected @NotNull ValueParser<UNIT> valueParser;
@SuppressWarnings("NotNullFieldNotInitialized") // Already initialized in constructor
protected @NotNull ValueSerializer<UNIT> valueSerializer;
protected AbstractSourceBuilder(@NotNull ValueType<V> type,
@NotNull ValueType<SOURCE> sourceType, @NotNull ValueType<UNIT> paramType,
@NotNull ValueHandler<SOURCE, UNIT> parser,
@NotNull ValueHandler<UNIT, SOURCE> serializer) {
super(type);
this.sourceType = sourceType;
this.paramType = paramType;
parse(parser);
serialize(serializer);
}
public @NotNull SELF parse(@NotNull DataFunction<SOURCE, UNIT> parser) {
return parse((p, source) -> parser.handle(source));
}
public @NotNull SELF parse(@NotNull ValueHandler<SOURCE, UNIT> parser) {
return parser((holder, type, data) -> {
SOURCE source = holder.deserialize(this.sourceType, data);
return parser.handle(holder, source);
});
}
public @NotNull SELF parser(@NotNull ValueParser<UNIT> parser) {
this.valueParser = parser;
return self();
}
public @NotNull SELF serialize(@NotNull ValueHandler<UNIT, SOURCE> serializer) {
return serializer((holder, type, data) -> {
SOURCE source = serializer.handle(holder, data);
return holder.serialize(source);
});
}
public @NotNull SELF serialize(@NotNull DataFunction<UNIT, SOURCE> serializer) {
return serialize((p, value) -> serializer.handle(value));
}
public @NotNull SELF serializer(@NotNull ValueSerializer<UNIT> serializer) {
this.valueSerializer = serializer;
return self();
}
protected ValueAdapter<UNIT> buildAdapter() {
return new ValueAdapter<>(this.paramType, this.valueSerializer, this.valueParser);
}
}
@@ -0,0 +1,17 @@
package cc.carm.lib.configuration.builder.list;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.builder.collection.SimpleCollectionCreator;
import cc.carm.lib.configuration.value.standard.ConfiguredList;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
public class ConfigListCreator<V> extends SimpleCollectionCreator<V, List<V>, ConfiguredList<V>> {
public ConfigListCreator(@NotNull ValueType<V> type) {
super(type, ArrayList::new, ConfiguredList::new);
}
}
@@ -0,0 +1,89 @@
package cc.carm.lib.configuration.builder.map;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.function.ValueHandler;
import cc.carm.lib.configuration.source.section.ConfigureSection;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
import java.util.function.Supplier;
public class ConfigMapBuilder<M extends Map<K, V>, K, V> {
protected final @NotNull Supplier<@NotNull M> constructor;
protected final @NotNull ValueType<K> keyType;
protected final @NotNull ValueType<V> valueType;
public ConfigMapBuilder(@NotNull Supplier<@NotNull M> constructor,
@NotNull ValueType<K> keyType, @NotNull ValueType<V> valueType) {
this.constructor = constructor;
this.keyType = keyType;
this.valueType = valueType;
}
public <W extends Map<K, V>> ConfigMapBuilder<W, K, V> constructor(@NotNull Supplier<W> supplier) {
return new ConfigMapBuilder<>(supplier, keyType, valueType);
}
public @NotNull <S> SourceMapBuilder<M, S, K, V> from(@NotNull Class<S> clazz) {
return from(ValueType.of(clazz));
}
public @NotNull <S> SourceMapBuilder<M, S, K, V> from(@NotNull ValueType<S> sourceType) {
return from(
sourceType,
ValueHandler.required(keyType), ValueHandler.stringValue(),
ValueHandler.required(valueType), ValueHandler.required()
);
}
public <S> @NotNull SourceMapBuilder<M, S, K, V> from(@NotNull ValueType<S> sourceType,
@NotNull ValueHandler<String, K> keyParser,
@NotNull ValueHandler<K, String> keySerializer,
@NotNull ValueHandler<S, V> valueParser,
@NotNull ValueHandler<V, S> valueSerializer) {
return new SourceMapBuilder<>(
this.constructor, sourceType, keyType, valueType,
keyParser, keySerializer, valueParser, valueSerializer
);
}
public @NotNull <S> SourceMapBuilder<M, Object, K, V> fromObject() {
return from(
ValueType.OBJECT,
ValueHandler.deserialize(keyType), ValueHandler.stringValue(),
ValueHandler.deserialize(valueType), ValueHandler.toObject()
);
}
public @NotNull SourceMapBuilder<M, String, K, V> fromString() {
return from(
ValueType.STRING,
ValueHandler.required(keyType), ValueHandler.stringValue(),
ValueHandler.required(valueType), ValueHandler.stringValue()
);
}
public @NotNull SectionMapBuilder<M, K, V> fromSection() {
return fromSection(
ValueHandler.required(keyType), ValueHandler.stringValue(),
ValueHandler.required(valueType), ValueHandler.required()
);
}
public @NotNull SectionMapBuilder<M, K, V> fromSection(
@NotNull ValueHandler<String, K> keyParser,
@NotNull ValueHandler<K, String> keySerializer,
@NotNull ValueHandler<ConfigureSection, V> valueParser,
@NotNull ValueHandler<V, Map<String, Object>> valueSerializer
) {
return new SectionMapBuilder<>(
this.constructor, keyType, valueType,
keyParser, keySerializer, valueParser, valueSerializer
);
}
}
@@ -0,0 +1,49 @@
package cc.carm.lib.configuration.builder.map;
import cc.carm.lib.configuration.adapter.ValueType;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.function.Supplier;
public class ConfigMapCreator<K, V> {
protected final @NotNull ValueType<K> keyType;
protected final @NotNull ValueType<V> valueType;
public ConfigMapCreator(@NotNull ValueType<K> keyType, @NotNull ValueType<V> valueType) {
this.keyType = keyType;
this.valueType = valueType;
}
public <M extends Map<K, V>> @NotNull ConfigMapBuilder<M, K, V> constructor(@NotNull Supplier<@NotNull M> mapSuppler) {
return new ConfigMapBuilder<>(mapSuppler, keyType, valueType);
}
public <W extends Map<K, V>> @NotNull ConfigMapBuilder<W, K, V> constructor(@NotNull Class<W> type) {
return constructor(() -> {
try {
return type.getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}
public @NotNull ConfigMapBuilder<HashMap<K, V>, K, V> asHashMap() {
return constructor(HashMap::new);
}
public @NotNull ConfigMapBuilder<LinkedHashMap<K, V>, K, V> asLinkedMap() {
return constructor(LinkedHashMap::new);
}
public @NotNull ConfigMapBuilder<TreeMap<K, V>, K, V> asTreeMap() {
return constructor(TreeMap::new);
}
public @NotNull ConfigMapBuilder<TreeMap<K, V>, K, V> asTreeMap(@NotNull Comparator<? super K> comparator) {
return constructor(() -> new TreeMap<>(comparator));
}
}
@@ -0,0 +1,96 @@
package cc.carm.lib.configuration.builder.map;
import cc.carm.lib.configuration.adapter.ValueAdapter;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.builder.impl.AbstractSectionBuilder;
import cc.carm.lib.configuration.function.DataFunction;
import cc.carm.lib.configuration.function.ValueHandler;
import cc.carm.lib.configuration.source.section.ConfigureSection;
import cc.carm.lib.configuration.value.standard.ConfiguredMap;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class SectionMapBuilder<MAP extends Map<K, V>, K, V>
extends AbstractSectionBuilder<Map<K, V>, V, ConfiguredMap<K, V>, SectionMapBuilder<MAP, K, V>> {
protected final @NotNull ValueType<K> keyType;
protected @NotNull Supplier<? extends MAP> constructor;
protected @NotNull ValueHandler<String, K> keyParser;
protected @NotNull ValueHandler<K, String> keySerializer;
public SectionMapBuilder(@NotNull Supplier<? extends MAP> constructor,
@NotNull ValueType<K> keyType, @NotNull ValueType<V> valueType,
@NotNull ValueHandler<String, K> keyParser,
@NotNull ValueHandler<K, String> keySerializer,
@NotNull ValueHandler<ConfigureSection, V> valueParser,
@NotNull ValueHandler<V, Map<String, Object>> valueSerializer) {
super(new ValueType<Map<K, V>>() {
}, valueType, valueParser, valueSerializer);
this.keyType = keyType;
this.constructor = constructor;
this.keyParser = keyParser;
this.keySerializer = keySerializer;
}
@Override
protected @NotNull SectionMapBuilder<MAP, K, V> self() {
return this;
}
public @NotNull SectionMapBuilder<MAP, K, V> parseKey(@NotNull DataFunction<String, K> keyParser) {
return parseKey((holder, data) -> keyParser.handle(data));
}
public @NotNull SectionMapBuilder<MAP, K, V> parseKey(@NotNull ValueHandler<String, K> keyParser) {
this.keyParser = keyParser;
return this;
}
public @NotNull SectionMapBuilder<MAP, K, V> serializeKey(@NotNull DataFunction<K, String> keySerializer) {
return serializeKey((holder, data) -> keySerializer.handle(data));
}
public @NotNull SectionMapBuilder<MAP, K, V> serializeKey(@NotNull ValueHandler<K, String> keySerializer) {
this.keySerializer = keySerializer;
return this;
}
public @NotNull SectionMapBuilder<MAP, K, V> defaults(@NotNull MAP defaults) {
return defaults(() -> defaults);
}
public @NotNull SectionMapBuilder<MAP, K, V> defaults(@NotNull Consumer<MAP> defaults) {
return defaults(() -> {
MAP map = this.constructor.get();
defaults.accept(map);
return map;
});
}
public @NotNull SectionMapBuilder<MAP, K, V> defaults(@NotNull K key, @NotNull V value) {
return defaults(map -> map.put(key, value));
}
public @NotNull ValueAdapter<K> buildKeyAdapter() {
return new ValueAdapter<>(this.keyType)
.parser((holder, type, data) -> {
String source = holder.deserialize(String.class, data);
return this.keyParser.handle(holder, source);
})
.serializer((holder, type, data) -> {
String source = this.keySerializer.handle(holder, data);
return holder.serialize(source);
});
}
@Override
public @NotNull ConfiguredMap<K, V> build() {
return new ConfiguredMap<>(buildManifest(), this.constructor, buildKeyAdapter(), this.buildAdapter());
}
}
@@ -0,0 +1,92 @@
package cc.carm.lib.configuration.builder.map;
import cc.carm.lib.configuration.adapter.ValueAdapter;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.builder.impl.AbstractSourceBuilder;
import cc.carm.lib.configuration.function.DataFunction;
import cc.carm.lib.configuration.function.ValueHandler;
import cc.carm.lib.configuration.value.standard.ConfiguredMap;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class SourceMapBuilder<MAP extends Map<K, V>, SOURCE, K, V>
extends AbstractSourceBuilder<Map<K, V>, SOURCE, V, ConfiguredMap<K, V>, SourceMapBuilder<MAP, SOURCE, K, V>> {
protected final @NotNull ValueType<K> keyType;
protected @NotNull Supplier<? extends MAP> constructor;
protected @NotNull ValueHandler<String, K> keyParser;
protected @NotNull ValueHandler<K, String> keySerializer;
public SourceMapBuilder(@NotNull Supplier<? extends MAP> constructor, @NotNull ValueType<SOURCE> sourceType,
@NotNull ValueType<K> keyType, @NotNull ValueType<V> valueType,
@NotNull ValueHandler<String, K> keyParser, @NotNull ValueHandler<K, String> keySerializer,
@NotNull ValueHandler<SOURCE, V> valueParser, @NotNull ValueHandler<V, SOURCE> valueSerializer) {
super(new ValueType<Map<K, V>>() {
}, sourceType, valueType, valueParser, valueSerializer);
this.keyType = keyType;
this.constructor = constructor;
this.keyParser = keyParser;
this.keySerializer = keySerializer;
}
@Override
protected @NotNull SourceMapBuilder<MAP, SOURCE, K, V> self() {
return this;
}
public @NotNull SourceMapBuilder<MAP, SOURCE, K, V> defaults(@NotNull MAP defaults) {
return defaults(() -> defaults);
}
public @NotNull SourceMapBuilder<MAP, SOURCE, K, V> defaults(@NotNull Consumer<MAP> defaults) {
return defaults(() -> {
MAP map = this.constructor.get();
defaults.accept(map);
return map;
});
}
public @NotNull SourceMapBuilder<MAP, SOURCE, K, V> defaults(@NotNull K key, @NotNull V value) {
return defaults(map -> map.put(key, value));
}
public @NotNull SourceMapBuilder<MAP, SOURCE, K, V> parseKey(@NotNull DataFunction<String, K> keyParser) {
return parseKey((holder, data) -> keyParser.handle(data));
}
public @NotNull SourceMapBuilder<MAP, SOURCE, K, V> parseKey(@NotNull ValueHandler<String, K> keyParser) {
this.keyParser = keyParser;
return this;
}
public @NotNull SourceMapBuilder<MAP, SOURCE, K, V> serializeKey(@NotNull DataFunction<K, String> keySerializer) {
return serializeKey((holder, data) -> keySerializer.handle(data));
}
public @NotNull SourceMapBuilder<MAP, SOURCE, K, V> serializeKey(@NotNull ValueHandler<K, String> keySerializer) {
this.keySerializer = keySerializer;
return this;
}
public @NotNull ValueAdapter<K> buildKeyAdapter() {
return new ValueAdapter<>(this.keyType)
.parser((holder, type, data) -> {
String source = holder.deserialize(String.class, data);
return this.keyParser.handle(holder, source);
})
.serializer((holder, type, data) -> {
String source = this.keySerializer.handle(holder, data);
return holder.serialize(source);
});
}
@Override
public @NotNull ConfiguredMap<K, V> build() {
return new ConfiguredMap<>(buildManifest(), this.constructor, buildKeyAdapter(), this.buildAdapter());
}
}
@@ -0,0 +1,47 @@
package cc.carm.lib.configuration.builder.value;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.function.ValueHandler;
import cc.carm.lib.configuration.source.section.ConfigureSection;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
public class ConfigValueBuilder<V> {
protected final @NotNull ValueType<V> type;
public ConfigValueBuilder(@NotNull ValueType<V> type) {
this.type = type;
}
public @NotNull <S> SourceValueBuilder<S, V> from(@NotNull Class<S> clazz) {
return from(ValueType.of(clazz));
}
public @NotNull <S> SourceValueBuilder<S, V> from(@NotNull ValueType<S> sourceType) {
return from(sourceType, ValueHandler.required(type), ValueHandler.required(sourceType));
}
public @NotNull <S> SourceValueBuilder<S, V> from(@NotNull ValueType<S> sourceType,
@NotNull ValueHandler<S, V> valueParser,
@NotNull ValueHandler<V, S> valueSerializer) {
return new SourceValueBuilder<>(sourceType, this.type, valueParser, valueSerializer);
}
public @NotNull SourceValueBuilder<String, V> fromString() {
return from(ValueType.STRING, ValueHandler.required(type), ValueHandler.stringValue());
}
public @NotNull SectionValueBuilder<V> fromSection() {
return fromSection(ValueHandler.required(type), ValueHandler.required());
}
public @NotNull SectionValueBuilder<V> fromSection(
@NotNull ValueHandler<ConfigureSection, V> valueParser,
@NotNull ValueHandler<V, ? extends Map<String, Object>> valueSerializer
) {
return new SectionValueBuilder<>(this.type, valueParser, valueSerializer);
}
}
@@ -0,0 +1,30 @@
package cc.carm.lib.configuration.builder.value;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.builder.impl.AbstractSectionBuilder;
import cc.carm.lib.configuration.function.ValueHandler;
import cc.carm.lib.configuration.source.section.ConfigureSection;
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
public class SectionValueBuilder<V> extends AbstractSectionBuilder<V, V, ConfiguredValue<V>, SectionValueBuilder<V>> {
public SectionValueBuilder(@NotNull ValueType<V> type,
@NotNull ValueHandler<ConfigureSection, V> parser,
@NotNull ValueHandler<V, ? extends Map<String, Object>> serializer) {
super(type, type, parser, serializer);
}
@Override
protected @NotNull SectionValueBuilder<V> self() {
return this;
}
@Override
public @NotNull ConfiguredValue<V> build() {
return ConfiguredValue.of(buildManifest(), buildAdapter());
}
}
@@ -0,0 +1,28 @@
package cc.carm.lib.configuration.builder.value;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.builder.impl.AbstractSourceBuilder;
import cc.carm.lib.configuration.function.ValueHandler;
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
import org.jetbrains.annotations.NotNull;
public class SourceValueBuilder<S, V>
extends AbstractSourceBuilder<V, S, V, ConfiguredValue<V>, SourceValueBuilder<S, V>> {
public SourceValueBuilder(@NotNull ValueType<S> sourceType, @NotNull ValueType<V> valueType,
@NotNull ValueHandler<S, V> parser, @NotNull ValueHandler<V, S> serializer) {
super(valueType, sourceType, valueType, parser, serializer);
}
@Override
protected @NotNull SourceValueBuilder<S, V> self() {
return this;
}
@Override
public @NotNull ConfiguredValue<V> build() {
return new ConfiguredValue<>(buildManifest(), buildAdapter());
}
}
@@ -1,124 +0,0 @@
package cc.carm.lib.configuration.core;
import cc.carm.lib.configuration.core.annotation.ConfigComment;
import cc.carm.lib.configuration.core.annotation.ConfigPath;
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
import cc.carm.lib.configuration.core.value.ConfigValue;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Optional;
public class ConfigInitializer {
public static void initialize(ConfigurationProvider source, Class<? extends ConfigurationRoot> rootClazz) {
initialize(source, rootClazz, true);
}
public static void initialize(ConfigurationProvider provider, Class<? extends ConfigurationRoot> rootClazz, boolean saveDefault) {
String rootSection = null;
ConfigPath sectionAnnotation = rootClazz.getAnnotation(ConfigPath.class);
if (sectionAnnotation != null && sectionAnnotation.value().length() > 1) {
rootSection = sectionAnnotation.value();
}
if (rootSection != null) {
//Not usable for null section.
ConfigComment comments = rootClazz.getAnnotation(ConfigComment.class);
if (comments != null && comments.value().length > 0) {
provider.setComments(rootSection, comments.value());
}
}
for (Class<?> innerClass : rootClazz.getDeclaredClasses()) {
initSection(provider, rootSection, innerClass, saveDefault);
}
for (Field field : rootClazz.getDeclaredFields()) {
initValue(provider, rootSection, rootClazz, field, saveDefault);
}
if (saveDefault) {
try {
provider.save();
} catch (Exception e) {
e.printStackTrace();
}
}
}
private static void initSection(ConfigurationProvider provider, String parentSection, Class<?> clazz, boolean saveDefault) {
if (!Modifier.isStatic(clazz.getModifiers()) || !Modifier.isPublic(clazz.getModifiers())) return;
String section = getSectionPath(clazz.getSimpleName(), parentSection, clazz.getAnnotation(ConfigPath.class));
ConfigComment comments = clazz.getAnnotation(ConfigComment.class);
if (comments != null && comments.value().length > 0) {
provider.setComments(parentSection, comments.value());
}
for (Field field : clazz.getDeclaredFields()) initValue(provider, section, clazz, field, saveDefault);
for (Class<?> innerClass : clazz.getDeclaredClasses()) initSection(provider, section, innerClass, saveDefault);
}
private static void initValue(ConfigurationProvider provider, String parentSection, Class<?> clazz, Field field, boolean saveDefault) {
try {
field.setAccessible(true);
Object object = field.get(clazz);
if (object instanceof ConfigValue<?>) {
initializeValue(
provider, (ConfigValue<?>) object, saveDefault,
getSectionPath(field.getName(), parentSection, field.getAnnotation(ConfigPath.class)),
Optional.ofNullable(field.getAnnotation(ConfigComment.class))
.map(ConfigComment::value).orElse(new String[0])
);
}
} catch (IllegalAccessException ignored) {
}
}
public static void initializeValue(@NotNull ConfigurationProvider provider, @NotNull ConfigValue<?> value,
boolean saveDefault, @NotNull String path, @NotNull String[] comments) {
value.initialize(provider, path, comments);
if (saveDefault && value.getDefaultValue() != null && !provider.getConfiguration().contains(path)) {
value.setDefault();
}
}
public static String getSectionPath(@NotNull String name,
@Nullable String parentSection,
@Nullable ConfigPath pathAnnotation) {
@NotNull String parent = parentSection != null ? parentSection + "." : "";
@NotNull String path = getSectionName(name);
boolean root = false;
if (pathAnnotation != null) {
if (pathAnnotation.value().length() > 0) path = pathAnnotation.value();
root = pathAnnotation.root();
}
return (root ? "" : parent) + path;
}
/**
* 得到指定元素的配置名称。
* 采用 全小写,以“-”链接 的命名规则。
*
* @param name 源名称
* @return 全小写,以“-”链接 的 路径名称
*/
public static String getSectionName(String name) {
return name.replaceAll("[A-Z]", "-$0") // 将驼峰转换为蛇形;
.replaceAll("-(.*)", "$1") // 若首字母也为大写,则也会被转换,需要去掉第一个横线
.replaceAll("_-([A-Z])", "_$1") // 因为命名中可能包含 _,因此需要被特殊处理一下
.replaceAll("([a-z])-([A-Z])", "$1_$2") // 然后将非全大写命名的内容进行转换
.replace("-", "") // 移除掉多余的横线
.replace("_", "-") // 将下划线替换为横线
.toLowerCase(); // 最后转为全小写
}
}
@@ -1,4 +0,0 @@
package cc.carm.lib.configuration.core;
public abstract class ConfigurationRoot {
}
@@ -1,17 +0,0 @@
package cc.carm.lib.configuration.core.annotation;
import org.jetbrains.annotations.NotNull;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ConfigComment {
@NotNull
String[] value() default "";
}
@@ -1,34 +0,0 @@
package cc.carm.lib.configuration.core.annotation;
import cc.carm.lib.configuration.core.ConfigInitializer;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 用于标记对应类或参数的配置路径
*/
@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ConfigPath {
/**
* 指定路径的值。
* 若不指定,则会通过 {@link ConfigInitializer#getSectionName(String)}自动生成当前路径的值。
*
* @return 路径的值
*/
String value() default "";
/**
* 是否从根节点开始。
* <br>若为 false,则会自动添加上一个路径(如果有)到本节点的路径。
* <br>若为 true,则会从根节点开始直接设置本路径。
*
* @return 是否不继承上一路径,直接从根路径为开始
*/
boolean root() default false;
}
@@ -1,42 +0,0 @@
package cc.carm.lib.configuration.core.builder;
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
import cc.carm.lib.configuration.core.value.ConfigValue;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class AbstractConfigBuilder<B extends AbstractConfigBuilder<B, T>, T> {
protected @Nullable ConfigurationProvider provider;
protected @Nullable String path;
protected @NotNull String[] comments = new String[0];
protected @Nullable T defaultValue;
protected abstract @NotNull B getThis();
public abstract @NotNull ConfigValue<?> build();
public @NotNull B from(@Nullable ConfigurationProvider provider) {
this.provider = provider;
return getThis();
}
public @NotNull B path(@Nullable String path) {
this.path = path;
return getThis();
}
public @NotNull B comments(@NotNull String... comments) {
this.comments = comments;
return getThis();
}
public @NotNull B defaults(@Nullable T defaultValue) {
this.defaultValue = defaultValue;
return getThis();
}
}
@@ -1,42 +0,0 @@
package cc.carm.lib.configuration.core.builder;
import cc.carm.lib.configuration.core.builder.list.ConfigListBuilder;
import cc.carm.lib.configuration.core.builder.map.ConfigMapBuilder;
import cc.carm.lib.configuration.core.builder.value.ConfigValueBuilder;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.TreeMap;
public class ConfigBuilder {
public <V> @NotNull ConfigValueBuilder<V> asValue(@NotNull Class<V> valueClass) {
return new ConfigValueBuilder<>(valueClass);
}
public <V> @NotNull ConfigListBuilder<V> asList(@NotNull Class<V> valueClass) {
return new ConfigListBuilder<>(valueClass);
}
public <K, V> @NotNull ConfigMapBuilder<LinkedHashMap<K, V>, K, V> asMap(@NotNull Class<K> keyClass,
@NotNull Class<V> valueClass) {
return new ConfigMapBuilder<>(LinkedHashMap::new, keyClass, valueClass);
}
public <K, V> @NotNull ConfigMapBuilder<HashMap<K, V>, K, V> asHashMap(@NotNull Class<K> keyClass,
@NotNull Class<V> valueClass) {
return asMap(keyClass, valueClass).supplier(HashMap::new);
}
public <K, V> @NotNull ConfigMapBuilder<LinkedHashMap<K, V>, K, V> asLinkedMap(@NotNull Class<K> keyClass,
@NotNull Class<V> valueClass) {
return asMap(keyClass, valueClass);
}
public <K extends Comparable<K>, V> @NotNull ConfigMapBuilder<TreeMap<K, V>, K, V> asTreeMap(@NotNull Class<K> keyClass,
@NotNull Class<V> valueClass) {
return asMap(keyClass, valueClass).supplier(TreeMap::new);
}
}
@@ -1,46 +0,0 @@
package cc.carm.lib.configuration.core.builder.list;
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
import org.jetbrains.annotations.NotNull;
public class ConfigListBuilder<V> {
protected final @NotNull Class<V> valueClass;
public ConfigListBuilder(@NotNull Class<V> valueClass) {
this.valueClass = valueClass;
}
public @NotNull <S> SourceListBuilder<S, V> from(@NotNull Class<S> sourceClass,
@NotNull ConfigDataFunction<Object, S> sourceParser,
@NotNull ConfigDataFunction<S, V> valueParser,
@NotNull ConfigDataFunction<V, S> valueSerializer,
@NotNull ConfigDataFunction<S, Object> sourceSerializer) {
return new SourceListBuilder<>(sourceClass, sourceParser, this.valueClass, valueParser, valueSerializer, sourceSerializer);
}
public @NotNull <S> SourceListBuilder<S, V> from(Class<S> sourceClass) {
return from(sourceClass,
ConfigDataFunction.required(), ConfigDataFunction.required(),
ConfigDataFunction.required(), ConfigDataFunction.required()
);
}
public @NotNull SourceListBuilder<Object, V> fromObject() {
return from(
Object.class, ConfigDataFunction.identity(),
ConfigDataFunction.castObject(valueClass),
ConfigDataFunction.identity(), ConfigDataFunction.toObject()
);
}
public @NotNull SourceListBuilder<String, V> fromString() {
return from(
String.class, ConfigDataFunction.castToString(),
ConfigDataFunction.castFromString(this.valueClass),
ConfigDataFunction.castToString(), ConfigDataFunction.toObject()
);
}
}
@@ -1,70 +0,0 @@
package cc.carm.lib.configuration.core.builder.list;
import cc.carm.lib.configuration.core.builder.AbstractConfigBuilder;
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
import cc.carm.lib.configuration.core.value.type.ConfiguredList;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class SourceListBuilder<S, V>
extends AbstractConfigBuilder<SourceListBuilder<S, V>, List<V>> {
protected final @NotNull Class<S> sourceClass;
protected @NotNull ConfigDataFunction<Object, S> sourceParser;
protected final @NotNull Class<V> valueClass;
protected @NotNull ConfigDataFunction<S, V> valueParser;
protected @NotNull ConfigDataFunction<V, S> valueSerializer;
protected @NotNull ConfigDataFunction<S, Object> sourceSerializer;
public SourceListBuilder(@NotNull Class<S> sourceClass, @NotNull ConfigDataFunction<Object, S> sourceParser,
@NotNull Class<V> valueClass, @NotNull ConfigDataFunction<S, V> valueParser,
@NotNull ConfigDataFunction<V, S> valueSerializer,
@NotNull ConfigDataFunction<S, Object> sourceSerializer) {
this.sourceClass = sourceClass;
this.sourceParser = sourceParser;
this.sourceSerializer = sourceSerializer;
this.valueClass = valueClass;
this.valueParser = valueParser;
this.valueSerializer = valueSerializer;
}
public @NotNull SourceListBuilder<S, V> parseSource(ConfigDataFunction<Object, S> sourceParser) {
this.sourceParser = sourceParser;
return this;
}
public @NotNull SourceListBuilder<S, V> parseValue(ConfigDataFunction<S, V> valueParser) {
this.valueParser = valueParser;
return this;
}
public @NotNull SourceListBuilder<S, V> serializeValue(ConfigDataFunction<V, S> serializer) {
this.valueSerializer = serializer;
return this;
}
public @NotNull SourceListBuilder<S, V> serializeSource(ConfigDataFunction<S, Object> serializer) {
this.sourceSerializer = serializer;
return this;
}
@Override
protected @NotNull SourceListBuilder<S, V> getThis() {
return this;
}
@Override
public @NotNull ConfiguredList<V> build() {
return new ConfiguredList<>(
this.provider, this.path, this.comments,
this.valueClass, this.defaultValue,
this.sourceParser.andThen(this.valueParser),
this.valueSerializer.andThen(sourceSerializer)
);
}
}
@@ -1,60 +0,0 @@
package cc.carm.lib.configuration.core.builder.map;
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
import java.util.function.Supplier;
public class ConfigMapBuilder<M extends Map<K, V>, K, V> {
protected final @NotNull Supplier<@NotNull M> supplier;
protected final @NotNull Class<K> keyClass;
protected final @NotNull Class<V> valueClass;
public ConfigMapBuilder(@NotNull Supplier<@NotNull M> supplier, @NotNull Class<K> keyClass, @NotNull Class<V> valueClass) {
this.supplier = supplier;
this.keyClass = keyClass;
this.valueClass = valueClass;
}
public <MAP extends Map<K, V>> ConfigMapBuilder<MAP, K, V> supplier(@NotNull Supplier<MAP> supplier) {
return new ConfigMapBuilder<>(supplier, keyClass, valueClass);
}
public <S> SourceMapBuilder<M, S, K, V> from(@NotNull Class<S> sourceClass,
@NotNull ConfigDataFunction<S, V> valueParser,
@NotNull ConfigDataFunction<V, S> valueSerializer) {
return new SourceMapBuilder<>(supplier,
keyClass, ConfigDataFunction.castFromString(this.keyClass), // #String -> key
sourceClass, ConfigDataFunction.castObject(sourceClass), // #Object -> source
valueClass, valueParser, // source -> value
ConfigDataFunction.castToString(), // key -> #String
valueSerializer/*value -> source*/,
ConfigDataFunction.toObject()/* source -> #Object */
);
}
public <S> SourceMapBuilder<M, S, K, V> from(@NotNull Class<S> sourceClass) {
return from(sourceClass, ConfigDataFunction.required(), ConfigDataFunction.required());
}
public SourceMapBuilder<M, String, K, V> fromString(@NotNull ConfigDataFunction<String, V> valueParser) {
return from(String.class, valueParser, ConfigDataFunction.castToString());
}
public SourceMapBuilder<M, String, K, V> fromString() {
return fromString(ConfigDataFunction.castFromString(this.valueClass));
}
public SourceMapBuilder<M, Object, K, V> fromObject(@NotNull ConfigDataFunction<Object, V> valueParser) {
return from(Object.class, valueParser, ConfigDataFunction.toObject());
}
public SourceMapBuilder<M, Object, K, V> fromObject() {
return fromObject(ConfigDataFunction.required());
}
}
@@ -1,101 +0,0 @@
package cc.carm.lib.configuration.core.builder.map;
import cc.carm.lib.configuration.core.builder.AbstractConfigBuilder;
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
import cc.carm.lib.configuration.core.value.type.ConfiguredMap;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
import java.util.function.Supplier;
public class SourceMapBuilder<M extends Map<K, V>, S, K, V>
extends AbstractConfigBuilder<SourceMapBuilder<M, S, K, V>, M> {
protected final @NotNull Supplier<@NotNull M> supplier;
protected final @NotNull Class<K> keyClass;
protected @NotNull ConfigDataFunction<String, K> keyParser;
protected final @NotNull Class<S> sourceClass;
protected @NotNull ConfigDataFunction<Object, S> sourceParser;
protected final @NotNull Class<V> valueClass;
protected @NotNull ConfigDataFunction<S, V> valueParser;
protected @NotNull ConfigDataFunction<K, String> keySerializer;
protected @NotNull ConfigDataFunction<V, S> valueSerializer;
protected @NotNull ConfigDataFunction<S, Object> sourceSerializer;
public SourceMapBuilder(@NotNull Supplier<@NotNull M> supplier,
@NotNull Class<K> keyClass, @NotNull ConfigDataFunction<String, K> keyParser,
@NotNull Class<S> sourceClass, @NotNull ConfigDataFunction<Object, S> sourceParser,
@NotNull Class<V> valueClass, @NotNull ConfigDataFunction<S, V> valueParser,
@NotNull ConfigDataFunction<K, String> keySerializer,
@NotNull ConfigDataFunction<V, S> valueSerializer,
@NotNull ConfigDataFunction<S, Object> sourceSerializer) {
this.supplier = supplier;
this.keyClass = keyClass;
this.keyParser = keyParser;
this.valueClass = valueClass;
this.valueParser = valueParser;
this.sourceClass = sourceClass;
this.sourceParser = sourceParser;
this.keySerializer = keySerializer;
this.valueSerializer = valueSerializer;
this.sourceSerializer = sourceSerializer;
}
public <MAP extends Map<K, V>> SourceMapBuilder<MAP, S, K, V> supplier(@NotNull Supplier<MAP> supplier) {
return new SourceMapBuilder<>(supplier,
keyClass, keyParser, sourceClass, sourceParser, valueClass, valueParser,
keySerializer, valueSerializer, sourceSerializer
);
}
public @NotNull SourceMapBuilder<M, S, K, V> parseKey(@NotNull ConfigDataFunction<String, K> parser) {
this.keyParser = parser;
return this;
}
public @NotNull SourceMapBuilder<M, S, K, V> parseSource(@NotNull ConfigDataFunction<Object, S> parser) {
this.sourceParser = parser;
return this;
}
public @NotNull SourceMapBuilder<M, S, K, V> parseValue(@NotNull ConfigDataFunction<S, V> parser) {
this.valueParser = parser;
return this;
}
public @NotNull SourceMapBuilder<M, S, K, V> serializeKey(@NotNull ConfigDataFunction<K, String> serializer) {
this.keySerializer = serializer;
return this;
}
public @NotNull SourceMapBuilder<M, S, K, V> serializeValue(@NotNull ConfigDataFunction<V, S> serializer) {
this.valueSerializer = serializer;
return this;
}
public @NotNull SourceMapBuilder<M, S, K, V> serializeSource(@NotNull ConfigDataFunction<S, Object> serializer) {
this.sourceSerializer = serializer;
return this;
}
@Override
protected @NotNull SourceMapBuilder<M, S, K, V> getThis() {
return this;
}
@Override
public @NotNull ConfiguredMap<K, V> build() {
return new ConfiguredMap<>(
this.provider, this.path, this.comments,
this.defaultValue, this.supplier,
this.keyClass, this.keyParser,
this.valueClass, this.sourceParser.andThen(this.valueParser),
this.keySerializer, this.valueSerializer.andThen(this.sourceSerializer)
);
}
}
@@ -1,61 +0,0 @@
package cc.carm.lib.configuration.core.builder.value;
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
import cc.carm.lib.configuration.core.function.ConfigValueParser;
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
public class ConfigValueBuilder<V> {
protected final @NotNull Class<V> valueClass;
public ConfigValueBuilder(@NotNull Class<V> valueClass) {
this.valueClass = valueClass;
}
public @NotNull SectionValueBuilder<V> fromSection() {
return fromSection(ConfigValueParser.required(), ConfigDataFunction.required());
}
public @NotNull SectionValueBuilder<V> fromSection(@NotNull ConfigValueParser<ConfigurationWrapper, V> valueParser,
@NotNull ConfigDataFunction<V, ? extends Map<String, Object>> valueSerializer) {
return new SectionValueBuilder<>(this.valueClass, valueParser, valueSerializer);
}
public @NotNull <S> SourceValueBuilder<S, V> from(Class<S> sourceClass) {
return from(
sourceClass, ConfigDataFunction.required(), ConfigValueParser.required(),
ConfigDataFunction.required(), ConfigDataFunction.required()
);
}
public @NotNull <S> SourceValueBuilder<S, V> from(@NotNull Class<S> sourceClass,
@NotNull ConfigDataFunction<Object, S> sourceParser,
@NotNull ConfigValueParser<S, V> valueParser,
@NotNull ConfigDataFunction<V, S> valueSerializer,
@NotNull ConfigDataFunction<S, Object> sourceSerializer) {
return new SourceValueBuilder<>(
sourceClass, sourceParser, this.valueClass, valueParser,
valueSerializer, sourceSerializer
);
}
public @NotNull SourceValueBuilder<Object, V> fromObject() {
return from(
Object.class, ConfigDataFunction.identity(),
ConfigValueParser.castObject(valueClass),
ConfigDataFunction.identity(), ConfigDataFunction.toObject()
);
}
public @NotNull SourceValueBuilder<String, V> fromString() {
return from(
String.class, ConfigDataFunction.castToString(),
ConfigValueParser.parseString(this.valueClass),
ConfigDataFunction.castToString(), ConfigDataFunction.toObject()
);
}
}
@@ -1,54 +0,0 @@
package cc.carm.lib.configuration.core.builder.value;
import cc.carm.lib.configuration.core.builder.AbstractConfigBuilder;
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
import cc.carm.lib.configuration.core.function.ConfigValueParser;
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
import cc.carm.lib.configuration.core.value.type.ConfiguredSection;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
public class SectionValueBuilder<V>
extends AbstractConfigBuilder<SectionValueBuilder<V>, V> {
protected final @NotNull Class<V> valueClass;
protected @NotNull ConfigValueParser<ConfigurationWrapper, V> parser;
protected @NotNull ConfigDataFunction<V, ? extends Map<String, Object>> serializer;
public SectionValueBuilder(@NotNull Class<V> valueClass,
@NotNull ConfigValueParser<ConfigurationWrapper, V> parser,
@NotNull ConfigDataFunction<V, ? extends Map<String, Object>> serializer) {
this.valueClass = valueClass;
this.parser = parser;
this.serializer = serializer;
}
@Override
protected @NotNull SectionValueBuilder<V> getThis() {
return this;
}
public @NotNull SectionValueBuilder<V> parseValue(ConfigValueParser<ConfigurationWrapper, V> valueParser) {
this.parser = valueParser;
return this;
}
public @NotNull SectionValueBuilder<V> serializeValue(ConfigDataFunction<V, ? extends Map<String, Object>> serializer) {
this.serializer = serializer;
return this;
}
@Override
public @NotNull ConfiguredSection<V> build() {
return new ConfiguredSection<>(
this.provider, this.path, this.comments,
this.valueClass, this.defaultValue,
this.parser, this.serializer
);
}
}
@@ -1,67 +0,0 @@
package cc.carm.lib.configuration.core.builder.value;
import cc.carm.lib.configuration.core.builder.AbstractConfigBuilder;
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
import cc.carm.lib.configuration.core.function.ConfigValueParser;
import cc.carm.lib.configuration.core.value.type.ConfiguredValue;
import org.jetbrains.annotations.NotNull;
public class SourceValueBuilder<S, V> extends AbstractConfigBuilder<SourceValueBuilder<S, V>, V> {
protected final @NotNull Class<S> sourceClass;
protected @NotNull ConfigDataFunction<Object, S> sourceParser;
protected final @NotNull Class<V> valueClass;
protected @NotNull ConfigValueParser<S, V> valueParser;
protected @NotNull ConfigDataFunction<S, Object> sourceSerializer;
protected @NotNull ConfigDataFunction<V, S> valueSerializer;
public SourceValueBuilder(@NotNull Class<S> sourceClass, @NotNull ConfigDataFunction<Object, S> sourceParser,
@NotNull Class<V> valueClass, @NotNull ConfigValueParser<S, V> valueParser,
@NotNull ConfigDataFunction<V, S> valueSerializer,
@NotNull ConfigDataFunction<S, Object> sourceSerializer) {
this.sourceClass = sourceClass;
this.sourceParser = sourceParser;
this.valueClass = valueClass;
this.valueParser = valueParser;
this.sourceSerializer = sourceSerializer;
this.valueSerializer = valueSerializer;
}
@Override
protected @NotNull SourceValueBuilder<S, V> getThis() {
return this;
}
public @NotNull SourceValueBuilder<S, V> parseSource(@NotNull ConfigDataFunction<Object, S> sourceParser) {
this.sourceParser = sourceParser;
return this;
}
public @NotNull SourceValueBuilder<S, V> parseValue(@NotNull ConfigValueParser<S, V> valueParser) {
this.valueParser = valueParser;
return this;
}
public @NotNull SourceValueBuilder<S, V> serializeValue(@NotNull ConfigDataFunction<V, S> serializer) {
this.valueSerializer = serializer;
return this;
}
public @NotNull SourceValueBuilder<S, V> serializeSource(@NotNull ConfigDataFunction<S, Object> serializer) {
this.sourceSerializer = serializer;
return this;
}
@Override
public @NotNull ConfiguredValue<V> build() {
return new ConfiguredValue<>(
this.provider, this.path, this.comments,
this.valueClass, this.defaultValue,
this.valueParser.compose(this.sourceParser),
this.valueSerializer.andThen(sourceSerializer)
);
}
}
@@ -1,64 +0,0 @@
package cc.carm.lib.configuration.core.function;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
@FunctionalInterface
public interface ConfigDataFunction<T, R> {
@NotNull R parse(@NotNull T data) throws Exception;
default <V> @NotNull ConfigDataFunction<T, V> andThen(@NotNull ConfigDataFunction<? super R, V> after) {
Objects.requireNonNull(after);
return ((data) -> after.parse(parse(data)));
}
@Contract(pure = true)
static <T> @NotNull ConfigDataFunction<T, ? super T> identity() {
return (input) -> input;
}
@Contract(pure = true)
static <T, V> @NotNull ConfigDataFunction<T, V> required() {
return (input) -> {
throw new IllegalArgumentException("Please specify the value parser.");
};
}
@Contract(pure = true)
static <T> @NotNull ConfigDataFunction<T, Object> toObject() {
return (input) -> input;
}
@Contract(pure = true)
static <V> @NotNull ConfigDataFunction<Object, V> castObject(Class<V> valueClass) {
return (input) -> {
if (valueClass.isInstance(input)) return valueClass.cast(input);
else throw new IllegalArgumentException("Cannot cast value to " + valueClass.getName());
};
}
@Contract(pure = true)
static <V> @NotNull ConfigDataFunction<String, V> castFromString(Class<V> valueClass) {
return (input) -> {
if (valueClass.isInstance(input)) return valueClass.cast(input);
else throw new IllegalArgumentException("Cannot cast string to " + valueClass.getName());
};
}
@Contract(pure = true)
static <T> @NotNull ConfigDataFunction<T, String> castToString() {
return (input) -> {
if (input instanceof String) return (String) input;
else return input.toString();
};
}
}
@@ -1,38 +0,0 @@
package cc.carm.lib.configuration.core.source;
import cc.carm.lib.configuration.core.ConfigInitializer;
import cc.carm.lib.configuration.core.ConfigurationRoot;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class ConfigurationProvider {
protected long updateTime;
public ConfigurationProvider() {
this.updateTime = System.currentTimeMillis();
}
public long getUpdateTime() {
return updateTime;
}
public boolean isExpired(long time) {
return this.updateTime > time;
}
public abstract @NotNull ConfigurationWrapper getConfiguration();
public abstract void reload() throws Exception;
public abstract void save() throws Exception;
public abstract void setComments(@NotNull String path, @NotNull String... comments);
public abstract @Nullable String[] getComments(@NotNull String path);
public void initialize(Class<? extends ConfigurationRoot> configClazz) {
ConfigInitializer.initialize(this, configClazz, true);
}
}
@@ -1,144 +0,0 @@
package cc.carm.lib.configuration.core.source;
import cc.carm.lib.configuration.core.function.ConfigValueParser;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
interface ConfigurationReader {
ConfigurationWrapper getWrapper();
default boolean isBoolean(@NotNull String path) {
return getWrapper().isType(path, Boolean.class);
}
default boolean getBoolean(@NotNull String path) {
return getBoolean(path, false);
}
@Contract("_, !null -> !null")
default @Nullable Boolean getBoolean(@NotNull String path, @Nullable Boolean def) {
return getWrapper().get(path, def, ConfigValueParser.booleanValue());
}
default @Nullable Boolean isByte(@NotNull String path) {
return getWrapper().isType(path, Byte.class);
}
default @Nullable Byte getByte(@NotNull String path) {
return getByte(path, (byte) 0);
}
@Contract("_, !null -> !null")
default @Nullable Byte getByte(@NotNull String path, @Nullable Byte def) {
return getWrapper().get(path, def, ConfigValueParser.byteValue());
}
default boolean isShort(@NotNull String path) {
return getWrapper().isType(path, Short.class);
}
default @Nullable Short getShort(@NotNull String path) {
return getShort(path, (short) 0);
}
@Contract("_, !null -> !null")
default @Nullable Short getShort(@NotNull String path, @Nullable Short def) {
return getWrapper().get(path, def, ConfigValueParser.shortValue());
}
default boolean isInt(@NotNull String path) {
return getWrapper().isType(path, Integer.class);
}
default @Nullable Integer getInt(@NotNull String path) {
return getInt(path, 0);
}
@Contract("_, !null -> !null")
default @Nullable Integer getInt(@NotNull String path, @Nullable Integer def) {
return getWrapper().get(path, def, ConfigValueParser.intValue());
}
default boolean isLong(@NotNull String path) {
return getWrapper().isType(path, Long.class);
}
default @Nullable Long getLong(@NotNull String path) {
return getLong(path, 0L);
}
@Contract("_, !null -> !null")
default @Nullable Long getLong(@NotNull String path, @Nullable Long def) {
return getWrapper().get(path, def, ConfigValueParser.longValue());
}
default boolean isFloat(@NotNull String path) {
return getWrapper().isType(path, Float.class);
}
default @Nullable Float getFloat(@NotNull String path) {
return getFloat(path, 0.0F);
}
@Contract("_, !null -> !null")
default @Nullable Float getFloat(@NotNull String path, @Nullable Float def) {
return getWrapper().get(path, def, ConfigValueParser.floatValue());
}
default boolean isDouble(@NotNull String path) {
return getWrapper().isType(path, Double.class);
}
default @Nullable Double getDouble(@NotNull String path) {
return getDouble(path, 0.0D);
}
@Contract("_, !null -> !null")
default @Nullable Double getDouble(@NotNull String path, @Nullable Double def) {
return getWrapper().get(path, def, ConfigValueParser.doubleValue());
}
default boolean isChar(@NotNull String path) {
return getWrapper().isType(path, Boolean.class);
}
default @Nullable Character getChar(@NotNull String path) {
return getChar(path, null);
}
@Contract("_, !null -> !null")
default @Nullable Character getChar(@NotNull String path, @Nullable Character def) {
return getWrapper().get(path, def, Character.class);
}
default boolean isString(@NotNull String path) {
return getWrapper().isType(path, String.class);
}
default @Nullable String getString(@NotNull String path) {
return getString(path, null);
}
@Contract("_, !null -> !null")
default @Nullable String getString(@NotNull String path, @Nullable String def) {
return getWrapper().get(path, def, String.class);
}
}
@@ -1,72 +0,0 @@
package cc.carm.lib.configuration.core.source;
import cc.carm.lib.configuration.core.function.ConfigValueParser;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Map;
import java.util.Set;
public interface ConfigurationWrapper extends ConfigurationReader{
@Override
default ConfigurationWrapper getWrapper() {
return this;
}
@NotNull
Set<String> getKeys(boolean deep);
@NotNull
Map<String, Object> getValues(boolean deep);
void set(@NotNull String path, @Nullable Object value);
boolean contains(@NotNull String path);
default <T> boolean isType(@NotNull String path, @NotNull Class<T> typeClass) {
return typeClass.isInstance(get(path));
}
@Nullable Object get(@NotNull String path);
default @Nullable <T> T get(@NotNull String path, @NotNull Class<T> clazz) {
return get(path, null, clazz);
}
default @Nullable <T> T get(@NotNull String path, @NotNull ConfigValueParser<Object, T> parser) {
return get(path, null, parser);
}
@Contract("_,!null,_->!null")
default @Nullable <T> T get(@NotNull String path, @Nullable T defaultValue, @NotNull Class<T> clazz) {
return get(path, defaultValue, ConfigValueParser.castObject(clazz));
}
@Contract("_,!null,_->!null")
default @Nullable <T> T get(@NotNull String path, @Nullable T defaultValue,
@NotNull ConfigValueParser<Object, T> parser) {
Object value = get(path);
if (value != null) {
try {
return parser.parse(value, defaultValue);
} catch (Exception e) {
e.printStackTrace();
}
}
return defaultValue;
}
boolean isList(@NotNull String path);
@Nullable List<?> getList(@NotNull String path);
boolean isConfigurationSection(@NotNull String path);
@Nullable
ConfigurationWrapper getConfigurationSection(@NotNull String path);
}
@@ -1,88 +0,0 @@
package cc.carm.lib.configuration.core.source.impl;
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.Objects;
public abstract class FileConfigProvider extends ConfigurationProvider {
protected final @NotNull File file;
public FileConfigProvider(@NotNull File file) {
this.file = file;
}
public @NotNull File getFile() {
return file;
}
public void initializeFile(@Nullable String sourcePath) throws IOException {
if (this.file.exists()) return;
File parent = this.file.getParentFile();
if (parent != null && !parent.exists() && !parent.mkdirs()) {
throw new IOException("Failed to create directory " + file.getParentFile().getAbsolutePath());
}
if (!this.file.createNewFile()) {
throw new IOException("Failed to create file " + file.getAbsolutePath());
}
if (sourcePath != null) {
try {
saveResource(sourcePath, true);
} catch (Exception ignored) {
}
}
}
public void saveResource(@NotNull String resourcePath, boolean replace)
throws NullPointerException, IOException, IllegalArgumentException {
Objects.requireNonNull(resourcePath, "ResourcePath cannot be null");
if (resourcePath.equals("")) throw new IllegalArgumentException("ResourcePath cannot be empty");
resourcePath = resourcePath.replace('\\', '/');
InputStream in = getResource(resourcePath);
if (in == null) throw new IllegalArgumentException("The resource '" + resourcePath + "' not exists");
int lastIndex = resourcePath.lastIndexOf('/');
File outDir = new File(file, resourcePath.substring(0, Math.max(lastIndex, 0)));
if (!outDir.exists() && !outDir.mkdirs()) throw new IOException("Failed to create directory " + outDir);
if (!file.exists() || replace) {
try {
OutputStream out = new FileOutputStream(file);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
out.close();
in.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
@Nullable
public InputStream getResource(@NotNull String filename) {
try {
URL url = this.getClass().getClassLoader().getResource(filename);
if (url == null) return null;
URLConnection connection = url.openConnection();
connection.setUseCaches(false);
return connection.getInputStream();
} catch (IOException ex) {
return null;
}
}
}
@@ -1,67 +0,0 @@
package cc.carm.lib.configuration.core.util;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
public class MapFactory<S extends Map<K, V>, K, V> {
private final S map;
protected MapFactory(S map) {
this.map = map;
}
public MapFactory<S, K, V> put(K key, V value) {
this.map.put(key, value);
return this;
}
public MapFactory<S, K, V> remove(K key) {
this.map.remove(key);
return this;
}
public MapFactory<S, K, V> clear() {
this.map.clear();
return this;
}
public S build() {
return get();
}
public S get() {
return map;
}
public static <K, V> MapFactory<HashMap<K, V>, K, V> hashMap() {
return new MapFactory<>(new HashMap<>());
}
public static <K, V> MapFactory<HashMap<K, V>, K, V> hashMap(K firstKey, V firstValue) {
return MapFactory.<K, V>hashMap().put(firstKey, firstValue);
}
public static <K, V> MapFactory<LinkedHashMap<K, V>, K, V> linkedMap() {
return of(new LinkedHashMap<>());
}
public static <K, V> MapFactory<LinkedHashMap<K, V>, K, V> linkedMap(K firstKey, V firstValue) {
return MapFactory.<K, V>linkedMap().put(firstKey, firstValue);
}
public static <K extends Comparable<K>, V> MapFactory<TreeMap<K, V>, K, V> treeMap() {
return of(new TreeMap<>());
}
public static <K extends Comparable<K>, V> MapFactory<TreeMap<K, V>, K, V> treeMap(K firstKey, V firstValue) {
return MapFactory.<K, V>treeMap().put(firstKey, firstValue);
}
public static <M extends Map<K, V>, K, V> MapFactory<M, K, V> of(M map) {
return new MapFactory<>(map);
}
}
@@ -1,40 +0,0 @@
package cc.carm.lib.configuration.core.value;
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class CachedConfigValue<T> extends ConfigValue<T> {
protected @Nullable T cachedValue;
protected long parsedTime = -1;
public CachedConfigValue(@Nullable ConfigurationProvider provider, @Nullable String sectionPath,
@NotNull String[] comments, @Nullable T defaultValue) {
super(provider, sectionPath, comments, defaultValue);
}
protected T updateCache(T value) {
this.parsedTime = System.currentTimeMillis();
this.cachedValue = value;
return getCachedValue();
}
public @Nullable T getCachedValue() {
return cachedValue;
}
public boolean isExpired() {
return this.parsedTime <= 0 || getProvider().isExpired(this.parsedTime);
}
protected final T useDefault() {
return useOrDefault(null);
}
protected final T useOrDefault(@Nullable T value) {
return updateCache(this.defaultValue == null ? value : this.defaultValue);
}
}
@@ -1,105 +0,0 @@
package cc.carm.lib.configuration.core.value;
import cc.carm.lib.configuration.core.builder.ConfigBuilder;
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
import java.util.Optional;
public abstract class ConfigValue<T> {
public static @NotNull ConfigBuilder builder() {
return new ConfigBuilder();
}
protected @Nullable T defaultValue;
protected @Nullable ConfigurationProvider provider;
protected @Nullable String configPath;
protected @NotNull String[] comments;
public ConfigValue(@Nullable ConfigurationProvider provider, @Nullable String configPath,
@NotNull String[] comments, @Nullable T defaultValue) {
this.provider = provider;
this.configPath = configPath;
this.comments = comments;
this.defaultValue = defaultValue;
}
public void initialize(@NotNull ConfigurationProvider provider, @NotNull String configPath,
@NotNull String... comments) {
if (this.provider == null) this.provider = provider;
if (this.configPath == null) this.configPath = configPath;
if (this.comments.length == 0) this.comments = comments;
this.provider.setComments(this.configPath, this.comments);
get();
}
public @Nullable T getDefaultValue() {
return defaultValue;
}
public void setDefaultValue(@Nullable T defaultValue) {
this.defaultValue = defaultValue;
}
public abstract @Nullable T get();
public @Nullable T getOrDefault() {
return Optional.ofNullable(get()).orElse(getDefaultValue());
}
public @NotNull T getNotNull() {
return Objects.requireNonNull(getOrDefault(), "Value(" + configPath + ") is null.");
}
public @NotNull Optional<@Nullable T> getOptional() {
return Optional.ofNullable(get());
}
public abstract void set(@Nullable T value);
public void setDefault() {
Optional.ofNullable(getDefaultValue()).ifPresent(this::set);
}
public @NotNull ConfigurationProvider getProvider() {
return Optional.ofNullable(this.provider)
.orElseThrow(() -> new IllegalStateException("Value(" + configPath + ") does not have a provider."));
}
public final @NotNull ConfigurationWrapper getConfiguration() {
try {
return getProvider().getConfiguration();
} catch (Exception ex) {
throw new IllegalStateException("Value(" + configPath + ") has not been initialized", ex);
}
}
public @NotNull String getConfigPath() {
return Optional.ofNullable(this.configPath)
.orElseThrow(() -> new IllegalStateException("No section path provided."));
}
protected Object getValue() {
return getConfiguration().get(getConfigPath());
}
protected void setValue(@Nullable Object value) {
getConfiguration().set(getConfigPath(), value);
}
public String[] getComments() {
return comments;
}
public void setComments(String[] comments) {
this.comments = comments;
}
}
@@ -1,77 +0,0 @@
package cc.carm.lib.configuration.core.value.type;
import cc.carm.lib.configuration.core.builder.list.ConfigListBuilder;
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
import cc.carm.lib.configuration.core.value.CachedConfigValue;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
public class ConfiguredList<V> extends CachedConfigValue<List<V>> {
public static <V> @NotNull ConfigListBuilder<V> builder(@NotNull Class<V> valueClass) {
return builder().asList(valueClass);
}
protected final @NotNull Class<V> valueClass;
protected final @NotNull ConfigDataFunction<Object, V> parser;
protected final @NotNull ConfigDataFunction<V, Object> serializer;
public ConfiguredList(@Nullable ConfigurationProvider provider,
@Nullable String sectionPath, @NotNull String[] comments,
@NotNull Class<V> valueClass, @Nullable List<V> defaultValue,
@NotNull ConfigDataFunction<Object, V> parser,
@NotNull ConfigDataFunction<V, Object> serializer) {
super(provider, sectionPath, comments, defaultValue);
this.valueClass = valueClass;
this.parser = parser;
this.serializer = serializer;
}
@Override
public @NotNull List<V> get() {
if (isExpired()) { // 已过时的数据,需要重新解析一次。
List<V> list = new ArrayList<>();
List<?> data = getConfiguration().getList(getConfigPath());
if (data == null || data.isEmpty()) return useOrDefault(list);
for (Object dataVal : data) {
if (dataVal == null) continue;
try {
list.add(parser.parse(dataVal));
} catch (Exception e) {
e.printStackTrace();
}
}
return updateCache(list);
} else if (getCachedValue() != null) return getCachedValue();
else if (getDefaultValue() != null) return getDefaultValue();
else return new ArrayList<>();
}
@Override
public void set(@Nullable List<V> value) {
updateCache(value);
if (value == null) setValue(null);
else {
List<Object> data = new ArrayList<>();
for (V val : value) {
if (val == null) continue;
try {
data.add(serializer.parse(val));
} catch (Exception ex) {
ex.printStackTrace();
}
}
setValue(data);
}
}
}
@@ -1,125 +0,0 @@
package cc.carm.lib.configuration.core.value.type;
import cc.carm.lib.configuration.core.builder.ConfigBuilder;
import cc.carm.lib.configuration.core.builder.map.ConfigMapBuilder;
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
import cc.carm.lib.configuration.core.value.CachedConfigValue;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> {
public static <K, V> @NotNull ConfigMapBuilder<LinkedHashMap<K, V>, K, V> builder(@NotNull Class<K> keyClass,
@NotNull Class<V> valueClass) {
return builder().asMap(keyClass, valueClass);
}
protected final @NotNull Supplier<? extends Map<K, V>> supplier;
protected final @NotNull Class<K> keyClass;
protected final @NotNull Class<V> valueClass;
protected final @NotNull ConfigDataFunction<String, K> keyParser;
protected final @NotNull ConfigDataFunction<Object, V> valueParser;
protected final @NotNull ConfigDataFunction<K, String> keySerializer;
protected final @NotNull ConfigDataFunction<V, Object> valueSerializer;
public ConfiguredMap(@Nullable ConfigurationProvider provider,
@Nullable String sectionPath, @NotNull String[] comments,
@Nullable Map<K, V> defaultValue, @NotNull Supplier<? extends Map<K, V>> supplier,
@NotNull Class<K> keyClass, @NotNull ConfigDataFunction<String, K> keyParser,
@NotNull Class<V> valueClass, @NotNull ConfigDataFunction<Object, V> valueParser,
@NotNull ConfigDataFunction<K, String> keySerializer,
@NotNull ConfigDataFunction<V, Object> valueSerializer) {
super(provider, sectionPath, comments, defaultValue);
this.supplier = supplier;
this.keyClass = keyClass;
this.valueClass = valueClass;
this.keyParser = keyParser;
this.valueParser = valueParser;
this.keySerializer = keySerializer;
this.valueSerializer = valueSerializer;
}
public @NotNull Class<K> getKeyClass() {
return keyClass;
}
public @NotNull Class<V> getValueClass() {
return valueClass;
}
public @NotNull ConfigDataFunction<String, K> getKeyParser() {
return keyParser;
}
public @NotNull ConfigDataFunction<Object, V> getValueParser() {
return valueParser;
}
public @NotNull ConfigDataFunction<K, String> getKeySerializer() {
return keySerializer;
}
public @NotNull ConfigDataFunction<V, Object> getValueSerializer() {
return valueSerializer;
}
@Override
public @NotNull Map<K, V> get() {
if (isExpired()) { // 已过时的数据,需要重新解析一次。
Map<K, V> map = supplier.get();
ConfigurationWrapper section = getConfiguration().getConfigurationSection(getConfigPath());
if (section == null) return useOrDefault(map);
Set<String> keys = section.getKeys(false);
if (keys.isEmpty()) return useOrDefault(map);
for (String dataKey : keys) {
Object dataVal = section.get(dataKey);
if (dataVal == null) continue;
try {
K key = keyParser.parse(dataKey);
V value = valueParser.parse(dataVal);
map.put(key, value);
} catch (Exception e) {
e.printStackTrace();
}
}
return updateCache(map);
} else if (getCachedValue() != null) return getCachedValue();
else if (getDefaultValue() != null) return getDefaultValue();
else return supplier.get();
}
@Override
public void set(Map<K, V> value) {
updateCache(value);
if (value == null) setValue(null);
else {
Map<String, Object> data = new LinkedHashMap<>();
for (Map.Entry<K, V> entry : value.entrySet()) {
try {
String key = keySerializer.parse(entry.getKey());
Object val = valueSerializer.parse(entry.getValue());
data.put(key, val);
} catch (Exception e) {
e.printStackTrace();
}
}
setValue(data);
}
}
}
@@ -1,81 +0,0 @@
package cc.carm.lib.configuration.core.value.type;
import cc.carm.lib.configuration.core.builder.ConfigBuilder;
import cc.carm.lib.configuration.core.builder.value.SectionValueBuilder;
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
import cc.carm.lib.configuration.core.function.ConfigValueParser;
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
import cc.carm.lib.configuration.core.value.CachedConfigValue;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.Optional;
public class ConfiguredSection<V> extends CachedConfigValue<V> {
public static <V> @NotNull SectionValueBuilder<V> builder(@NotNull Class<V> valueClass) {
return builder().asValue(valueClass).fromSection();
}
protected final @NotNull Class<V> valueClass;
protected final @NotNull ConfigValueParser<ConfigurationWrapper, V> parser;
protected final @NotNull ConfigDataFunction<V, ? extends Map<String, Object>> serializer;
public ConfiguredSection(@Nullable ConfigurationProvider provider,
@Nullable String sectionPath, @NotNull String[] comments,
@NotNull Class<V> valueClass, @Nullable V defaultValue,
@NotNull ConfigValueParser<ConfigurationWrapper, V> parser,
@NotNull ConfigDataFunction<V, ? extends Map<String, Object>> serializer) {
super(provider, sectionPath, comments, defaultValue);
this.valueClass = valueClass;
this.parser = parser;
this.serializer = serializer;
}
public @NotNull Class<V> getValueClass() {
return valueClass;
}
public @NotNull ConfigValueParser<ConfigurationWrapper, V> getParser() {
return parser;
}
public @NotNull ConfigDataFunction<V, ? extends Map<String, Object>> getSerializer() {
return serializer;
}
@Override
public @Nullable V get() {
if (isExpired()) { // 已过时的数据,需要重新解析一次。
ConfigurationWrapper section = getConfiguration().getConfigurationSection(getConfigPath());
if (section == null) return useDefault();
try {
// 若未出现错误,则直接更新缓存并返回。
return updateCache(this.parser.parse(section, this.defaultValue));
} catch (Exception e) {
// 出现了解析错误,提示并返回默认值。
e.printStackTrace();
return useDefault();
}
} else return Optional.ofNullable(getCachedValue()).orElse(defaultValue);
}
@Override
public void set(V value) {
updateCache(value);
if (value == null) setValue(null);
else {
try {
setValue(serializer.parse(value));
// getConfiguration().createSection(getSectionPath(), serializer.parse(value));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@@ -1,83 +0,0 @@
package cc.carm.lib.configuration.core.value.type;
import cc.carm.lib.configuration.core.builder.ConfigBuilder;
import cc.carm.lib.configuration.core.builder.value.ConfigValueBuilder;
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
import cc.carm.lib.configuration.core.function.ConfigValueParser;
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
import cc.carm.lib.configuration.core.value.CachedConfigValue;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
public class ConfiguredValue<V> extends CachedConfigValue<V> {
public static <V> ConfigValueBuilder<V> builder(Class<V> valueClass) {
return builder().asValue(valueClass);
}
public static <V> ConfiguredValue<V> of(Class<V> valueClass) {
return of(valueClass, null);
}
public static <V> ConfiguredValue<V> of(Class<V> valueClass, @Nullable V defaultValue) {
return builder(valueClass).fromObject().defaults(defaultValue).build();
}
protected final @NotNull Class<V> valueClass;
protected final @NotNull ConfigValueParser<Object, V> parser;
protected final @NotNull ConfigDataFunction<V, Object> serializer;
public ConfiguredValue(@Nullable ConfigurationProvider provider,
@Nullable String sectionPath, @NotNull String[] comments,
@NotNull Class<V> valueClass, @Nullable V defaultValue,
@NotNull ConfigValueParser<Object, V> parser,
@NotNull ConfigDataFunction<V, Object> serializer) {
super(provider, sectionPath, comments, defaultValue);
this.valueClass = valueClass;
this.parser = parser;
this.serializer = serializer;
}
public @NotNull Class<V> getValueClass() {
return valueClass;
}
public @NotNull ConfigValueParser<Object, V> getParser() {
return parser;
}
@Override
public V get() {
if (isExpired()) { // 已过时的数据,需要重新解析一次。
Object value = getConfiguration().get(getConfigPath());
if (value == null) return useDefault(); // 获取的值不存在,直接使用默认值。
try {
// 若未出现错误,则直接更新缓存并返回。
return updateCache(this.parser.parse(value, this.defaultValue));
} catch (Exception e) {
// 出现了解析错误,提示并返回默认值。
e.printStackTrace();
return useDefault();
}
} else return Optional.ofNullable(getCachedValue()).orElse(defaultValue);
}
@Override
public void set(V value) {
updateCache(value);
if (value == null) setValue(null);
else {
try {
setValue(serializer.parse(value));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@@ -0,0 +1,22 @@
package cc.carm.lib.configuration.function;
import org.jetbrains.annotations.NotNull;
@FunctionalInterface
public interface ConfigExceptionHandler {
void handle(@NotNull String path, @NotNull Throwable throwable);
static @NotNull ConfigExceptionHandler silence() {
return (path, throwable) -> {
};
}
static @NotNull ConfigExceptionHandler print() {
return (path, throwable) -> {
System.err.println("Error occurred at path: " + path);
throwable.printStackTrace();
};
}
}
@@ -0,0 +1,20 @@
package cc.carm.lib.configuration.function;
import org.jetbrains.annotations.NotNull;
import java.io.Serializable;
@FunctionalInterface
public interface DataConsumer<T> extends Serializable {
void accept(@NotNull T data) throws Exception;
default DataConsumer<T> andThen(DataConsumer<? super T> after) {
return (T t) -> {
accept(t);
after.accept(t);
};
}
}
@@ -1,87 +1,80 @@
package cc.carm.lib.configuration.core.function;
package cc.carm.lib.configuration.function;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.Serializable;
import java.util.Objects;
@FunctionalInterface
public interface ConfigValueParser<T, R> {
public interface DataFunction<T, R> extends Serializable {
@Nullable R parse(@NotNull T data, @Nullable R defaultValue) throws Exception;
@NotNull R handle(@NotNull T data) throws Exception;
default <V> ConfigValueParser<T, V> andThen(@NotNull ConfigValueParser<R, V> after) {
default <V> @NotNull DataFunction<T, V> andThen(@NotNull DataFunction<? super R, V> after) {
Objects.requireNonNull(after);
return ((data, defaultValue) -> {
R result = parse(data, null);
if (result == null) return defaultValue;
else return after.parse(result, defaultValue);
});
}
default <V> ConfigValueParser<V, R> compose(@NotNull ConfigDataFunction<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return ((data, defaultValue) -> {
T result = before.parse(data);
return parse(result, defaultValue);
});
}
@Contract(pure = true)
static <T> @NotNull ConfigValueParser<T, T> identity() {
return (input, defaultValue) -> input;
return data -> after.handle(handle(data));
}
@Contract(pure = true)
static <T> @NotNull ConfigValueParser<T, Object> toObject() {
return (input, defaultValue) -> input;
static <T> @NotNull DataFunction<T, T> identity() {
return input -> input;
}
@Contract(pure = true)
static <T, V> @NotNull ConfigValueParser<T, V> required() {
return (input, defaultValue) -> {
static <T> @NotNull DataFunction<T, T> identity(Class<T> type) {
return input -> input;
}
@Contract(pure = true)
static <T, V> @NotNull DataFunction<T, V> required() {
return input -> {
throw new IllegalArgumentException("Please specify the value parser.");
};
}
@Contract(pure = true)
static <V> @NotNull ConfigValueParser<Object, V> castObject(Class<V> valueClass) {
return (input, defaultValue) -> {
static <T> @NotNull DataFunction<T, Object> toObject() {
return input -> input;
}
@Contract(pure = true)
static <V> @NotNull DataFunction<Object, V> castObject(Class<V> valueClass) {
return input -> {
if (valueClass.isInstance(input)) return valueClass.cast(input);
else throw new IllegalArgumentException("Cannot cast value to " + valueClass.getName());
};
}
@Contract(pure = true)
static <V> @NotNull ConfigValueParser<String, V> parseString(Class<V> valueClass) {
return (input, defaultValue) -> {
static <V> @NotNull DataFunction<String, V> castFromString(Class<V> valueClass) {
return input -> {
if (valueClass.isInstance(input)) return valueClass.cast(input);
else throw new IllegalArgumentException("Cannot cast string to " + valueClass.getName());
};
}
@Contract(pure = true)
static @NotNull ConfigValueParser<Object, String> castToString() {
return (input, defaultValue) -> {
static <T> @NotNull DataFunction<T, String> castToString() {
return input -> {
if (input instanceof String) return (String) input;
else if (input instanceof Enum<?>) return ((Enum<?>) input).name();
else return input.toString();
};
}
@Contract(pure = true)
static @NotNull <T> ConfigValueParser<T, String> castToString(Class<T> clazz) {
return (input, defaultValue) -> {
if (input instanceof String) return (String) input;
else return input.toString();
static <V> @NotNull DataFunction<String, V> parseString(Class<V> valueClass) {
return input -> {
if (valueClass.isInstance(input)) return valueClass.cast(input);
else throw new IllegalArgumentException("Cannot cast string to " + valueClass.getName());
};
}
@Contract(pure = true)
static @NotNull ConfigValueParser<Object, Integer> intValue() {
return (input, defaultValue) -> {
static @NotNull DataFunction<Object, Integer> intValue() {
return input -> {
if (input instanceof Integer) {
return (Integer) input;
} else if (input instanceof Number) {
@@ -91,8 +84,8 @@ public interface ConfigValueParser<T, R> {
}
@Contract(pure = true)
static @NotNull ConfigValueParser<Object, Short> shortValue() {
return (input, defaultValue) -> {
static @NotNull DataFunction<Object, Short> shortValue() {
return input -> {
if (input instanceof Short) {
return (Short) input;
} else if (input instanceof Number) {
@@ -102,8 +95,8 @@ public interface ConfigValueParser<T, R> {
}
@Contract(pure = true)
static @NotNull ConfigValueParser<Object, Double> doubleValue() {
return (input, defaultValue) -> {
static @NotNull DataFunction<Object, Double> doubleValue() {
return input -> {
if (input instanceof Double) {
return (Double) input;
} else if (input instanceof Number) {
@@ -113,8 +106,8 @@ public interface ConfigValueParser<T, R> {
}
@Contract(pure = true)
static @NotNull ConfigValueParser<Object, Byte> byteValue() {
return (input, defaultValue) -> {
static @NotNull DataFunction<Object, Byte> byteValue() {
return input -> {
if (input instanceof Byte) {
return (Byte) input;
} else if (input instanceof Number) {
@@ -124,8 +117,8 @@ public interface ConfigValueParser<T, R> {
}
@Contract(pure = true)
static @NotNull ConfigValueParser<Object, Float> floatValue() {
return (input, defaultValue) -> {
static @NotNull DataFunction<Object, Float> floatValue() {
return input -> {
if (input instanceof Float) {
return (Float) input;
} else if (input instanceof Number) {
@@ -135,8 +128,8 @@ public interface ConfigValueParser<T, R> {
}
@Contract(pure = true)
static @NotNull ConfigValueParser<Object, Long> longValue() {
return (input, defaultValue) -> {
static @NotNull DataFunction<Object, Long> longValue() {
return input -> {
if (input instanceof Long) {
return (Long) input;
} else if (input instanceof Number) {
@@ -146,19 +139,20 @@ public interface ConfigValueParser<T, R> {
}
@Contract(pure = true)
static @NotNull ConfigValueParser<Object, Boolean> booleanValue() {
return (input, defaultValue) -> {
static @NotNull DataFunction<Object, Boolean> booleanValue() {
return input -> {
if (input instanceof Boolean) {
return (Boolean) input;
} else if (input instanceof String) {
String s = (String) input;
return Boolean.parseBoolean(s) || "yes".equalsIgnoreCase(s);
} else if (input instanceof Integer) {
return ((Integer) input) == 1;
return (Integer) input == 1;
} else throw new IllegalArgumentException("Cannot cast value to " + Boolean.class.getName());
};
}
}
@@ -0,0 +1,19 @@
package cc.carm.lib.configuration.function;
import org.jetbrains.annotations.Nullable;
import java.io.Serializable;
@FunctionalInterface
public interface DataValidator<T> extends Serializable {
void validate(@Nullable T value) throws Exception;
default DataValidator<T> compose(DataValidator<? super T> other) {
return value -> {
validate(value);
other.validate(value);
};
}
}
@@ -0,0 +1,31 @@
package cc.carm.lib.configuration.function;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import org.jetbrains.annotations.NotNull;
import java.io.Serializable;
@FunctionalInterface
public interface ValueComposer<T, U> extends Serializable {
/**
* Accept the value and the data, and then compose the value.
*
* @param holder The configuration holder
* @param type The value type, e.g. {@link java.util.List}, {@link java.util.Map}, etc.
* @param data The unit data
* @throws Exception If an error occurs
*/
void accept(@NotNull ConfigurationHolder<?> holder, @NotNull T type, @NotNull U data) throws Exception;
default ValueComposer<T, U> andThen(ValueComposer<? super T, ? super U> after) {
return (holder, unit, data) -> {
accept(holder, unit, data);
after.accept(holder, unit, data);
};
}
}
@@ -0,0 +1,80 @@
package cc.carm.lib.configuration.function;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.Serializable;
import java.util.Objects;
@FunctionalInterface
public interface ValueHandler<T, R> extends Serializable {
@Nullable R handle(@NotNull ConfigurationHolder<?> holder, @NotNull T data) throws Exception;
default <V> ValueHandler<T, V> andThen(@NotNull ValueHandler<R, V> after) {
Objects.requireNonNull(after);
return ((provider, data) -> {
R result = handle(provider, data);
if (result == null) return null;
else return after.handle(provider, result);
});
}
default <V> ValueHandler<V, R> compose(@NotNull ValueHandler<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return ((provider, data) -> {
T result = before.handle(provider, data);
if (result == null) return null;
return handle(provider, result);
});
}
default <V> ValueHandler<V, R> compose(@NotNull DataFunction<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return ((provider, data) -> {
T result = before.handle(data);
return handle(provider, result);
});
}
@Contract(pure = true)
static <T> @NotNull ValueHandler<T, T> identity() {
return (provider, input) -> input;
}
@Contract(pure = true)
static <T> @NotNull ValueHandler<T, Object> toObject() {
return ConfigurationHolder::serialize;
}
@Contract(pure = true)
static <T> @NotNull ValueHandler<T, String> stringValue() {
return (provider, input) -> String.valueOf(input);
}
@Contract(pure = true)
static <O, T> @NotNull ValueHandler<O, T> deserialize(ValueType<T> to) {
return (provider, input) -> provider.deserialize(to, input);
}
@Contract(pure = true)
static <T, V> @NotNull ValueHandler<T, V> required() {
return (provider, input) -> {
throw new IllegalArgumentException("Please specify the value parser.");
};
}
@Contract(pure = true)
static <T, V> @NotNull ValueHandler<T, V> required(ValueType<V> type) {
return (provider, input) -> {
if (type.isInstance(input)) return type.cast(input); // Simple cast
throw new IllegalArgumentException("Please specify the value parser.");
};
}
}
@@ -0,0 +1,49 @@
package cc.carm.lib.configuration.function;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.Serializable;
@FunctionalInterface
public interface ValueValidator<T> extends Serializable {
void validate(@NotNull ConfigurationHolder<?> holder, @Nullable T value) throws Exception;
default ValueValidator<T> and(ValueValidator<? super T> other) {
return (holder, value) -> {
validate(holder, value);
other.validate(holder, value);
};
}
static <V> ValueValidator<V> none() {
return (holder, data) -> {
};
}
static <V> ValueValidator<V> nonnull() {
return nonnull("Value cannot be null");
}
static <V> ValueValidator<V> nonnull(String message) {
return (holder, data) -> {
if (data == null) throw new IllegalArgumentException(message);
};
}
static <V extends Number> ValueValidator<V> range(V min, V max) {
return range(min, max, "Value must be in range [" + min + ", " + max + "]");
}
static <V extends Number> ValueValidator<V> range(V min, V max, String message) {
return (holder, data) -> {
if (data.doubleValue() < min.doubleValue() || data.doubleValue() > max.doubleValue()) {
throw new IllegalArgumentException(message);
}
};
}
}
@@ -0,0 +1,204 @@
package cc.carm.lib.configuration.source;
import cc.carm.lib.configuration.adapter.*;
import cc.carm.lib.configuration.adapter.strandard.StandardAdapters;
import cc.carm.lib.configuration.function.ConfigExceptionHandler;
import cc.carm.lib.configuration.function.DataFunction;
import cc.carm.lib.configuration.function.ValueValidator;
import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
import cc.carm.lib.configuration.source.loader.PathGenerator;
import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder;
import cc.carm.lib.configuration.source.meta.ConfigurationMetadata;
import cc.carm.lib.configuration.source.option.ConfigurationOption;
import cc.carm.lib.configuration.source.option.ConfigurationOptionHolder;
import cc.carm.lib.configuration.source.section.ConfigureSource;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* ConfigurationFactory, used to create configuration holder.
*
* @param <SOURCE> The {@link ConfigureSource} type
* @param <HOLDER> The {@link ConfigurationHolder} type.
* @param <SELF> Self builder, for further implement support.
*/
public abstract class ConfigurationFactory<
SOURCE extends ConfigureSource<?, ?, SOURCE>,
HOLDER extends ConfigurationHolder<SOURCE>,
SELF
> {
protected @NotNull ValueAdapterRegistry adapters = new ValueAdapterRegistry();
protected @NotNull ConfigurationOptionHolder options = new ConfigurationOptionHolder();
protected @NotNull Map<String, ConfigurationMetaHolder> metadata = new HashMap<>();
protected @NotNull ConfigurationInitializer initializer = new ConfigurationInitializer();
protected @NotNull ConfigExceptionHandler exceptionHandler = ConfigExceptionHandler.print();
protected ConfigurationFactory() {
this.adapters.register(StandardAdapters.PRIMITIVES);
this.adapters.register(StandardAdapters.SECTIONS);
this.adapters.register(StandardAdapters.ENUMS);
this.adapters.register(StandardAdapters.UUID);
}
protected abstract SELF self();
public SELF adapters(ValueAdapterRegistry adapters) {
this.adapters = adapters;
return self();
}
public SELF adapter(Consumer<ValueAdapterRegistry> adapterRegistryConsumer) {
adapterRegistryConsumer.accept(adapters);
return self();
}
public <T> SELF adapter(@NotNull ValueAdapter<T> adapter) {
return adapter(a -> a.register(adapter));
}
public <T> SELF adapter(@NotNull ValueType<T> type, @NotNull ValueSerializer<T> serializer) {
return adapter(a -> a.register(type, serializer));
}
public <T> SELF adapter(@NotNull ValueType<T> type, @NotNull ValueParser<T> parser) {
return adapter(a -> a.register(type, parser));
}
public <FROM, TO> SELF adapter(@NotNull Class<FROM> from, @NotNull Class<TO> to,
@NotNull DataFunction<FROM, TO> parser,
@NotNull DataFunction<TO, FROM> serializer) {
return adapter(a -> a.register(from, to, parser, serializer));
}
public <FROM, TO> SELF adapter(@NotNull ValueType<FROM> from, @NotNull ValueType<TO> to,
@NotNull DataFunction<FROM, TO> parser,
@NotNull DataFunction<TO, FROM> serializer) {
return adapter(a -> a.register(from, to, parser, serializer));
}
public <T> SELF adapter(@NotNull ValueType<T> type, @NotNull ValueSerializer<T> serializer, @NotNull ValueParser<T> parser) {
return adapter(a -> a.register(type, serializer, parser));
}
public <T> SELF adapter(@NotNull Class<T> type, @NotNull ValueSerializer<T> serializer, @NotNull ValueParser<T> parser) {
return adapter(ValueType.of(type), serializer, parser);
}
public SELF options(ConfigurationOptionHolder options) {
this.options = options;
return self();
}
public SELF option(Consumer<ConfigurationOptionHolder> modifier) {
modifier.accept(options);
return self();
}
public <O> SELF option(ConfigurationOption<O> type, O value) {
return option(o -> o.set(type, value));
}
public <O> SELF option(ConfigurationOption<O> type, Supplier<O> value) {
return option(type, value.get());
}
public <O> SELF option(ConfigurationOption<O> type, Consumer<O> modifier) {
return option(holder -> {
O current = holder.get(type);
modifier.accept(current);
holder.set(type, current);
});
}
public SELF metadata(@NotNull Map<String, ConfigurationMetaHolder> metadata) {
this.metadata = metadata;
return self();
}
public SELF metadata(@NotNull Consumer<Map<String, ConfigurationMetaHolder>> handler) {
handler.accept(this.metadata);
return self();
}
public SELF metadata(@Nullable String path, @NotNull ConfigurationMetaHolder meta) {
return metadata(m -> m.put(path, meta));
}
public SELF metadata(@Nullable String path, @NotNull Consumer<ConfigurationMetaHolder> handler) {
return metadata(map -> {
ConfigurationMetaHolder meta = map.computeIfAbsent(path, k -> new ConfigurationMetaHolder());
handler.accept(meta);
});
}
public SELF initializer(ConfigurationInitializer initializer) {
this.initializer = initializer;
return self();
}
public SELF initializer(Consumer<ConfigurationInitializer> initializerConsumer) {
initializerConsumer.accept(initializer);
return self();
}
public SELF exceptionally(@NotNull ConfigExceptionHandler handler) {
this.exceptionHandler = handler;
return self();
}
/**
* Supply the base path generator for this configuration holder
*
* @param generator {@link PathGenerator}
* @return this
*/
public SELF pathGenerator(PathGenerator generator) {
return initializer(loader -> loader.pathGenerator(generator));
}
/**
* Register a new annotation for metadata to the configuration loader
*
* @param annotation The {@link Annotation}
* @param metadata The {@link ConfigurationMetadata} type
* @param extractor The {@link Function} to extract the metadata from the annotation
* @param <M> The metadata type
* @param <A> The annotation type
* @return this
*/
public <M, A extends Annotation> SELF metaAnnotation(@NotNull Class<A> annotation,
@NotNull ConfigurationMetadata<M> metadata,
@NotNull Function<A, M> extractor) {
return initializer(loader -> loader.registerAnnotation(annotation, metadata, extractor));
}
/**
* Register a new annotation for {@link ValueValidator} to the configuration loader
*
* @param annotation The {@link Annotation}
* @param builder The {@link Function} to build the {@link ValueValidator} from the annotation
* @param <A> The annotation type
* @return this
*/
public <A extends Annotation> SELF validAnnotation(@NotNull Class<A> annotation,
@NotNull Function<A, ValueValidator<Object>> builder) {
return initializer(loader -> loader.registerValidAnnotation(annotation, builder));
}
/**
* Build the configuration holder.
*
* @return The configuration holder
*/
public abstract @NotNull HOLDER build();
}
@@ -0,0 +1,155 @@
package cc.carm.lib.configuration.source;
import cc.carm.lib.configuration.Configuration;
import cc.carm.lib.configuration.adapter.ValueAdapterRegistry;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.function.ConfigExceptionHandler;
import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder;
import cc.carm.lib.configuration.source.meta.ConfigurationMetadata;
import cc.carm.lib.configuration.source.meta.StandardMeta;
import cc.carm.lib.configuration.source.option.ConfigurationOption;
import cc.carm.lib.configuration.source.option.ConfigurationOptionHolder;
import cc.carm.lib.configuration.source.section.ConfigureSource;
import cc.carm.lib.configuration.value.ConfigValue;
import cc.carm.lib.configuration.value.ValueManifest;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.UnmodifiableView;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.Predicate;
public abstract class ConfigurationHolder<SOURCE extends ConfigureSource<?, ?, SOURCE>> {
protected final @NotNull ValueAdapterRegistry adapters;
protected final @NotNull ConfigurationOptionHolder options;
protected final @NotNull Map<String, ConfigurationMetaHolder> metadata;
protected final @NotNull ConfigurationInitializer initializer;
protected @NotNull ConfigExceptionHandler exceptionHandler;
public ConfigurationHolder(@NotNull ValueAdapterRegistry adapters,
@NotNull ConfigurationOptionHolder options,
@NotNull Map<String, ConfigurationMetaHolder> metadata,
@NotNull ConfigurationInitializer initializer) {
this(adapters, options, metadata, initializer, ConfigExceptionHandler.print());
}
public ConfigurationHolder(@NotNull ValueAdapterRegistry adapters,
@NotNull ConfigurationOptionHolder options,
@NotNull Map<String, ConfigurationMetaHolder> metadata,
@NotNull ConfigurationInitializer initializer,
@NotNull ConfigExceptionHandler exceptionHandler) {
this.initializer = initializer;
this.adapters = adapters;
this.options = options;
this.metadata = metadata;
this.exceptionHandler = exceptionHandler;
}
public abstract @NotNull SOURCE config();
public void reload() throws Exception {
config().reload();
}
public void save() throws Exception {
config().save();
}
public ConfigurationOptionHolder options() {
return options;
}
public <O> @NotNull O option(@NotNull ConfigurationOption<O> option) {
return options().get(option);
}
public @NotNull Map<String, ConfigurationMetaHolder> metadata() {
return this.metadata;
}
public @NotNull ConfigurationMetaHolder metadata(@Nullable String path) {
return metadata().computeIfAbsent(path, k -> new ConfigurationMetaHolder());
}
@NotNull
@UnmodifiableView
public <M> Map<String, M> extractMetadata(@NotNull ConfigurationMetadata<M> type) {
return extractMetadata(type, Objects::nonNull);
}
@NotNull
@UnmodifiableView
public <M> Map<String, M> extractMetadata(@NotNull ConfigurationMetadata<M> type, @NotNull Predicate<@Nullable M> filter) {
Map<String, M> metas = new LinkedHashMap<>();
for (Map.Entry<String, ConfigurationMetaHolder> entry : this.metadata.entrySet()) {
M data = entry.getValue().get(type);
if (filter.test(data)) metas.put(entry.getKey(), data);
}
return Collections.unmodifiableMap(metas);
}
@NotNull
@UnmodifiableView
public Map<String, ConfigValue<?, ?>> registeredValues() {
return extractMetadata(StandardMeta.VALUE);
}
public ValueAdapterRegistry adapters() {
return this.adapters;
}
public ConfigurationInitializer initializer() {
return initializer;
}
@Nullable
public <T> T deserialize(@NotNull Class<T> type, @Nullable Object source) throws Exception {
return adapters().deserialize(this, type, source);
}
@Nullable
public <T> T deserialize(@NotNull ValueType<T> type, @Nullable Object source) throws Exception {
return adapters().deserialize(this, type, source);
}
@Nullable
public <T> Object serialize(@Nullable T value) throws Exception {
return adapters().serialize(this, value);
}
public void initialize(Class<? extends Configuration> configClass) {
try {
initializer.initialize(this, configClass);
} catch (Exception e) {
throwing(configClass.getName(), e);
}
}
public void initialize(@NotNull Configuration config) {
try {
initializer.initialize(this, config);
} catch (Exception e) {
throwing(config.getClass().getName(), e);
}
}
public void initialize(@NotNull ValueManifest<?, ?> value) {
value.holder(this);
}
public void throwing(@NotNull String path, @NotNull Throwable e) {
this.exceptionHandler.handle(path, e);
}
public void exceptionally(@NotNull ConfigExceptionHandler handler) {
this.exceptionHandler = handler;
}
}
@@ -0,0 +1,33 @@
package cc.carm.lib.configuration.source.loader;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@FunctionalInterface
public interface ConfigInitializeHandler<T, V> {
static <T, V> ConfigInitializeHandler<T, V> start() {
return (provider, path, value, instance) -> {
};
}
void whenInitialize(@NotNull ConfigurationHolder<?> holder, @Nullable String path,
@NotNull T value, @Nullable V instance) throws Exception;
default ConfigInitializeHandler<T, V> andThen(ConfigInitializeHandler<T, V> after) {
return (provider, path, value, instance) -> {
whenInitialize(provider, path, value, instance);
after.whenInitialize(provider, path, value, instance);
};
}
default ConfigInitializeHandler<T, V> compose(ConfigInitializeHandler<T, V> before) {
return (provider, path, value, instance) -> {
before.whenInitialize(provider, path, value, instance);
whenInitialize(provider, path, value, instance);
};
}
}
@@ -0,0 +1,209 @@
package cc.carm.lib.configuration.source.loader;
import cc.carm.lib.configuration.Configuration;
import cc.carm.lib.configuration.function.ValueValidator;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import cc.carm.lib.configuration.source.meta.ConfigurationMetadata;
import cc.carm.lib.configuration.source.meta.StandardMeta;
import cc.carm.lib.configuration.source.option.StandardOptions;
import cc.carm.lib.configuration.value.ConfigValue;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.function.Function;
/**
* Configuration initializer,
* used to initialize {@link ConfigValue}s from {@link Configuration} classes.
*/
public class ConfigurationInitializer {
protected @NotNull PathGenerator pathGenerator;
protected @NotNull ConfigInitializeHandler<Field, ConfigValue<?, ?>> valueInitializer;
protected @NotNull ConfigInitializeHandler<Class<? extends Configuration>, Object> classInitializer;
public ConfigurationInitializer() {
this(PathGenerator.of(), ConfigInitializeHandler.start(), ConfigInitializeHandler.start());
}
public ConfigurationInitializer(@NotNull PathGenerator pathGenerator,
@NotNull ConfigInitializeHandler<Field, ConfigValue<?, ?>> valueInitializer,
@NotNull ConfigInitializeHandler<Class<? extends Configuration>, Object> classInitializer) {
this.pathGenerator = pathGenerator;
this.valueInitializer = valueInitializer;
this.classInitializer = classInitializer;
}
public void pathGenerator(@NotNull PathGenerator pathGenerator) {
this.pathGenerator = pathGenerator;
}
public @NotNull PathGenerator pathGenerator() {
return pathGenerator;
}
public ConfigInitializeHandler<Field, ConfigValue<?, ?>> fieldInitializer() {
return valueInitializer;
}
public void fieldInitializer(@NotNull ConfigInitializeHandler<Field, ConfigValue<?, ?>> fieldInitializer) {
this.valueInitializer = fieldInitializer;
}
public ConfigInitializeHandler<Class<? extends Configuration>, Object> classInitializer() {
return classInitializer;
}
public void classInitializer(@NotNull ConfigInitializeHandler<Class<? extends Configuration>, Object> classInitializer) {
this.classInitializer = classInitializer;
}
public void appendFieldInitializer(@NotNull ConfigInitializeHandler<Field, ConfigValue<?, ?>> fieldInitializer) {
this.valueInitializer = this.valueInitializer.andThen(fieldInitializer);
}
public void appendClassInitializer(@NotNull ConfigInitializeHandler<Class<? extends Configuration>, Object> classInitializer) {
this.classInitializer = this.classInitializer.andThen(classInitializer);
}
public <T, A extends Annotation> void registerClassAnnotation(@NotNull Class<A> annotation,
@NotNull ConfigurationMetadata<T> metadata,
@NotNull Function<A, T> extractor) {
appendClassInitializer((holder, path, clazz, instance) -> {
A data = clazz.getAnnotation(annotation);
if (data == null) return;
holder.metadata(path).setIfAbsent(metadata, extractor.apply(data));
});
}
public <T, A extends Annotation> void registerFieldAnnotation(@NotNull Class<A> annotation,
@NotNull ConfigurationMetadata<T> metadata,
@NotNull Function<A, T> extractor) {
appendFieldInitializer((holder, path, field, instance) -> {
A data = field.getAnnotation(annotation);
if (data == null) return;
holder.metadata(path).setIfAbsent(metadata, extractor.apply(data));
});
}
public <T, A extends Annotation> void registerAnnotation(@NotNull Class<A> annotation,
@NotNull ConfigurationMetadata<T> metadata,
@NotNull Function<A, T> extractor) {
registerClassAnnotation(annotation, metadata, extractor);
registerFieldAnnotation(annotation, metadata, extractor);
}
public <A extends Annotation> void registerValidAnnotation(@NotNull Class<A> annotation,
@NotNull Function<A, ValueValidator<Object>> builder) {
appendFieldInitializer((holder, path, field, instance) -> {
A data = field.getAnnotation(annotation);
if (data == null) return;
instance.validate((h, t) -> builder.apply(data).validate(h, t));
});
}
public @Nullable String getFieldPath(@NotNull ConfigurationHolder<?> holder, @Nullable String parentPath, @NotNull Field field) {
return pathGenerator.getFieldPath(holder, parentPath, field);
}
public @Nullable String getClassPath(@NotNull ConfigurationHolder<?> holder, @Nullable String parentPath,
@NotNull Class<?> clazz, @Nullable Field clazzField) {
return pathGenerator.getClassPath(holder, parentPath, clazz, clazzField);
}
public void initialize(@NotNull ConfigurationHolder<?> holder,
@NotNull Configuration config) throws Exception {
initializeInstance(holder, config, null, null);
if (holder.option(StandardOptions.SET_DEFAULTS)) holder.save();
}
public void initialize(@NotNull ConfigurationHolder<?> holder,
@NotNull Class<? extends Configuration> clazz) throws Exception {
initializeStaticClass(holder, clazz, null, null);
if (holder.option(StandardOptions.SET_DEFAULTS)) holder.save();
}
// 针对实例类的初始化方法
protected void initializeInstance(@NotNull ConfigurationHolder<?> holder, @NotNull Configuration root,
@Nullable String parentPath, @Nullable Field configField) {
String path = getClassPath(holder, parentPath, root.getClass(), configField);
try {
this.classInitializer.whenInitialize(holder, path, root.getClass(), root);
} catch (Exception e) {
holder.throwing(path, e);
}
Arrays.stream(root.getClass().getDeclaredFields()).forEach(field -> initializeField(holder, root, field, path));
}
// 针对静态类的初始化方法
@SuppressWarnings("unchecked")
protected void initializeStaticClass(@NotNull ConfigurationHolder<?> holder,
@NotNull Class<?> clazz,
@Nullable String parentPath, @Nullable Field configField) {
if (!Configuration.class.isAssignableFrom(clazz)) return; // Only Configuration class can be initialized.
String path = getClassPath(holder, parentPath, clazz, configField);
try {
this.classInitializer.whenInitialize(holder, path, (Class<? extends Configuration>) clazz, configField);
} catch (Exception e) {
holder.throwing(path, e);
}
for (Field field : clazz.getDeclaredFields()) {
initializeField(holder, clazz, field, path);
}
if (holder.option(StandardOptions.LOAD_SUB_CLASSES)) {
Class<?>[] classes = clazz.getDeclaredClasses();
for (int i = classes.length - 1; i >= 0; i--) { // 逆向加载,保持顺序。
initializeStaticClass(holder, classes[i], path, null);
}
}
}
protected void initializeField(@NotNull ConfigurationHolder<?> holder,
@NotNull Object source, @NotNull Field field, @Nullable String parent) {
try {
field.setAccessible(true);
Object object = field.get(source);
//
if (object instanceof ConfigValue<?, ?>) {
// 目标是 ConfigValue 实例,进行具体的初始化注入
ConfigValue<?, ?> value = (ConfigValue<?, ?>) object;
String path = getFieldPath(holder, parent, field);
if (path == null) return;
value.initialize(holder, path);
holder.metadata(path).set(StandardMeta.VALUE, value); // Mark the minimal config value unit.
if (holder.option(StandardOptions.SET_DEFAULTS)) {
value.setDefault(); // Set default value.
}
try {
this.valueInitializer.whenInitialize(holder, path, field, value);
} catch (Exception e) {
holder.throwing(path, e);
}
if (holder.option(StandardOptions.PRELOAD)) {
value.get(); // Preload the value by calling #get method.
}
} else if (source instanceof Configuration && object instanceof Configuration) {
// 当且仅当 源字段与字段 均为Configuration实例时,才对目标字段进行下一步初始化加载。
initializeInstance(holder, (Configuration) object, parent, field);
} else if (source instanceof Class<?> && object instanceof Class<?>) {
// 当且仅当 源字段与字段 均为静态类时,才对目标字段进行下一步初始化加载。
initializeStaticClass(holder, (Class<?>) object, parent, field);
}
// 以上判断实现以下规范:
// - 实例类中仅加载 ConfigValue实例 与 Configuration实例
// - 静态类中仅加载 静态ConfigValue实例 与 静态Configuration类
} catch (IllegalAccessException ignored) {
}
}
}
@@ -0,0 +1,121 @@
package cc.carm.lib.configuration.source.loader;
import cc.carm.lib.configuration.annotation.ConfigPath;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import cc.carm.lib.configuration.source.option.StandardOptions;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Field;
import java.util.function.UnaryOperator;
/**
* Path generator for configuration.
* <p>
* Path generator is a utility class that helps to generate the path of the configuration.
* It can be used to generate the path of the field or class.
*/
public class PathGenerator {
public static PathGenerator of() {
return of(PathGenerator::covertPathName);
}
public static PathGenerator of(UnaryOperator<String> pathConverter) {
return new PathGenerator(pathConverter);
}
protected UnaryOperator<String> pathConverter;
public PathGenerator(UnaryOperator<String> pathConverter) {
this.pathConverter = pathConverter;
}
public @NotNull UnaryOperator<String> getPathConverter() {
return pathConverter;
}
public void setPathConverter(UnaryOperator<String> pathConverter) {
this.pathConverter = pathConverter;
}
public String covertPath(String name) {
return pathConverter.apply(name);
}
public @Nullable String getFieldPath(@NotNull ConfigurationHolder<?> holder,
@Nullable String parentPath, @NotNull Field field) {
ConfigPath path = field.getAnnotation(ConfigPath.class);
if (path == null)
return link(holder, parentPath, false, covertPath(field.getName())); // No annotation, use field name.
else return link(holder, parentPath, path.root(), select(path.value(), covertPath(field.getName())));
}
public @Nullable String getClassPath(@NotNull ConfigurationHolder<?> holder,
@Nullable String parentPath, @NotNull Class<?> clazz, @Nullable Field clazzField) {
// For standard path generator, we generate path following by:
// 1. Check if the class has a ConfigPath annotation, if so, use the root and value as the path.
// 2. If the class defined as a field, check if the field has a ConfigPath annotation,
// and use filed information.
ConfigPath clazzPath = clazz.getAnnotation(ConfigPath.class);
if (clazzPath != null) return link(holder, parentPath, clazzPath.root(), clazzPath.value());
if (clazzField != null) {
ConfigPath fieldPath = clazzField.getAnnotation(ConfigPath.class);
if (fieldPath == null) return link(holder, parentPath, false, covertPath(clazzField.getName()));
else return getFieldPath(holder, parentPath, clazzField);
}
return link(holder, parentPath, false, covertPath(clazz.getSimpleName())); // No field, use class name.
}
protected String select(String path, String defaultValue) {
if (path == null || path.isEmpty()) return defaultValue;
else return isBlank(path) ? null : path;
}
protected @Nullable String link(@NotNull ConfigurationHolder<?> holder,
@Nullable String parent, boolean root, @Nullable String path) {
if (path == null || path.isEmpty()) return root ? null : parent;
return (root || parent == null) ? path : (parent + pathSeparator(holder) + path);
}
public static boolean isBlank(String path) {
return path == null || path.replace(" ", "").isEmpty();
}
public static char pathSeparator(ConfigurationHolder<?> holder) {
return holder.option(StandardOptions.PATH_SEPARATOR);
}
/**
* Get the configuration name of the specified element.
* Use the naming convention of all lowercase and "-" links.
* <p>
* e.g. "SOME_NAME" will be "some-name"
*
* @param name source name
* @return the final path
*/
public static String covertPathName(String name) {
return name
// Replace all uppercase letters with dashes
.replaceAll("[A-Z]", "=$0")
// If the first letter is also capitalized,
// it will also be converted and the first dash will need to be removed
.replaceAll("^=(.*)$", "$1")
// Because the name may contain _, it needs to be treated a little differently
.replaceAll("_=([A-Z])", "_$1")
// The content that is not named in all caps is then converted
.replaceAll("([a-z])=([A-Z])", "$1_$2")
// Remove any extra horizontal lines
.replace("=", "")
// Replace the underscore with a dash
.replace("_", "-")
// Finally, convert it to all lowercase
.toLowerCase();
}
}
@@ -0,0 +1,125 @@
package cc.carm.lib.configuration.source.meta;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
public class ConfigurationMetaHolder {
protected final @NotNull Map<ConfigurationMetadata<?>, Object> values;
public ConfigurationMetaHolder() {
this(new ConcurrentHashMap<>());
}
public ConfigurationMetaHolder(@NotNull Map<ConfigurationMetadata<?>, Object> values) {
this.values = values;
}
public @NotNull Map<ConfigurationMetadata<?>, Object> values() {
return values;
}
/**
* Get the value of option.
*
* @param type {@link ConfigurationMetadata}
* @param defaultValue Default value if the value of option is not set.
* @param <V> Value type
* @return Value of option
*/
@SuppressWarnings("unchecked")
@Contract("_,!null -> !null")
public <V> @Nullable V get(@NotNull ConfigurationMetadata<V> type, @Nullable V defaultValue) {
return (V) values().getOrDefault(type, type.defaultOrSupply(defaultValue));
}
/**
* Get the value of option.
*
* @param type {@link ConfigurationMetadata}
* @param defaultValue Default value if the value of option is not set.
* @param <V> Value type
* @return Value of option
*/
@SuppressWarnings("unchecked")
@Contract("_,!null -> !null")
public <V> @Nullable V get(@NotNull ConfigurationMetadata<V> type, Supplier<@Nullable V> defaultValue) {
return (V) values().getOrDefault(type, type.defaultOrSupply(defaultValue));
}
/**
* Get the value of option.
*
* @param type {@link ConfigurationMetadata}
* @param <V> Value type
* @return Value of option
*/
public <V> @Nullable V get(@NotNull ConfigurationMetadata<V> type) {
return get(type, (V) null);
}
public boolean contains(@NotNull ConfigurationMetadata<?> type) {
return values().containsKey(type) || type.hasDefaults();
}
/**
* Set the value of meta, if the value is null, the meta will be removed.
* <br> Will only be changed in current holder.
*
* @param type {@link ConfigurationMetadata}
* @param value Value of meta
* @param <V> Value type
* @return Previous value of meta
*/
@SuppressWarnings("unchecked")
public <V> @Nullable V set(@NotNull ConfigurationMetadata<V> type, @Nullable V value) {
if (value == null || type.isDefault(value)) {
return (V) values().remove(type);
} else {
return (V) values().put(type, value);
}
}
/**
* Set the value of meta, if the value is null, the meta will not be changed.
* <br> Will only be changed in current holder.
*
* @param type {@link ConfigurationMetadata}
* @param value Value of meta
* @param <V> Value type
*/
public <V> void setIfAbsent(@NotNull ConfigurationMetadata<V> type, @Nullable V value) {
if (value == null || type.isDefault(value)) {
values().remove(type);
} else {
values().putIfAbsent(type, value);
}
}
/**
* Set the value of meta, if the value is null, the meta will not be changed.
* <br> Will only be changed in current holder.
*
* @param type {@link ConfigurationMetadata}
* @param value Value of meta
* @param <V> Value type
* @return Previous value of meta
*/
@SuppressWarnings("unchecked")
public <V> @Nullable V setIfPresent(@NotNull ConfigurationMetadata<V> type, @Nullable V value) {
Object exists = values().get(type);
if (exists == null) return null;
if (value == null || type.isDefault(value)) {
return (V) values().remove(type);
} else {
return (V) values().put(type, value);
}
}
}
@@ -0,0 +1,57 @@
package cc.carm.lib.configuration.source.meta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.Supplier;
public class ConfigurationMetadata<T> {
public static <T> ConfigurationMetadata<T> of() {
return of(() -> null);
}
public static <T> ConfigurationMetadata<T> of(T defaults) {
return of(() -> defaults);
}
public static <T> ConfigurationMetadata<T> of(@NotNull Supplier<@Nullable T> defaults) {
return new ConfigurationMetadata<>(defaults);
}
protected Supplier<@Nullable T> defaultsSupplier;
public ConfigurationMetadata(@NotNull Supplier<@Nullable T> defaults) {
this.defaultsSupplier = defaults;
}
public boolean isDefault(@NotNull T value) {
return value.equals(defaults());
}
public boolean hasDefaults() {
return defaults() != null;
}
public T defaultOrSupply(@Nullable T suppliedValue) {
return defaultOrSupply(() -> suppliedValue);
}
public T defaultOrSupply(Supplier<@Nullable T> suppliedValue) {
T defaults = defaults();
return defaults == null ? suppliedValue.get() : defaults;
}
public @Nullable T defaults() {
return defaultsSupplier.get();
}
public void setDefaults(Supplier<T> defaultFunction) {
this.defaultsSupplier = defaultFunction;
}
public void setDefaults(T value) {
setDefaults(() -> value);
}
}
@@ -0,0 +1,12 @@
package cc.carm.lib.configuration.source.meta;
import cc.carm.lib.configuration.value.ConfigValue;
public interface StandardMeta {
/**
* To mark the {@link ConfigValue} instance of specific path.
*/
ConfigurationMetadata<ConfigValue<?, ?>> VALUE = ConfigurationMetadata.of();
}
@@ -0,0 +1,40 @@
package cc.carm.lib.configuration.source.option;
import org.jetbrains.annotations.NotNull;
import java.util.function.Supplier;
public class ConfigurationOption<V> {
public static <T> ConfigurationOption<T> of(@NotNull T defaultValue) {
return new ConfigurationOption<>(defaultValue);
}
public static <T> ConfigurationOption<T> of(@NotNull Supplier<T> defaultValue) {
return of(defaultValue.get());
}
private @NotNull V defaultValue;
public ConfigurationOption(@NotNull V defaultValue) {
this.defaultValue = defaultValue;
}
public @NotNull V defaults() {
return defaultValue;
}
/**
* Set the default value of option.
*
* @param defaultValue Default value
*/
public void defaults(@NotNull V defaultValue) {
this.defaultValue = defaultValue;
}
public boolean isDefault(@NotNull V value) {
return value.equals(defaultValue);
}
}
@@ -0,0 +1,70 @@
package cc.carm.lib.configuration.source.option;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
public class ConfigurationOptionHolder {
public static @NotNull ConfigurationOptionHolder of(@NotNull Map<ConfigurationOption<?>, Object> options) {
return new ConfigurationOptionHolder(new ConcurrentHashMap<>(options));
}
protected final Map<ConfigurationOption<?>, Object> options;
public ConfigurationOptionHolder() {
this(new ConcurrentHashMap<>());
}
public ConfigurationOptionHolder(Map<ConfigurationOption<?>, Object> options) {
this.options = options;
}
public @NotNull Map<ConfigurationOption<?>, Object> values() {
return options;
}
/**
* Get the value of option.
*
* @param type {@link ConfigurationOption}
* @param <V> Value type
* @return Value of option
*/
@SuppressWarnings("unchecked")
public <V> @NotNull V get(@NotNull ConfigurationOption<V> type) {
return Optional.ofNullable(values().get(type)).map(v -> (V) v).orElseGet(type::defaults);
}
/**
* Set the value of option.
*
* @param type {@link ConfigurationOption}
* @param value Value of option
* @param <V> Value type
* @return Previous value of option
*/
@SuppressWarnings("unchecked")
public <V> @Nullable V set(@NotNull ConfigurationOption<V> type, @Nullable V value) {
if (value == null) {
return (V) values().remove(type);
} else {
return (V) values().put(type, value);
}
}
/**
* Set the value of option to option's {@link ConfigurationOption#defaults()}.
*
* @param type {@link ConfigurationOption}
* @param <V> Value type
* @return Previous value of option
*/
public <V> @Nullable V clear(@NotNull ConfigurationOption<V> type) {
return set(type, null);
}
}
@@ -0,0 +1,35 @@
package cc.carm.lib.configuration.source.option;
import cc.carm.lib.configuration.Configuration;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import static cc.carm.lib.configuration.source.option.ConfigurationOption.of;
public interface StandardOptions {
/**
* The configuration path separator.
*/
ConfigurationOption<Character> PATH_SEPARATOR = of('.');
/**
* Whether to set and save default values if offered and not exists in configuration.
*/
ConfigurationOption<Boolean> SET_DEFAULTS = of(true);
/**
* Whether to load subclasses of configuration class.
*/
ConfigurationOption<Boolean> LOAD_SUB_CLASSES = of(true);
/**
* Whether to pre parse the config values,
* may good to set true if you want to keep the config format.
* <br> if true, the values will be parsed when
* {@link ConfigurationHolder#initialize(Configuration)}.
* <br> if false, the values will be parsed when calling
* {@link cc.carm.lib.configuration.value.ConfigValue#get()}
*/
ConfigurationOption<Boolean> PRELOAD = of(true);
}
@@ -0,0 +1,920 @@
package cc.carm.lib.configuration.source.section;
import cc.carm.lib.configuration.function.DataFunction;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.UnmodifiableView;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;
/**
* Represents a section of a configuration.
*
* @author Carm
* @since 4.0.0
*/
public interface ConfigureSection {
/**
* Gets the parent section of this section.
* <p>
* For root sections, this will return null.
*
* @return Parent section, or null if this is a root section.
*/
@Contract(pure = true)
@Nullable ConfigureSection parent();
/**
* Get the current section's path from {@link #parent()} of this section.
*
* @return The current path of this section, if {@link #isRoot()}, return empty string.
*/
@NotNull String path();
/**
* Get the full path of this section.
*
* @return The full path of this section, if {@link #isRoot()}, return empty string.
*/
default @NotNull String fullPath() {
if (parent() == null) return "";
return (parent().isRoot() ? "" : parent().fullPath() + pathSeparator()) + path();
}
/**
* Get the path separator for the section.
*
* @return The path separator
*/
default char pathSeparator() {
return '.';
}
/**
* Gets if this section is a root section.
*
* @return True if this section is a root section, false otherwise.
*/
@Contract(pure = true)
default boolean isRoot() {
return parent() == null;
}
/**
* Gets if this section is empty.
*
* @return True if this section is empty, false otherwise.
*/
default boolean isEmpty() {
return getValues(false).isEmpty();
}
/**
* Gets the number of keys in this section.
*
* @return Number of keys in this section.
*/
default int size(boolean deep) {
return getKeys(deep).size();
}
/**
* Gets a set containing all keys in this section.
* <p>
* If deep is set to true, then this will contain all the keys within any
* child {@link ConfigureSection}s (and their children paths).
* <p>
* If deep is set to false, then this will contain only the keys of any
* direct children, and not their own children.
*
* @param deep Whether to get a deep list.
* @return Set of keys contained within this Section.
*/
@NotNull
@UnmodifiableView
default Set<String> getKeys(boolean deep) {
return getValues(deep).keySet();
}
/**
* Gets a set containing all primary keys in this section.
*
* @return Set of keys contained within this Section.
*/
@NotNull
@UnmodifiableView
default Set<String> keys() {
return getKeys(false);
}
/**
* Gets a set containing all values in this section.
* <p>
* If deep is set to true, then this will contain all the keys within any
* child {@link ConfigureSection}s (and their children paths).
* <p>
* If deep is set to false, then this will contain only the keys of any
* direct children, and not their own children.
*
* @param deep Whether to get a deep list.
* @return Map of data values contained within this Section.
*/
@NotNull
@UnmodifiableView
Map<String, Object> getValues(boolean deep);
/**
* Gets a set containing all key-values in this section.
*
* @return Map of data values contained within this Section.
* @see #getValues(boolean)
*/
@NotNull
@UnmodifiableView
default Map<String, Object> values() {
return getValues(false);
}
/**
* Get this section as a map.
* <p>
* In this map, child {@link ConfigureSection}s will also be represented as {@link Map}s.
*
* @return Map of data values contained within this Section.
*/
@NotNull
@UnmodifiableView
Map<String, Object> asMap();
/**
* Create a stream of all values in this section.
*
* @return Stream of all values in this section.
*/
default Stream<Map.Entry<String, Object>> stream() {
return values().entrySet().stream();
}
/**
* Iterates over all key-values in this section (include child sections)
*
* @param action The action to apply to each key.
*/
default void forEach(@NotNull BiConsumer<String, Object> action) {
values().forEach(action);
}
/**
* Sets the value at the given path.
* <p>
* Null values will be kept, if you want to remove a value use {@link #remove(String)}
* Path separator depends on holder's
* {@link cc.carm.lib.configuration.source.option.StandardOptions#PATH_SEPARATOR}
*
* @param path The path to set the value at.
* @param value The value to set.
*/
void set(@NotNull String path, @Nullable Object value);
/**
* Removes the value at the given path.
* <p>
* Path separator depends on holder's
* {@link cc.carm.lib.configuration.source.option.StandardOptions#PATH_SEPARATOR}
*
* @param path The path to remove the value at.
*/
void remove(@NotNull String path);
/**
* Check if the given path is present.
* <p>
* Path separator depends on holder's
* {@link cc.carm.lib.configuration.source.option.StandardOptions#PATH_SEPARATOR}
*
* @param path The path to check.
* @return True if the value is present, false otherwise.
*/
default boolean contains(@NotNull String path) {
return getKeys(true).contains(path);
}
/**
* Check if the value of given path is present.
* <p>
* Path separator depends on holder's
* {@link cc.carm.lib.configuration.source.option.StandardOptions#PATH_SEPARATOR}
*
* @param path The path to check.
* @return True if the value is present, false otherwise.
*/
default boolean containsValue(@NotNull String path) {
return get(path) != null;
}
/**
* Predicate the value of given path is specific type.
*
* @param path The path to check.
* @param typeClass The type's class
* @param <T> The type to check.
* @return True if the value is present and is the correct type, false otherwise.
*/
default <T> boolean isType(@NotNull String path, @NotNull Class<T> typeClass) {
return typeClass.isInstance(get(path));
}
/**
* Predicate the value of given path is a {@link List}.
*
* @param path The path to check.
* @return True if the value is present and is a list, false otherwise.
*/
default boolean isList(@NotNull String path) {
return isType(path, List.class);
}
/**
* Get the value as a {@link List} from the specified path.
*
* @param path The path to get the {@link List}.
* @return The list if the path exists and is a list, otherwise null.
*/
default @Nullable List<?> getList(@NotNull String path) {
Object val = get(path);
return (val instanceof List<?>) ? (List<?>) val : null;
}
/**
* Predicate the value of given path is a {@link ConfigureSection}.
*
* @param path The path to check.
* @return True if the value is present and is a section, false otherwise.
*/
default boolean isSection(@NotNull String path) {
return isType(path, ConfigureSection.class);
}
/**
* Get the value as a {@link ConfigureSection} from the specified path.
*
* @param path The path to get the section.
* @return The section if the path exists and is a section, otherwise null.
*/
@Nullable
default ConfigureSection getSection(@NotNull String path) {
Object val = get(path);
return (val instanceof ConfigureSection) ? (ConfigureSection) val : null;
}
/**
* Creates a new {@link ConfigureSection} with specified values.
* <p> The {@link #parent()} of the new section will be this section.
* <p> This section will not be saved until {@link #set(String, Object)} is called.
* <p> If you want to create and use a section and set it to this section, use {@link #computeSection(String)}.
*
* @param data The data to be used to create section.
* @return Newly created section
*/
@NotNull ConfigureSection createSection(@NotNull String path, @NotNull Map<?, ?> data);
/**
* Creates a new {@link ConfigureSection} with specified values.
* <p> The {@link #parent()} of the new section will be this section.
*
* @param data The data to be used to create section.
* @return Newly created section
*/
default @NotNull ConfigureSection createSection(@NotNull String path, @NotNull Consumer<Map<String, Object>> data) {
return createSection(path, () -> {
Map<String, Object> map = new LinkedHashMap<>();
data.accept(map);
return map;
});
}
/**
* Creates a new {@link ConfigureSection} with specified values.
* <p> The {@link #parent()} of the new section will be this section.
*
* @param data The data to be used to create section.
* @return Newly created section
*/
default @NotNull ConfigureSection createSection(@NotNull String path, @NotNull Supplier<Map<String, Object>> data) {
return createSection(path, data.get());
}
/**
* Creates a new empty {@link ConfigureSection}.
* <p> The {@link #parent()} of the new section will be this section.
*
* @return Newly created section
*/
default @NotNull ConfigureSection createSection(@NotNull String path) {
return createSection(path, new LinkedHashMap<>());
}
/**
* Get or create a section at the given path.
* <p>
* Any value previously set at this path will be replaced if it is not a section
* or will be returned if it is an exists {@link ConfigureSection}.
*
* @param path The path to get the section from.
* @return The section at the path, or a new section if it does not exist.
* @see #createSection(String, Map)
*/
default @NotNull ConfigureSection computeSection(@NotNull String path) {
return computeSection(path, new LinkedHashMap<>());
}
/**
* Get or create a section at the given path.
* <p>
* Any value previously set at this path will be replaced if it is not a section
* or will be returned if it is an exists {@link ConfigureSection}.
*
* @param path The path to get the section from.
* @return The section at the path, or a new section if it does not exist.
* @see #createSection(String, Map)
*/
default @NotNull ConfigureSection computeSection(@NotNull String path, @NotNull Map<?, ?> data) {
ConfigureSection current = getSection(path);
if (current == null) {
current = createSection(path, data);
set(path, current);
}
return current;
}
/**
* Get or create a section at the given path.
* <p>
* Any value previously set at this path will be replaced if it is not a section
* or will be returned if it is an exists {@link ConfigureSection}.
*
* @param path The path to get the section from.
* @return The section at the path, or a new section if it does not exist.
* @see #createSection(String, Map)
*/
default @NotNull ConfigureSection computeSection(@NotNull String path, @NotNull Consumer<Map<String, Object>> data) {
return computeSection(path, () -> {
Map<String, Object> map = new LinkedHashMap<>();
data.accept(map);
return map;
});
}
/**
* Get or create a section at the given path.
* <p>
* Any value previously set at this path will be replaced if it is not a section
* or will be returned if it is an exists {@link ConfigureSection}.
*
* @param path The path to get the section from.
* @return The section at the path, or a new section if it does not exist.
* @see #createSection(String, Map)
*/
default @NotNull ConfigureSection computeSection(@NotNull String path, @NotNull Supplier<Map<String, Object>> data) {
return computeSection(path, data.get());
}
/**
* Get the origin value of the path.
*
* @param path The path to get the value from.
* @return The value at the path, or null if not found.
*/
@Nullable Object get(@NotNull String path);
/**
* Get the value of the path for specific type,
* if the path does not exist, return null.
*
* @param path The path to get the value from.
* @param type The type class of the value
* @param <T> The type of the value
* @return The value at the path, or the default value if not found.
*/
default @Nullable <T> T get(@NotNull String path, @NotNull Class<T> type) {
return get(path, null, type);
}
/**
* Get the value of the path using a parser function,
* if the path does not exist, return NULL.
*
* @param path The path to get the value from.
* @param parser The function to parse the value
* @param <T> The type of the value
* @return The value at the path, or null if not found.
*/
default @Nullable <T> T get(@NotNull String path, @NotNull DataFunction<@Nullable Object, T> parser) {
return get(path, null, parser);
}
/**
* Get the value of the path for specific type,
* if the path does not exist, return the default value.
*
* @param path The path to get the value from.
* @param defaults The default value to return if the path does not exist.
* @param clazz The type class of the value
* @param <T> The type of the value
* @return The value at the path, or the default value if not found.
*/
@Contract("_,!null,_->!null")
default @Nullable <T> T get(@NotNull String path, @Nullable T defaults, @NotNull Class<T> clazz) {
return get(path, defaults, DataFunction.castObject(clazz));
}
/**
* Get the value of the path using a parser function,
* if the path does not exist, return the default value.
*
* @param path The path to get the value from.
* @param defaultValue The default value to return if the path does not exist.
* @param parser The function to parse the value
* @param <T> The type of the value
* @return The value at the path, or the default value if not found.
*/
@Contract("_,!null,_->!null")
default @Nullable <T> T get(@NotNull String path, @Nullable T defaultValue,
@NotNull DataFunction<Object, T> parser) {
Object value = get(path);
if (value != null) {
try {
return parser.handle(value);
} catch (Exception e) {
e.printStackTrace();
}
}
return defaultValue;
}
/**
* Predicate the value of given path is a {@link Boolean}.
*
* @param path The path to check.
* @return True if the value is present and is a boolean, false otherwise.
*/
default boolean isBoolean(@NotNull String path) {
return isType(path, Boolean.class);
}
/**
* Get the value as a {@link Boolean} from the specified path.
*
* @param path The path to get the boolean.
* @return The boolean if the path exists and is a boolean, otherwise false.
*/
default boolean getBoolean(@NotNull String path) {
return getBoolean(path, null);
}
/**
* Get the value as a {@link Boolean} from the specified path.
*
* @param path The path to get the boolean.
* @param def The default value to return if the path does not exist.
* @return The boolean if the path exists and is a boolean, otherwise the default value.
*/
@Contract("_, !null -> !null")
default @Nullable Boolean getBoolean(@NotNull String path, @Nullable Boolean def) {
return get(path, def, DataFunction.booleanValue());
}
/**
* Predicate the value of given path is a {@link Byte}.
*
* @param path The path to check.
* @return True if the value is present and is a byte, false otherwise.
*/
default @Nullable Boolean isByte(@NotNull String path) {
return isType(path, Byte.class);
}
/**
* Get the value as a {@link Byte} from the specified path.
*
* @param path The path to get the byte.
* @return The byte if the path exists and is a byte, otherwise 0.
*/
default @Nullable Byte getByte(@NotNull String path) {
return getByte(path, null);
}
/**
* Get the value as a {@link Byte} from the specified path.
*
* @param path The path to get the byte.
* @param def The default value to return if the path does not exist.
* @return The byte if the path exists and is a byte, otherwise the default value.
*/
@Contract("_, !null -> !null")
default @Nullable Byte getByte(@NotNull String path, @Nullable Byte def) {
return get(path, def, DataFunction.byteValue());
}
/**
* Predicate the value of given path is a {@link Short}.
*
* @param path The path to check.
* @return True if the value is present and is a short, false otherwise.
*/
default boolean isShort(@NotNull String path) {
return isType(path, Short.class);
}
/**
* Get the value as a {@link Short} from the specified path.
*
* @param path The path to get the short.
* @return The short if the path exists and is a short, otherwise 0.
*/
default @Nullable Short getShort(@NotNull String path) {
return getShort(path, null);
}
/**
* Get the value as a {@link Short} from the specified path.
*
* @param path The path to get the short.
* @param def The default value to return if the path does not exist.
* @return The short if the path exists and is a short, otherwise the default value.
*/
@Contract("_, !null -> !null")
default @Nullable Short getShort(@NotNull String path, @Nullable Short def) {
return get(path, def, DataFunction.shortValue());
}
/**
* Predicate the value of given path is a {@link Integer}.
*
* @param path The path to check.
* @return True if the value is present and is an int, false otherwise.
*/
default boolean isInt(@NotNull String path) {
return isType(path, Integer.class);
}
/**
* Get the value as a {@link Integer} from the specified path.
*
* @param path The path to get the int.
* @return The int if the path exists and is an int, otherwise 0.
*/
default @Nullable Integer getInt(@NotNull String path) {
return getInt(path, null);
}
/**
* Get the value as a {@link Integer} from the specified path.
*
* @param path The path to get the int.
* @param def The default value to return if the path does not exist.
* @return The int if the path exists and is an int, otherwise the default value.
*/
@Contract("_, !null -> !null")
default @Nullable Integer getInt(@NotNull String path, @Nullable Integer def) {
return get(path, def, DataFunction.intValue());
}
/**
* Predicate the value of given path is a {@link Long}.F
*
* @param path The path to check.
* @return True if the value is present and is a long, false otherwise.
*/
default boolean isLong(@NotNull String path) {
return isType(path, Long.class);
}
/**
* Get the value as a {@link Long} from the specified path.
*
* @param path The path to get the long.
* @return The long if the path exists and is a long, otherwise 0.
*/
default @Nullable Long getLong(@NotNull String path) {
return getLong(path, null);
}
/**
* Get the value as a {@link Long} from the specified path.
*
* @param path The path to get the long.
* @param def The default value to return if the path does not exist.
* @return The long if the path exists and is a long, otherwise the default value.
*/
@Contract("_, !null -> !null")
default @Nullable Long getLong(@NotNull String path, @Nullable Long def) {
return get(path, def, DataFunction.longValue());
}
/**
* Predicate the value of given path is a {@link Float}.
*
* @param path The path to check.
* @return True if the value is present and is a float, false otherwise.
*/
default boolean isFloat(@NotNull String path) {
return isType(path, Float.class);
}
/**
* Get the value as a {@link Float} from the specified path.
*
* @param path The path to get the float.
* @return The float if the path exists and is a float, otherwise 0.
*/
default @Nullable Float getFloat(@NotNull String path) {
return getFloat(path, null);
}
/**
* Get the value as a {@link Float} from the specified path.
*
* @param path The path to get the float.
* @param def The default value to return if the path does not exist.
* @return The float if the path exists and is a float, otherwise the default value.
*/
@Contract("_, !null -> !null")
default @Nullable Float getFloat(@NotNull String path, @Nullable Float def) {
return get(path, def, DataFunction.floatValue());
}
/**
* Predicate the value of given path is a {@link Double}.
*
* @param path The path to check.
* @return True if the value is present and is a double, false otherwise.
*/
default boolean isDouble(@NotNull String path) {
return isType(path, Double.class);
}
/**
* Get the value as a {@link Double} from the specified path.
*
* @param path The path to get the double.
* @return The double if the path exists and is a double, otherwise 0.
*/
default @Nullable Double getDouble(@NotNull String path) {
return getDouble(path, null);
}
/**
* Get the value as a {@link Double} from the specified path.
*
* @param path The path to get the double.
* @param def The default value to return if the path does not exist.
* @return The double if the path exists and is a double, otherwise the default value.
*/
@Contract("_, !null -> !null")
default @Nullable Double getDouble(@NotNull String path, @Nullable Double def) {
return get(path, def, DataFunction.doubleValue());
}
/**
* Predicate the value of given path is a {@link Character}.
*
* @param path The path to check.
* @return True if the value is present and is a char, false otherwise.
*/
default boolean isChar(@NotNull String path) {
return isType(path, Character.class);
}
/**
* Get the value as a {@link Character} from the specified path.
*
* @param path The path to get the char.
* @return The char if the path exists and is a char, otherwise null.
*/
default @Nullable Character getChar(@NotNull String path) {
return getChar(path, null);
}
/**
* Get the value as a {@link Character} from the specified path.
*
* @param path The path to get the char.
* @param def The default value to return if the path does not exist.
* @return The char if the path exists and is a char, otherwise the default value.
*/
@Contract("_, !null -> !null")
default @Nullable Character getChar(@NotNull String path, @Nullable Character def) {
return get(path, def, Character.class);
}
/**
* Predicate the value of given path is a {@link String}.
*
* @param path The path to check.
* @return True if the value is present and is a string, false otherwise.
*/
default boolean isString(@NotNull String path) {
return isType(path, String.class);
}
/**
* Get the value as a {@link String} from the specified path.
*
* @param path The path to get the string.
* @return The string if the path exists and is a string, otherwise null.
*/
default @Nullable String getString(@NotNull String path) {
return getString(path, null);
}
/**
* Get the value as a {@link String} from the specified path.
*
* @param path The path to get the string.
* @param def The default value to return if the path does not exist.
* @return The string if the path exists and is a string, otherwise the default value.
*/
@Contract("_, !null -> !null")
default @Nullable String getString(@NotNull String path, @Nullable String def) {
return get(path, def, String.class);
}
/**
* Get a list of values from current section
* <p>
* If the path does not exist, an empty list will be returned
* <br>Any changes please use {@link #set(String, Object)} after changes
*
* @param path The path to get the list from
* @param parser The function to parse the values
* @param <V> The type of the values
* @return The list of values
*/
default <V> @NotNull List<V> getList(@NotNull String path, @NotNull DataFunction<Object, V> parser) {
return getCollection(path, ArrayList::new, parser);
}
/**
* Get a list of strings from current section
* <p> Limitations see {@link #getList(String, DataFunction)}
*
* @param path The path to get the list from
* @return The list of strings
*/
default @NotNull List<String> getStringList(@NotNull String path) {
return getList(path, DataFunction.castToString());
}
/**
* Get a list of integer from current section
* <p> Limitations see {@link #getList(String, DataFunction)}
*
* @param path The path to get the list from
* @return The list of int values
*/
default @NotNull List<Integer> getIntegerList(@NotNull String path) {
return getList(path, DataFunction.intValue());
}
/**
* Get a list of long from current section
* <p> Limitations see {@link #getList(String, DataFunction)}
*
* @param path The path to get the list from
* @return The list of long values
*/
default @NotNull List<Long> getLongList(@NotNull String path) {
return getList(path, DataFunction.longValue());
}
/**
* Get a list of double from current section
* <p> Limitations see {@link #getList(String, DataFunction)}
*
* @param path The path to get the list from
* @return The list of doubles
*/
default @NotNull List<Double> getDoubleList(@NotNull String path) {
return getList(path, DataFunction.doubleValue());
}
/**
* Get a list of floats from current section
* <p> Limitations see {@link #getList(String, DataFunction)}
*
* @param path The path to get the list from
* @return The list of floats
*/
default @NotNull List<Float> getFloatList(@NotNull String path) {
return getList(path, DataFunction.floatValue());
}
/**
* Get a list of bytes from current section
* <p> Limitations see {@link #getList(String, DataFunction)}
*
* @param path The path to get the list from
* @return The list of bytes
*/
default @NotNull List<Byte> getByteList(@NotNull String path) {
return getList(path, DataFunction.byteValue());
}
/**
* Get a list of char from current section
* <p> Limitations see {@link #getList(String, DataFunction)}
*
* @param path The path to get the list from
* @return The list of char
*/
default @NotNull List<Character> getCharList(@NotNull String path) {
return getList(path, DataFunction.castObject(Character.class));
}
/**
* Get a list of {@link ConfigureSection} from current section
*
* @param path The path to get the list from
* @return The list of {@link ConfigureSection}
*/
default @NotNull List<ConfigureSection> getSectionList(@NotNull String path) {
return getList(path, obj -> {
if (obj instanceof ConfigureSection) {
return (ConfigureSection) obj;
} else if (obj instanceof Map) {
return createSection(childPath(path), (Map<?, ?>) obj);
}
return null;
});
}
/**
* Get the specific type of collection from current section.
*
* @param path The path to get the collection from
* @param constructor The constructor of the collection
* @param parser The function to parse the values
* @param <T> The type of the values
* @param <C> The type of the collection
* @return The collection of values
*/
default <T, C extends Collection<T>> @NotNull C getCollection(@NotNull String path,
@NotNull Supplier<C> constructor,
@NotNull DataFunction<Object, T> parser) {
return parseCollection(getList(path), constructor, parser);
}
/**
* Get the specific type of steam from current section.
*
* @param path The path to get the stream from
* @return The stream of values
*/
default @NotNull Stream<?> stream(@NotNull String path) {
List<?> values = getList(path);
return values == null ? Stream.empty() : values.stream();
}
/**
* Get the specific type of steam from current section.
*
* @param path The path to get the stream from
* @param parser The function to parse the values
* @param <T> The type of the values
* @return The stream of values
*/
default <T> @NotNull Stream<T> stream(@NotNull String path, @NotNull Function<Object, T> parser) {
return stream(path).map(parser);
}
default String childPath(String path) {
int index = path.indexOf(pathSeparator());
return (index == -1) ? path : path.substring(index + 1);
}
static <T, C extends Collection<T>> @NotNull C parseCollection(
@Nullable List<?> data,
@NotNull Supplier<C> constructor,
@NotNull DataFunction<Object, T> parser
) {
C values = constructor.get();
if (data == null) return values;
for (Object obj : data) {
try {
values.add(parser.handle(obj));
} catch (Exception ignored) {
}
}
return values;
}
}
@@ -0,0 +1,135 @@
package cc.carm.lib.configuration.source.section;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import cc.carm.lib.configuration.source.option.StandardOptions;
import org.jetbrains.annotations.*;
import java.util.Map;
import java.util.Set;
/**
* ConfigureSource represents the source of configuration,
* which can be a file, a database, or any other source.
*
* @param <SECTION> The type of the root section.
* @param <ORIGINAL> The original configuration object.
* @param <SELF> The type of the source itself, for further implement support.
* @see ConfigureSection
*/
public abstract class ConfigureSource<
SECTION extends ConfigureSection, ORIGINAL,
SELF extends ConfigureSource<SECTION, ORIGINAL, SELF>>
implements ConfigureSection {
protected final @NotNull ConfigurationHolder<? extends SELF> holder;
protected long lastUpdateMillis;
protected ConfigureSource(@NotNull ConfigurationHolder<? extends SELF> holder, long lastUpdateMillis) {
this.holder = holder;
this.lastUpdateMillis = lastUpdateMillis;
}
public @NotNull ConfigurationHolder<? extends SELF> holder() {
return holder;
}
public void reload() throws Exception {
onReload(); // 调用重写的Reload方法
this.lastUpdateMillis = System.currentTimeMillis();
}
@Contract(pure = true)
@ApiStatus.Internal
protected abstract @NotNull SELF self();
/**
* @return The original configuration object.
*/
@Contract(pure = true)
public abstract @NotNull ORIGINAL original();
/**
* @return The root {@link ConfigureSection}, which represents the entire configuration.
*/
public abstract @NotNull SECTION section();
/**
* Save the whole configuration.
*
* @throws Exception If any error occurs while saving.
*/
public abstract void save() throws Exception;
/**
* Reload the configuration.
* <br>This used for implementation, for external usage, use {@link #reload()}
*
* @throws Exception If any error occurs while reloading.
*/
@ApiStatus.OverrideOnly
protected abstract void onReload() throws Exception;
public char pathSeparator() {
return holder().options().get(StandardOptions.PATH_SEPARATOR);
}
public long getLastUpdateMillis() {
return this.lastUpdateMillis;
}
public boolean isExpired(long parsedTime) {
return getLastUpdateMillis() > parsedTime;
}
/**
* Source also represents the root section, so it has no parent
*
* @return null
*/
@Override
@Contract(pure = true, value = "->null")
public @Nullable ConfigureSection parent() {
return null;
}
@Override
public @NotNull String path() {
return "";
}
@Override
public @NotNull Map<String, Object> getValues(boolean deep) {
return section().getValues(deep);
}
@Override
public @NotNull @UnmodifiableView Set<String> getKeys(boolean deep) {
return section().getKeys(deep);
}
@Override
public @NotNull @UnmodifiableView Map<String, Object> asMap() {
return section().asMap();
}
@Override
public @NotNull ConfigureSection createSection(@NotNull String path, @NotNull Map<?, ?> data) {
return section().createSection(path, data);
}
@Override
public void set(@NotNull String path, @Nullable Object value) {
section().set(path, value);
}
@Override
public void remove(@NotNull String path) {
section().remove(path);
}
@Override
public @Nullable Object get(@NotNull String path) {
return section().get(path);
}
}
@@ -0,0 +1,153 @@
package cc.carm.lib.configuration.value;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
import java.util.Optional;
/**
* Represents a configurable value with type safety and null-handling capabilities.
* <p>
* This abstract class provides core functionalities for managing configuration values,
* including value retrieval with fallback defaults, null safety enforcement, and value
* persistence controls. It serves as the foundation for type-specific configuration
* implementations.
* </p>
*
* <h3>Functions:</h3>
* <ul>
* <li>Type-safe value access through {@link #get()} and {@link #optional()}</li>
* <li>Default value fallback via {@link #getOrDefault()}</li>
* <li>Null-safety enforcement with {@link #resolve()} and {@link #getNotNull()}</li>
* <li>Default value initialization through {@link #setDefault()}</li>
* <li>Value comparison with {@link #isDefault()}</li>
* </ul>
*
* <h3>Persistence Behavior:</h3>
* Value modifications via {@link #set(Object)} or {@link #setDefault()} methods
* <b>do NOT automatically persist</b> to configuration sources. Explicit calls to
* {@link ConfigurationHolder#save()} are required for permanent storage.
*
* @see ValueManifest Base class providing metadata and default value handling
* @see ConfigurationHolder Responsible for configuration source persistence
*/
public abstract class ConfigValue<T, U> extends ValueManifest<T, U> {
protected ConfigValue(@NotNull ValueManifest<T, U> manifest) {
super(manifest);
}
/**
* Gets the configured value (i.e., the value read from the source).
* <br> If no default value was written during initialization, you can use
* the {@link #getOrDefault()} method to obtain the default value when this value is empty.
*
* @return Configured value
*/
public abstract @Nullable T get();
/**
* Gets the configured value, or returns the default value if not present.
*
* @return Configured value or default value
*/
public T getOrDefault() {
return getOr(defaults());
}
/**
* Gets the configured value, or returns the specified default value if not present.
*
* @param defaults The default value to return if the configured value is not present
* @return Configured value or specified default value
*/
@Contract("!null -> !null")
public T getOr(T defaults) {
return optional().orElse(defaults);
}
/**
* Gets the non-null value of this configuration.
*
* @return Non-null value
* @throws NullPointerException Thrown when the corresponding data is null
*/
public @NotNull T resolve() {
return Objects.requireNonNull(getOrDefault(), "Value(" + type() + ") @[" + path() + "] is null.");
}
/**
* Gets the non-null value of this configuration.
*
* @return Non-null value
* @throws NullPointerException Thrown when the corresponding data is null
* @see #resolve() for a more descriptive function
*/
public @NotNull T getNotNull() {
return resolve();
}
/**
* Gets the value of this configuration as an {@link Optional}.
*
* @return {@link Optional} value
*/
public @NotNull Optional<@Nullable T> optional() {
return Optional.ofNullable(get());
}
/**
* Sets the value of this configuration.
* <br> After setting, the configuration file will NOT be saved automatically.
* To save, call {@link ConfigurationHolder#save()}.
*
* @param value The value to set
*/
public abstract void set(@Nullable T value);
/**
* Initializes the default value for this configuration.
* <br> After setting, the configuration file will NOT be saved automatically.
* To save, call {@link ConfigurationHolder#save()}.
*/
public void setDefault() {
setDefault(false);
}
/**
* Sets the configuration value to its default.
* <br> After setting, the configuration file will NOT be saved automatically.
* To save, call {@link ConfigurationHolder#save()}.
*
* @param override Whether to overwrite existing configured value
*/
public void setDefault(boolean override) {
if (config().contains(path()) && !override) return; // Skip if the value is already set
set(defaults()); // Set the default value
}
/**
* Checks if the loaded configuration value matches the default value.
*
* @return Whether the current value is the default value
*/
public boolean isDefault() {
return Objects.equals(defaults(), get());
}
/**
* Try to save the configuration.
* <br>To save multiple modifications,
* it is recommended to call {@link ConfigurationHolder#save()}
* after all modifications are completed instead of this.
*
* @throws Exception Thrown when an error occurs during saving
*/
public void save() throws Exception {
holder().save();
}
}
@@ -0,0 +1,163 @@
package cc.carm.lib.configuration.value;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.function.ValueValidator;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder;
import cc.carm.lib.configuration.source.section.ConfigureSource;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
public class ValueManifest<TYPE, UNIT> {
protected final @NotNull ValueType<TYPE> type;
protected final @NotNull BiConsumer<@NotNull ConfigurationHolder<?>, @NotNull String> initializer;
protected @Nullable ConfigurationHolder<?> holder;
protected @Nullable String path; // Section path
protected @NotNull ValueValidator<UNIT> validator;
protected @NotNull Supplier<@Nullable TYPE> defaultSupplier;
public ValueManifest(@NotNull ValueType<TYPE> type) {
this(type, () -> null, ValueValidator.none(), EMPTY_INITIALIZER, null, null);
}
public ValueManifest(@NotNull TYPE defaultValue) {
this(ValueType.of(defaultValue), () -> defaultValue);
}
public ValueManifest(@NotNull ValueType<TYPE> type, @NotNull Supplier<@Nullable TYPE> defaultSupplier) {
this(type, defaultSupplier, ValueValidator.none(), EMPTY_INITIALIZER, null, null);
}
public ValueManifest(@NotNull ValueType<TYPE> type,
@NotNull Supplier<@Nullable TYPE> defaultSupplier,
@NotNull ValueValidator<UNIT> validator) {
this(type, defaultSupplier, validator, EMPTY_INITIALIZER, null, null);
}
public ValueManifest(@NotNull ValueType<TYPE> type, @NotNull Supplier<@Nullable TYPE> defaultSupplier,
@NotNull ValueValidator<UNIT> validator,
@NotNull BiConsumer<@NotNull ConfigurationHolder<?>, @NotNull String> initializer) {
this(type, defaultSupplier, validator, initializer, null, null);
}
public ValueManifest(@NotNull ValueType<TYPE> type,
@NotNull Supplier<@Nullable TYPE> defaultSupplier,
@NotNull ValueValidator<UNIT> validator,
@NotNull BiConsumer<@NotNull ConfigurationHolder<?>, @NotNull String> initializer,
@Nullable ConfigurationHolder<?> holder, @Nullable String path) {
this.type = type;
this.validator = validator;
this.initializer = initializer;
this.defaultSupplier = defaultSupplier;
this.holder = holder;
this.path = path;
initialize();
}
protected ValueManifest(@NotNull ValueManifest<TYPE, UNIT> manifest) {
this(manifest.type, manifest.defaultSupplier, manifest.validator, manifest.initializer, manifest.holder, manifest.path);
}
public void initialize(@NotNull ConfigurationHolder<?> holder, @NotNull String path) {
this.holder = holder;
this.path = path;
initialize();
}
protected void initialize() {
if (holder != null && path != null) this.initializer.accept(holder, path);
}
public @NotNull ValueType<TYPE> type() {
return this.type;
}
public void holder(@NotNull ConfigurationHolder<?> holder) {
this.holder = holder;
}
public void path(@NotNull String path) {
this.path = path;
}
public @Nullable TYPE defaults() {
return this.defaultSupplier.get();
}
public void defaults(@Nullable TYPE defaultValue) {
defaults(() -> defaultValue);
}
public void defaults(@NotNull Supplier<@Nullable TYPE> defaultValue) {
this.defaultSupplier = defaultValue;
}
public boolean hasDefaults() {
return defaults() != null;
}
public @NotNull ValueValidator<UNIT> validator() {
return this.validator;
}
public void validator(@NotNull ValueValidator<UNIT> validator) {
this.validator = validator;
}
public void validate(@NotNull ValueValidator<UNIT> validator) {
validator(this.validator.and(validator));
}
protected UNIT withValidated(@Nullable UNIT value) throws Exception {
validator.validate(holder(), value);
return value;
}
public @NotNull String path() {
if (path != null) return path;
else throw new IllegalStateException("No section path provided for Value(" + type() + ").");
}
public @NotNull ConfigurationHolder<?> holder() {
if (this.holder != null) return this.holder;
throw new IllegalStateException("Value(" + type() + ") does not have a provider.");
}
public @NotNull ConfigureSource<?, ?, ?> config() {
return holder().config();
}
public @NotNull ConfigurationMetaHolder metadata() {
return holder().metadata(path());
}
@ApiStatus.Internal
protected @Nullable Object getData() {
return config().get(path());
}
@ApiStatus.Internal
protected void setData(@Nullable Object value) {
config().set(path(), value);
}
protected void throwing(@NotNull Throwable throwable) {
throwing(path, throwable);
}
protected void throwing(@NotNull String path, @NotNull Throwable throwable) {
if (holder == null) throwable.printStackTrace();
else holder.throwing(path, throwable);
}
private static final @NotNull BiConsumer<@NotNull ConfigurationHolder<?>, @NotNull String> EMPTY_INITIALIZER = (provider, valuePath) -> {
};
}
@@ -0,0 +1,85 @@
package cc.carm.lib.configuration.value.impl;
import cc.carm.lib.configuration.adapter.ValueAdapter;
import cc.carm.lib.configuration.adapter.ValueParser;
import cc.carm.lib.configuration.adapter.ValueSerializer;
import cc.carm.lib.configuration.value.ConfigValue;
import cc.carm.lib.configuration.value.ValueManifest;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class CachedConfigValue<T, U> extends ConfigValue<T, U> {
protected @Nullable T cachedValue;
protected long parsedTime = -1;
protected CachedConfigValue(@NotNull ValueManifest<T, U> manifest) {
super(manifest);
}
protected T updateCache(T value) {
this.parsedTime = System.currentTimeMillis();
this.cachedValue = value;
return getCachedValue();
}
public @Nullable T getCachedValue() {
return cachedValue;
}
public boolean cacheExpired() {
return this.parsedTime <= 0 || config().isExpired(this.parsedTime);
}
protected final T getDefaultFirst(@Nullable T value) {
return updateCache(this.defaults() == null ? value : this.defaults());
}
/**
* Get the cached value or the default value if the cached value is null
*
* @return the cached value or the default value
*/
protected @Nullable T getCachedOrDefault() {
return getCachedOrDefault(null);
}
/**
* Get the cached value or the default value if the cached value is null
*
* @param emptyValue the value to return if the cached value and the default value are null
* @return the cached value or the default value
*/
@Contract("!null->!null")
protected T getCachedOrDefault(@Nullable T emptyValue) {
if (getCachedValue() != null) return getCachedValue();
else if (defaults() != null) return defaults();
else return emptyValue;
}
/**
* @param adapter Value adapter
* @param <O> Base object type
* @return Value's parser, parse base object to value.
*/
protected <O> @Nullable ValueParser<O> parserFor(@NotNull ValueAdapter<O> adapter) {
if (adapter.parser() != null) return adapter.parser();
ValueAdapter<O> registered = holder().adapters().adapterOf(adapter.type());
if (registered == null) return null;
return registered.parser();
}
/**
* @param adapter Value adapter
* @param <O> Base object type
* @return Value's serializer, parse value to base object.
*/
protected <O> @Nullable ValueSerializer<O> serializerFor(@NotNull ValueAdapter<O> adapter) {
if (adapter.serializer() != null) return adapter.serializer();
ValueAdapter<O> registered = holder().adapters().adapterOf(adapter.type());
if (registered == null) return null;
return registered.serializer();
}
}
@@ -0,0 +1,210 @@
package cc.carm.lib.configuration.value.impl;
import cc.carm.lib.configuration.adapter.ValueAdapter;
import cc.carm.lib.configuration.adapter.ValueParser;
import cc.carm.lib.configuration.adapter.ValueSerializer;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.value.ValueManifest;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* Base implementation of a collection config value, like {@link List} or {@link Set}.
*
* @param <V> Value type
* @param <C> Collection type
* @param <SELF> Self reference type (used for internal call or recursive generics)
*/
public abstract class CollectionConfigValue<
V, C extends Collection<V>,
SELF extends CollectionConfigValue<V, C, SELF>
> extends CachedConfigValue<C, V> implements Collection<V> {
protected final @NotNull Supplier<? extends C> constructor;
protected final @NotNull ValueAdapter<V> paramAdapter;
public CollectionConfigValue(@NotNull ValueManifest<C, V> manifest,
@NotNull Supplier<? extends C> constructor,
@NotNull ValueAdapter<V> paramAdapter) {
super(manifest);
this.constructor = constructor;
this.paramAdapter = paramAdapter;
}
/**
* @return Adapter of this value.
*/
public @NotNull ValueAdapter<V> adapter() {
return this.paramAdapter;
}
public @NotNull ValueType<V> paramType() {
return adapter().type();
}
/**
* @return Value's parser, parse base object to value.
*/
public @Nullable ValueParser<V> parser() {
return parserFor(adapter());
}
/**
* @return Value's serializer, parse value to base object.
*/
public @Nullable ValueSerializer<V> serializer() {
return serializerFor(adapter());
}
private @NotNull C createCollection() {
return constructor.get();
}
@Override
public @NotNull C get() {
if (!cacheExpired()) return getCachedOrDefault(createCollection());
// Data that is outdated and needs to be parsed again.
C set = createCollection();
try {
List<?> data = config().contains(path()) ? config().getList(path()) : null;
if (data == null) return getDefaultFirst(set);
ValueParser<V> parser = parser();
if (parser == null) return getDefaultFirst(set);
int i = 0;
for (Object dataVal : data) {
if (dataVal == null) continue;
try {
set.add(withValidated(parser.parse(holder(), paramType(), dataVal)));
} catch (Exception e) {
throwing(path + "[" + i + "]", e);
}
}
} catch (Exception ex) {
throwing(ex);
}
return updateCache(set);
}
@Override
public void set(@Nullable C collection) {
updateCache(collection);
if (collection == null) {
setData(null);
return;
}
ValueSerializer<V> serializer = serializer();
if (serializer == null) return;
List<Object> data = new ArrayList<>();
for (V val : collection) {
if (val == null) continue;
try {
data.add(serializer.serialize(holder(), paramType(), withValidated(val)));
} catch (Exception ex) {
throwing(ex);
}
}
setData(data);
}
public @NotNull C copy() {
C other = createCollection();
other.addAll(resolve());
return other;
}
public abstract @NotNull SELF self();
public <T> @NotNull T handle(Function<C, T> function) {
C list = resolve();
T result = function.apply(list);
set(list);
return result;
}
public @NotNull SELF modify(Consumer<C> consumer) {
C list = resolve();
consumer.accept(list);
set(list);
return self();
}
@Override
public int size() {
return resolve().size();
}
@Override
public boolean isEmpty() {
return resolve().isEmpty();
}
@Override
public boolean contains(Object o) {
return resolve().contains(o);
}
@NotNull
@Override
public Iterator<V> iterator() {
return resolve().iterator();
}
@NotNull
@Override
public Object @NotNull [] toArray() {
return resolve().toArray();
}
@NotNull
@Override
public <T> T @NotNull [] toArray(@NotNull T[] a) {
return resolve().toArray(a);
}
@Override
public boolean containsAll(@NotNull Collection<?> c) {
return new HashSet<>(resolve()).containsAll(c);
}
@Override
public boolean add(V v) {
handle(list -> list.add(v));
return true;
}
@Override
public boolean addAll(@NotNull Collection<? extends V> c) {
return handle(list -> list.addAll(c));
}
@Override
public boolean remove(Object o) {
return handle(list -> list.remove(o));
}
@Override
public boolean removeAll(@NotNull Collection<?> c) {
return handle(list -> list.removeAll(c));
}
@Override
public boolean retainAll(@NotNull Collection<?> c) {
return handle(list -> list.retainAll(c));
}
@Override
public void clear() {
modify(Collection::clear);
}
}
@@ -0,0 +1,108 @@
package cc.carm.lib.configuration.value.standard;
import cc.carm.lib.configuration.adapter.ValueAdapter;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.builder.collection.SimpleCollectionCreator;
import cc.carm.lib.configuration.builder.list.ConfigListCreator;
import cc.carm.lib.configuration.value.ValueManifest;
import cc.carm.lib.configuration.value.impl.CollectionConfigValue;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.function.Supplier;
public class ConfiguredList<V> extends CollectionConfigValue<V, List<V>, ConfiguredList<V>> implements List<V> {
public static <T> @NotNull ConfigListCreator<T> builderOf(@NotNull Class<T> type) {
return builderOf(ValueType.of(type));
}
public static <T> @NotNull ConfigListCreator<T> builderOf(@NotNull ValueType<T> type) {
return new ConfigListCreator<>(type);
}
public static <T>
@NotNull SimpleCollectionCreator.Source<Object, T, List<T>, ConfiguredList<T>> with(@NotNull Class<T> registeredType) {
return with(ValueType.of(registeredType));
}
public static <T> @NotNull SimpleCollectionCreator.Source<Object, T, List<T>, ConfiguredList<T>> with(@NotNull ValueType<T> registeredType) {
return builderOf(registeredType).fromObject();
}
@SafeVarargs
public static <T> @NotNull ConfiguredList<T> of(@NotNull T value, @NotNull T... values) {
List<T> list = new ArrayList<>();
list.add(value);
Collections.addAll(list, values);
return with(ValueType.of(value)).defaults(list).build();
}
public ConfiguredList(@NotNull ValueManifest<List<V>, V> manifest,
@NotNull Supplier<? extends List<V>> constructor,
@NotNull ValueAdapter<V> paramAdapter) {
super(manifest, constructor, paramAdapter);
}
@Override
public V get(int index) {
return resolve().get(index);
}
@Override
public @NotNull ConfiguredList<V> self() {
return this;
}
@Override
public V set(int index, V element) {
return handle(list -> list.set(index, element));
}
@Override
public void add(int index, V element) {
modify(list -> list.add(index, element));
}
@Override
public boolean addAll(int index, @NotNull Collection<? extends V> c) {
return handle(list -> list.addAll(index, c));
}
@Override
public V remove(int index) {
return handle(list -> list.remove(index));
}
@Override
public int indexOf(Object o) {
return resolve().indexOf(o);
}
@Override
public int lastIndexOf(Object o) {
return resolve().lastIndexOf(o);
}
@NotNull
@Override
public ListIterator<V> listIterator() {
return resolve().listIterator();
}
@NotNull
@Override
public ListIterator<V> listIterator(int index) {
return resolve().listIterator(index);
}
@NotNull
@Override
public List<V> subList(int fromIndex, int toIndex) {
return resolve().subList(fromIndex, toIndex);
}
}

Some files were not shown because too many files have changed in this diff Show More