mirror of
https://github.com/CarmJos/EasyConfiguration.git
synced 2026-06-04 18:48:20 +08:00
Compare commits
62 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a9f3d829bd | |||
| 8eefba5159 | |||
| 01e20df559 | |||
| 35398ab741 | |||
| 6f97166192 | |||
| ccd239ad6b | |||
| 69b27476bc | |||
| 0651cac6b0 | |||
| 1a1efad283 | |||
| 3c1ba61b61 | |||
| 1a3e84a787 | |||
| 00228db2c4 | |||
| 0fddfe28af | |||
| 4a17089da0 | |||
| 8faa7b1c24 | |||
| 5e525428fe | |||
| bc0dfd5698 | |||
| dc28d743db | |||
| f61294c5f3 | |||
| 6883a464db | |||
| bcdf0d9bd1 | |||
| 5f89ff4db7 | |||
| d6f4970277 | |||
| c045ca1489 | |||
| ceea900b08 | |||
| 85bacb24f3 | |||
| 6b3a353fcc | |||
| 2c026fc0b0 | |||
| f8b4bbd3a9 | |||
| e9a0f0ff30 | |||
| e3fe6e7c80 | |||
| c179fa2ccd | |||
| 390815b790 | |||
| 760ac815df | |||
| 216050a701 | |||
| 6d0ee35197 | |||
| 494491cf94 | |||
| 00e88b50ff | |||
| 033236c89b | |||
| 791fa6e5b4 | |||
| 51c287a0a7 | |||
| ab2f898164 | |||
| 4f4b203240 | |||
| c94fef893f | |||
| c2a08c6c72 | |||
| dd7a6c819f | |||
| e9c010981e | |||
| 78d52e1aae | |||
| 42ccc23347 | |||
| 85578e3d8c | |||
| dc4d3664d3 | |||
| 2e4cb5480a | |||
| 4b7a7aeae7 | |||
| 132ca81635 | |||
| 80747ac922 | |||
| 0d10a06547 | |||
| 0bda97d82a | |||
| a13ea7569c | |||
| c9f488c932 | |||
| 72584f66ac | |||
| 05e055a6f1 | |||
| e52195a8bb |
@@ -6,4 +6,4 @@
|
|||||||
|
|
||||||
若您也想通过 [Github Actions](https://docs.github.com/en/actions/learn-github-actions)
|
若您也想通过 [Github Actions](https://docs.github.com/en/actions/learn-github-actions)
|
||||||
自动部署项目的Javadoc到 [Github Pages](https://pages.github.com/) ,
|
自动部署项目的Javadoc到 [Github Pages](https://pages.github.com/) ,
|
||||||
可以参考我的文章 [《自动部署Javadoc到Github Pages》](https://pages.carm.cc/doc/javadoc-in-github.html) 。
|
可以参考我的文章 [《自动部署Javadoc到Github Pages》](https://pages.carm.cc/doc/javadoc-in-github.html) 。
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# 欢迎使用 EasyConfiguration !
|
||||||
|
|
||||||
|
这个项目刚刚创建,详细的Javadoc与开发指南还在补充,请给我一点时间~
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
|
# 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
|
# 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:
|
on:
|
||||||
# 支持手动触发构建
|
# 支持手动触发构建
|
||||||
@@ -72,7 +72,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cd docs
|
cd docs
|
||||||
git init
|
git init
|
||||||
git remote add origin git@github.com:CarmJos/EasySQL.git
|
git remote add origin git@github.com:CarmJos/EasyConfiguration.git
|
||||||
git checkout -b gh-pages
|
git checkout -b gh-pages
|
||||||
git add -A
|
git add -A
|
||||||
git commit -m "API Document generated."
|
git commit -m "API Document generated."
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
|
# 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
|
# 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:
|
on:
|
||||||
# 支持手动触发构建
|
# 支持手动触发构建
|
||||||
|
|||||||
@@ -1,21 +1,165 @@
|
|||||||
MIT License
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
Copyright (c) 2022 Carm
|
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.
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
This version of the GNU Lesser General Public License incorporates
|
||||||
copies or substantial portions of the Software.
|
the terms and conditions of version 3 of the GNU General Public
|
||||||
|
License, supplemented by the additional permissions listed below.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
0. Additional Definitions.
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
General Public License.
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
"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.
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
# EasyConfiguration
|
# EasyConfiguration
|
||||||
|
|
||||||
[](https://github.com/CarmJos/EasyConfiguration/releases)
|
[](https://github.com/CarmJos/EasyConfiguration/releases)
|
||||||
[](https://opensource.org/licenses/MIT)
|
[](https://www.gnu.org/licenses/lgpl-3.0.html)
|
||||||
[](https://github.com/CarmJos/EasyConfiguration/actions/workflows/maven.yml)
|
[](https://github.com/CarmJos/EasyConfiguration/actions/workflows/maven.yml)
|
||||||
[](https://www.codefactor.io/repository/github/carmjos/easyconfiguration)
|
[](https://www.codefactor.io/repository/github/carmjos/easyconfiguration)
|
||||||

|

|
||||||
@@ -20,14 +20,17 @@
|
|||||||
## 优势
|
## 优势
|
||||||
|
|
||||||
- 基于类的配置文件初始化、加载、获取与更新机制,方便快捷。
|
- 基于类的配置文件初始化、加载、获取与更新机制,方便快捷。
|
||||||
|
- 支持复杂配置的手动序列化、反序列化。
|
||||||
|
- 提供多种builder形式,快速构建 `ConfigValue<?>` 对象。
|
||||||
|
- 支持通过注解规定配置对应的路径、注释等信息。
|
||||||
|
|
||||||
## 开发
|
## 开发
|
||||||
|
|
||||||
详细开发介绍请 [点击这里](.documentation/README.md) , JavaDoc(最新Release) 请 [点击这里](https://carmjos.github.io/EasyConfiguration) 。
|
详细开发介绍请 [点击这里](.documentation/README.md) , JavaDoc(最新Release) 请 [点击这里](https://CarmJos.github.io/EasyConfiguration) 。
|
||||||
|
|
||||||
### 示例代码
|
### 示例代码
|
||||||
|
|
||||||
您可以 [点击这里](impl/yaml/src/test/java/config/source/TestConfiguration.java) 查看部分代码演示,更多演示详见 [开发介绍](.documentation/README.md) 。
|
您可以 [点击这里](demo/src/main/java/cc/carm/lib/configuration/demo/DatabaseConfiguration.java) 查看部分代码演示,更多演示详见 [开发介绍](.documentation/README.md) 。
|
||||||
|
|
||||||
### 依赖方式
|
### 依赖方式
|
||||||
|
|
||||||
@@ -91,40 +94,15 @@
|
|||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
<!--基于JSON文件的实现版本,可用于全部Java环境。-->
|
||||||
</project>
|
<!--需要注意的是,JSON不支持文件注释。-->
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
**基于Spigot实现的版本**
|
|
||||||
|
|
||||||
```xml
|
|
||||||
|
|
||||||
<project>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<artifactId>easyconfiguration-spigot</artifactId>
|
<artifactId>easyconfiguration-json</artifactId>
|
||||||
<version>[LATEST RELEASE]</version>
|
<version>[LATEST RELEASE]</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</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>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
```
|
```
|
||||||
@@ -165,30 +143,24 @@ dependencies {
|
|||||||
//基于YAML文件的实现版本,可用于全部Java环境。
|
//基于YAML文件的实现版本,可用于全部Java环境。
|
||||||
api "cc.carm.lib:easyconfiguration-yaml:[LATEST RELEASE]"
|
api "cc.carm.lib:easyconfiguration-yaml:[LATEST RELEASE]"
|
||||||
|
|
||||||
}
|
//基于JSON文件的实现版本,可用于全部Java环境。
|
||||||
```
|
//需要注意的是,JSON不支持文件注释。
|
||||||
|
api "cc.carm.lib:easyconfiguration-json:[LATEST RELEASE]"
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>平台依赖版本</summary>
|
|
||||||
|
|
||||||
```groovy
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
|
|
||||||
// 用于Spigot服务端的版本
|
|
||||||
api "cc.carm.lib:easyconfiguration-spigot:[LATEST RELEASE]"
|
|
||||||
|
|
||||||
// 用于BungeeCord服务端的版本,不支持注解。
|
|
||||||
// 如需注解,可选择使用 `easyconfiguration-yaml` 并打包。
|
|
||||||
api "cc.carm.lib:easyconfiguration-bungee:[LATEST RELEASE]"
|
|
||||||
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
## 衍生项目
|
||||||
|
|
||||||
|
### [**MineConfiguration**](https://github.com/CarmJos/MineConfiguration) (by @CarmJos )
|
||||||
|
|
||||||
|
EasyConfiguration for MineCraft!
|
||||||
|
开始在 MineCraft 相关服务器平台上轻松(做)配置吧!
|
||||||
|
|
||||||
|
目前支持 BungeeCord, Bukkit(Spigot) 服务端,后续将支持更多平台。
|
||||||
|
|
||||||
## 支持与捐赠
|
## 支持与捐赠
|
||||||
|
|
||||||
若您觉得本插件做的不错,您可以通过捐赠支持我!
|
若您觉得本插件做的不错,您可以通过捐赠支持我!
|
||||||
@@ -199,23 +171,4 @@ dependencies {
|
|||||||
|
|
||||||
## 开源协议
|
## 开源协议
|
||||||
|
|
||||||
本项目源码采用 [The MIT License](https://opensource.org/licenses/MIT) 开源协议。
|
本项目源码采用 [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>
|
|
||||||
|
|||||||
+3
-1
@@ -5,12 +5,14 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>easyconfiguration-parent</artifactId>
|
<artifactId>easyconfiguration-parent</artifactId>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<version>1.0.3</version>
|
<version>3.3.1</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<properties>
|
<properties>
|
||||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<artifactId>easyconfiguration-core</artifactId>
|
<artifactId>easyconfiguration-core</artifactId>
|
||||||
|
|||||||
@@ -1,99 +1,274 @@
|
|||||||
package cc.carm.lib.configuration.core;
|
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.annotation.ConfigPath;
|
||||||
|
import cc.carm.lib.configuration.core.annotation.HeaderComment;
|
||||||
|
import cc.carm.lib.configuration.core.annotation.InlineComment;
|
||||||
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
||||||
import cc.carm.lib.configuration.core.value.ConfigValue;
|
import cc.carm.lib.configuration.core.value.ConfigValue;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Modifier;
|
import java.util.Arrays;
|
||||||
import java.util.Optional;
|
import java.util.List;
|
||||||
|
|
||||||
public class ConfigInitializer {
|
/**
|
||||||
|
* 配置文件类初始化方法
|
||||||
|
* 用于初始化 {@link ConfigurationRoot} 中的每个 {@link ConfigValue} 对象
|
||||||
|
*
|
||||||
|
* @param <T> {@link ConfigurationProvider} 配置文件的数据来源
|
||||||
|
* @author CarmJos
|
||||||
|
*/
|
||||||
|
public class ConfigInitializer<T extends ConfigurationProvider<?>> {
|
||||||
|
|
||||||
public static void initialize(ConfigurationProvider source, Class<? extends ConfigurationRoot> rootClazz) {
|
protected final @NotNull T provider;
|
||||||
initialize(source, rootClazz, true);
|
|
||||||
|
public ConfigInitializer(@NotNull T provider) {
|
||||||
|
this.provider = provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void initialize(ConfigurationProvider provider, Class<? extends ConfigurationRoot> rootClazz, boolean saveDefault) {
|
/**
|
||||||
ConfigPath sectionAnnotation = rootClazz.getAnnotation(ConfigPath.class);
|
* 初始化指定类以及其子类的所有 {@link ConfigValue} 对象。
|
||||||
|
*
|
||||||
|
* @param clazz 配置文件类,须继承于 {@link ConfigurationRoot} 。
|
||||||
|
* @param saveDefaults 是否写入默认值(默认为 true)。
|
||||||
|
*/
|
||||||
|
public void initialize(@NotNull Class<? extends ConfigurationRoot> clazz, boolean saveDefaults) {
|
||||||
|
initialize(clazz, saveDefaults, true);
|
||||||
|
}
|
||||||
|
|
||||||
String rootSection = null;
|
/**
|
||||||
if (sectionAnnotation != null && sectionAnnotation.value().length() > 1) {
|
* 初始化指定类的所有 {@link ConfigValue} 对象。
|
||||||
rootSection = sectionAnnotation.value();
|
*
|
||||||
}
|
* @param clazz 配置文件类,须继承于 {@link ConfigurationRoot} 。
|
||||||
|
* @param saveDefaults 是否写入默认值(默认为 true)。
|
||||||
for (Class<?> innerClass : rootClazz.getDeclaredClasses()) {
|
* @param loadSubClasses 是否加载内部子类(默认为 true)。
|
||||||
initSection(provider, rootSection, innerClass, saveDefault);
|
*/
|
||||||
}
|
public void initialize(@NotNull Class<? extends ConfigurationRoot> clazz,
|
||||||
|
boolean saveDefaults, boolean loadSubClasses) {
|
||||||
for (Field field : rootClazz.getFields()) {
|
initializeStaticClass(
|
||||||
initValue(provider, rootSection, rootClazz, field, saveDefault);
|
clazz, null, null,
|
||||||
}
|
null, null, null,
|
||||||
|
saveDefaults, loadSubClasses
|
||||||
if (saveDefault) {
|
);
|
||||||
|
if (saveDefaults) {
|
||||||
try {
|
try {
|
||||||
provider.save();
|
provider.save();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void initSection(ConfigurationProvider provider, String parentSection, Class<?> clazz, boolean saveDefault) {
|
/**
|
||||||
if (!Modifier.isStatic(clazz.getModifiers()) || !Modifier.isPublic(clazz.getModifiers())) return;
|
* 初始化指定实例的所有 {@link ConfigValue} 与内部 {@link ConfigurationRoot} 对象。
|
||||||
|
*
|
||||||
|
* @param config 配置文件实例类,须实现 {@link ConfigurationRoot} 。
|
||||||
|
*/
|
||||||
|
public void initialize(@NotNull ConfigurationRoot config) {
|
||||||
|
initialize(config, true);
|
||||||
|
}
|
||||||
|
|
||||||
String section = getSectionPath(clazz.getSimpleName(), parentSection, clazz.getAnnotation(ConfigPath.class));
|
/**
|
||||||
ConfigComment comments = clazz.getAnnotation(ConfigComment.class);
|
* 初始化指定实例的所有 {@link ConfigValue} 与内部 {@link ConfigurationRoot} 对象。
|
||||||
if (comments != null && comments.value().length > 0) {
|
*
|
||||||
provider.setComments(parentSection, comments.value());
|
* @param config 配置文件实例类,须实现 {@link ConfigurationRoot} 。
|
||||||
|
* @param saveDefaults 是否写入默认值(默认为 true)。
|
||||||
|
*/
|
||||||
|
public void initialize(@NotNull ConfigurationRoot config, boolean saveDefaults) {
|
||||||
|
initializeInstance(
|
||||||
|
config, null, null,
|
||||||
|
null, null, null,
|
||||||
|
saveDefaults
|
||||||
|
);
|
||||||
|
if (saveDefaults) {
|
||||||
|
try {
|
||||||
|
provider.save();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 针对实例类的初始化方法
|
||||||
|
private void initializeInstance(@NotNull ConfigurationRoot root,
|
||||||
|
@Nullable String parentPath, @Nullable String fieldName,
|
||||||
|
@Nullable ConfigPath fieldPath,
|
||||||
|
@Nullable HeaderComment fieldHeaderComments,
|
||||||
|
@Nullable InlineComment fieldInlineComments,
|
||||||
|
boolean saveDefaults) {
|
||||||
|
String path = getClassPath(root.getClass(), parentPath, fieldName, fieldPath);
|
||||||
|
this.provider.setHeaderComment(path, getClassHeaderComments(root.getClass(), fieldHeaderComments));
|
||||||
|
if (path != null) this.provider.setInlineComment(path, readInlineComments(fieldInlineComments));
|
||||||
|
|
||||||
|
for (Field field : root.getClass().getDeclaredFields()) {
|
||||||
|
initializeField(root, field, path, saveDefaults, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 针对静态类的初始化方法
|
||||||
|
private void initializeStaticClass(@NotNull Class<?> clazz,
|
||||||
|
@Nullable String parentPath, @Nullable String fieldName,
|
||||||
|
@Nullable ConfigPath fieldPath,
|
||||||
|
@Nullable HeaderComment fieldHeaderComments,
|
||||||
|
@Nullable InlineComment fieldInlineComments,
|
||||||
|
boolean saveDefaults, boolean loadSubClasses) {
|
||||||
|
if (!ConfigurationRoot.class.isAssignableFrom(clazz)) return; // 只解析继承了 ConfigurationRoot 的类
|
||||||
|
String path = getClassPath(clazz, parentPath, fieldName, fieldPath);
|
||||||
|
this.provider.setHeaderComment(path, getClassHeaderComments(clazz, fieldHeaderComments));
|
||||||
|
if (path != null) this.provider.setInlineComment(path, readInlineComments(fieldInlineComments));
|
||||||
|
|
||||||
|
for (Field field : clazz.getDeclaredFields()) {
|
||||||
|
initializeField(clazz, field, path, saveDefaults, loadSubClasses);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Field field : clazz.getFields()) initValue(provider, section, clazz, field, saveDefault);
|
if (!loadSubClasses) return;
|
||||||
for (Class<?> innerClass : clazz.getDeclaredClasses()) initSection(provider, section, innerClass, saveDefault);
|
Class<?>[] classes = clazz.getDeclaredClasses();
|
||||||
|
for (int i = classes.length - 1; i >= 0; i--) { // 逆向加载,保持顺序。
|
||||||
|
initializeStaticClass(
|
||||||
|
classes[i], path, classes[i].getSimpleName(),
|
||||||
|
null, null, null,
|
||||||
|
saveDefaults, true
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void initValue(ConfigurationProvider provider, String parentSection, Class<?> clazz, Field field, boolean saveDefault) {
|
private void initializeField(@NotNull Object source, @NotNull Field field,
|
||||||
|
@Nullable String parent, boolean saveDefaults, boolean loadSubClasses) {
|
||||||
try {
|
try {
|
||||||
Object object = field.get(clazz);
|
field.setAccessible(true);
|
||||||
|
Object object = field.get(source);
|
||||||
|
|
||||||
if (object instanceof ConfigValue<?>) {
|
if (object instanceof ConfigValue<?>) {
|
||||||
initializeValue(
|
initializeValue(
|
||||||
provider, (ConfigValue<?>) object,
|
(ConfigValue<?>) object, getFieldPath(field, parent),
|
||||||
getSectionPath(field.getName(), parentSection, field.getAnnotation(ConfigPath.class)),
|
field.getAnnotation(HeaderComment.class),
|
||||||
Optional.ofNullable(field.getAnnotation(ConfigComment.class))
|
field.getAnnotation(InlineComment.class),
|
||||||
.map(ConfigComment::value).orElse(new String[0]),
|
saveDefaults
|
||||||
saveDefault);
|
);
|
||||||
|
} else if (source instanceof ConfigurationRoot && object instanceof ConfigurationRoot) {
|
||||||
|
// 当且仅当 源字段与字段 均为ConfigurationRoot实例时,才对目标字段进行下一步初始化加载。
|
||||||
|
initializeInstance(
|
||||||
|
(ConfigurationRoot) object, parent, field.getName(),
|
||||||
|
field.getAnnotation(ConfigPath.class),
|
||||||
|
field.getAnnotation(HeaderComment.class),
|
||||||
|
field.getAnnotation(InlineComment.class),
|
||||||
|
saveDefaults
|
||||||
|
);
|
||||||
|
} else if (source instanceof Class<?> && object instanceof Class<?>) {
|
||||||
|
// 当且仅当 源字段与字段 均为静态类时,才对目标字段进行下一步初始化加载。
|
||||||
|
initializeStaticClass(
|
||||||
|
(Class<?>) object, parent, field.getName(),
|
||||||
|
field.getAnnotation(ConfigPath.class),
|
||||||
|
field.getAnnotation(HeaderComment.class),
|
||||||
|
field.getAnnotation(InlineComment.class),
|
||||||
|
saveDefaults, loadSubClasses
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 以上判断实现以下规范:
|
||||||
|
// - 实例类中仅加载 ConfigValue实例 与 ConfigurationRoot实例
|
||||||
|
// - 静态类中仅加载 静态ConfigValue实例 与 静态ConfigurationRoot类
|
||||||
|
|
||||||
} catch (IllegalAccessException ignored) {
|
} catch (IllegalAccessException ignored) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void initializeValue(@NotNull ConfigValue<?> value, @NotNull String path,
|
||||||
public static void initializeValue(@NotNull ConfigurationProvider provider, @NotNull ConfigValue<?> value,
|
@Nullable HeaderComment fieldHeaderComment,
|
||||||
@NotNull String path, @NotNull String[] comments, boolean saveDefault) {
|
@Nullable InlineComment fieldInlineComment,
|
||||||
value.initialize(provider, path, comments);
|
boolean saveDefaults) {
|
||||||
if (saveDefault && value.getDefaultValue() != null && !provider.getConfiguration().contains(path)) {
|
value.initialize(
|
||||||
value.setDefault();
|
provider, saveDefaults, path,
|
||||||
}
|
readHeaderComments(fieldHeaderComment),
|
||||||
|
readInlineComments(fieldInlineComment)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getSectionPath(@NotNull String name,
|
protected static @Nullable List<String> getClassHeaderComments(@NotNull Class<?> clazz,
|
||||||
@Nullable String parentSection,
|
@Nullable HeaderComment fieldAnnotation) {
|
||||||
@Nullable ConfigPath pathAnnotation) {
|
List<String> classComments = readHeaderComments(clazz.getAnnotation(HeaderComment.class));
|
||||||
String parent = parentSection != null ? parentSection + "." : "";
|
if (classComments != null) return classComments;
|
||||||
if (pathAnnotation != null && pathAnnotation.value().length() > 0) {
|
else return readHeaderComments(fieldAnnotation);
|
||||||
return parent + pathAnnotation.value();
|
|
||||||
} else {
|
|
||||||
return parent + getSectionName(name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getSectionName(String codeName) {
|
|
||||||
return codeName.toLowerCase().replace("_", "-");
|
protected static List<String> readHeaderComments(@Nullable HeaderComment annotation) {
|
||||||
|
if (annotation == null) return null;
|
||||||
|
String[] value = annotation.value();
|
||||||
|
return value.length > 0 ? Arrays.asList(value) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected static @Nullable String readInlineComments(@Nullable InlineComment annotation) {
|
||||||
|
if (annotation == null) return null;
|
||||||
|
String value = annotation.value();
|
||||||
|
return value.length() > 0 ? value : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static @Nullable String getClassPath(@Nullable Class<?> clazz,
|
||||||
|
@Nullable String parentPath,
|
||||||
|
@Nullable String filedName,
|
||||||
|
@Nullable ConfigPath fieldAnnotation) {
|
||||||
|
@NotNull String parent = parentPath != null ? parentPath + "." : "";
|
||||||
|
boolean fromRoot = false;
|
||||||
|
|
||||||
|
// 先获取 Class 对应的路径注解 其优先度最高。
|
||||||
|
if (clazz != null) {
|
||||||
|
ConfigPath clazzAnnotation = clazz.getAnnotation(ConfigPath.class);
|
||||||
|
if (clazzAnnotation != null) {
|
||||||
|
fromRoot = clazzAnnotation.root();
|
||||||
|
if (clazzAnnotation.value().length() > 0) {
|
||||||
|
return (fromRoot ? "" : parent) + clazzAnnotation.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fieldAnnotation != null) {
|
||||||
|
fromRoot = fromRoot || fieldAnnotation.root();
|
||||||
|
if (fieldAnnotation.value().length() > 0) {
|
||||||
|
return (fromRoot ? "" : parent) + fieldAnnotation.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 再由 fieldName 获取路径
|
||||||
|
if (filedName != null) return (fromRoot ? "" : parent) + getPathFromName(filedName);
|
||||||
|
else return null; // 不满足上述条件 且 无 fieldName,则说明是根路径。
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static @NotNull String getFieldPath(@NotNull Field field, @Nullable String parentPath) {
|
||||||
|
@NotNull String parent = parentPath != null ? parentPath + "." : "";
|
||||||
|
boolean fromRoot = false;
|
||||||
|
|
||||||
|
// 先获取 Field 对应的路径注解 其优先度最高。
|
||||||
|
ConfigPath pathAnnotation = field.getAnnotation(ConfigPath.class);
|
||||||
|
if (pathAnnotation != null) {
|
||||||
|
fromRoot = pathAnnotation.root();
|
||||||
|
if (pathAnnotation.value().length() > 0) {
|
||||||
|
return (fromRoot ? "" : parent) + pathAnnotation.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 最后再通过 fieldName 自动生成路径
|
||||||
|
return (fromRoot ? "" : parent) + getPathFromName(field.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 得到指定元素的配置名称。
|
||||||
|
* 采用 全小写,以“-”链接 的命名规则。
|
||||||
|
*
|
||||||
|
* @param name 源名称
|
||||||
|
* @return 全小写,以“-”链接 的 路径名称
|
||||||
|
*/
|
||||||
|
public static String getPathFromName(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 +1,7 @@
|
|||||||
package cc.carm.lib.configuration.core;
|
package cc.carm.lib.configuration.core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置文件类的根节点,用于标注该类用于记录配置文件中的配置信息。
|
||||||
|
*/
|
||||||
public abstract class ConfigurationRoot {
|
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,14 +1,34 @@
|
|||||||
package cc.carm.lib.configuration.core.annotation;
|
package cc.carm.lib.configuration.core.annotation;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.core.ConfigInitializer;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于标记对应类或参数的配置路径
|
||||||
|
*/
|
||||||
@Target({ElementType.TYPE, ElementType.FIELD})
|
@Target({ElementType.TYPE, ElementType.FIELD})
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface ConfigPath {
|
public @interface ConfigPath {
|
||||||
|
|
||||||
String value();
|
/**
|
||||||
|
* 指定路径的值。
|
||||||
|
* 若不指定,则会通过 {@link ConfigInitializer#getPathFromName(String)} 自动生成当前路径的值。
|
||||||
|
*
|
||||||
|
* @return 路径的值
|
||||||
|
*/
|
||||||
|
String value() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否从根节点开始。
|
||||||
|
* <br>若为 false,则会自动添加上一个路径(如果有)到本节点的路径。
|
||||||
|
* <br>若为 true,则会从根节点开始直接设置本路径。
|
||||||
|
*
|
||||||
|
* @return 是否不继承上一路径,直接从根路径为开始
|
||||||
|
*/
|
||||||
|
boolean root() default false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 顶部注释,用于给对应配置的顶部添加注释,便于使用者阅读查看。
|
||||||
|
* <p>如:
|
||||||
|
* <blockquote><pre>
|
||||||
|
* # 注释第一行
|
||||||
|
* # 注释第二行
|
||||||
|
* foo: "bar"
|
||||||
|
* </pre></blockquote>
|
||||||
|
*/
|
||||||
|
@Target({ElementType.TYPE, ElementType.FIELD})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface HeaderComment {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注释内容,若内容长度为0则会视为一个空行。
|
||||||
|
* <p> 如 <b>{"foo","","bar"}</b>
|
||||||
|
* 会被添加为
|
||||||
|
* <blockquote><pre>
|
||||||
|
* # foo
|
||||||
|
*
|
||||||
|
* # bar
|
||||||
|
* foo: "bar"
|
||||||
|
* </pre></blockquote>
|
||||||
|
*
|
||||||
|
* @return 注释内容
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
String[] value() default "";
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 行内注释,用于给对应配置的所在行添加注释,便于使用者阅读查看。
|
||||||
|
* 如:
|
||||||
|
* <blockquote><pre>
|
||||||
|
* foo: "bar" # 注释内容
|
||||||
|
* </pre></blockquote>
|
||||||
|
*/
|
||||||
|
@Target({ElementType.FIELD})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface InlineComment {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注释内容,若内容长度为0则不会添加注释
|
||||||
|
* <p> 如 <b>"foobar"</b> 将被设定为
|
||||||
|
* <blockquote><pre>
|
||||||
|
* foo: "bar" # foobar
|
||||||
|
* </pre></blockquote>
|
||||||
|
*
|
||||||
|
* @return 注释内容
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
String value() default "";
|
||||||
|
|
||||||
|
}
|
||||||
+28
-6
@@ -5,20 +5,30 @@ import cc.carm.lib.configuration.core.value.ConfigValue;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public abstract class AbstractConfigBuilder<B extends AbstractConfigBuilder<B, T>, T> {
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public abstract class AbstractConfigBuilder<T, B extends AbstractConfigBuilder<T, B, P>, P extends ConfigurationProvider<?>> {
|
||||||
|
|
||||||
protected @Nullable ConfigurationProvider provider;
|
protected final Class<? super P> providerClass;
|
||||||
|
|
||||||
|
protected @Nullable P provider;
|
||||||
protected @Nullable String path;
|
protected @Nullable String path;
|
||||||
|
|
||||||
protected @NotNull String[] comments = new String[0];
|
protected @Nullable List<String> headerComments;
|
||||||
|
protected @Nullable String inlineComment;
|
||||||
|
|
||||||
protected @Nullable T defaultValue;
|
protected @Nullable T defaultValue;
|
||||||
|
|
||||||
|
public AbstractConfigBuilder(Class<? super P> providerClass) {
|
||||||
|
this.providerClass = providerClass;
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract @NotNull B getThis();
|
protected abstract @NotNull B getThis();
|
||||||
|
|
||||||
public abstract @NotNull ConfigValue<?> build();
|
public abstract @NotNull ConfigValue<?> build();
|
||||||
|
|
||||||
public @NotNull B from(@Nullable ConfigurationProvider provider) {
|
public @NotNull B from(@Nullable P provider) {
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
return getThis();
|
return getThis();
|
||||||
}
|
}
|
||||||
@@ -29,7 +39,20 @@ public abstract class AbstractConfigBuilder<B extends AbstractConfigBuilder<B, T
|
|||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull B comments(@NotNull String... comments) {
|
public @NotNull B comments(@NotNull String... comments) {
|
||||||
this.comments = comments;
|
return headerComments(comments);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull B headerComments(@NotNull String... comments) {
|
||||||
|
return headerComments(Arrays.asList(comments));
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull B headerComments(@NotNull List<String> comments) {
|
||||||
|
this.headerComments = comments;
|
||||||
|
return getThis();
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull B inlineComment(@NotNull String comment) {
|
||||||
|
this.inlineComment = comment;
|
||||||
return getThis();
|
return getThis();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,5 +61,4 @@ public abstract class AbstractConfigBuilder<B extends AbstractConfigBuilder<B, T
|
|||||||
return getThis();
|
return getThis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package cc.carm.lib.configuration.core.builder;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
||||||
|
|
||||||
|
public abstract class CommonConfigBuilder<T, B extends CommonConfigBuilder<T, B>>
|
||||||
|
extends AbstractConfigBuilder<T, B, ConfigurationProvider<?>> {
|
||||||
|
|
||||||
|
public CommonConfigBuilder() {
|
||||||
|
super(ConfigurationProvider.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+3
-1
@@ -1,8 +1,10 @@
|
|||||||
package cc.carm.lib.configuration.core.builder.list;
|
package cc.carm.lib.configuration.core.builder.list;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.core.annotation.InlineComment;
|
||||||
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
|
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
|
||||||
public class ConfigListBuilder<V> {
|
public class ConfigListBuilder<V> {
|
||||||
|
|
||||||
protected final @NotNull Class<V> valueClass;
|
protected final @NotNull Class<V> valueClass;
|
||||||
@@ -31,7 +33,7 @@ public class ConfigListBuilder<V> {
|
|||||||
return from(
|
return from(
|
||||||
Object.class, ConfigDataFunction.identity(),
|
Object.class, ConfigDataFunction.identity(),
|
||||||
ConfigDataFunction.castObject(valueClass),
|
ConfigDataFunction.castObject(valueClass),
|
||||||
ConfigDataFunction.identity(), ConfigDataFunction.toObject()
|
ConfigDataFunction.toObject(), ConfigDataFunction.toObject()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-4
@@ -1,14 +1,15 @@
|
|||||||
package cc.carm.lib.configuration.core.builder.list;
|
package cc.carm.lib.configuration.core.builder.list;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.core.builder.AbstractConfigBuilder;
|
import cc.carm.lib.configuration.core.builder.CommonConfigBuilder;
|
||||||
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
|
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
|
||||||
import cc.carm.lib.configuration.core.value.type.ConfiguredList;
|
import cc.carm.lib.configuration.core.value.type.ConfiguredList;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class SourceListBuilder<S, V>
|
public class SourceListBuilder<S, V> extends CommonConfigBuilder<List<V>, SourceListBuilder<S, V>> {
|
||||||
extends AbstractConfigBuilder<SourceListBuilder<S, V>, List<V>> {
|
|
||||||
|
|
||||||
protected final @NotNull Class<S> sourceClass;
|
protected final @NotNull Class<S> sourceClass;
|
||||||
protected @NotNull ConfigDataFunction<Object, S> sourceParser;
|
protected @NotNull ConfigDataFunction<Object, S> sourceParser;
|
||||||
@@ -31,6 +32,11 @@ public class SourceListBuilder<S, V>
|
|||||||
this.valueSerializer = valueSerializer;
|
this.valueSerializer = valueSerializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SafeVarargs
|
||||||
|
public final @NotNull SourceListBuilder<S, V> defaults(@NotNull V... values) {
|
||||||
|
return defaults(new ArrayList<>(Arrays.asList(values)));
|
||||||
|
}
|
||||||
|
|
||||||
public @NotNull SourceListBuilder<S, V> parseSource(ConfigDataFunction<Object, S> sourceParser) {
|
public @NotNull SourceListBuilder<S, V> parseSource(ConfigDataFunction<Object, S> sourceParser) {
|
||||||
this.sourceParser = sourceParser;
|
this.sourceParser = sourceParser;
|
||||||
return this;
|
return this;
|
||||||
@@ -59,7 +65,8 @@ public class SourceListBuilder<S, V>
|
|||||||
@Override
|
@Override
|
||||||
public @NotNull ConfiguredList<V> build() {
|
public @NotNull ConfiguredList<V> build() {
|
||||||
return new ConfiguredList<>(
|
return new ConfiguredList<>(
|
||||||
this.provider, this.path, this.comments,
|
this.provider, this.path,
|
||||||
|
this.headerComments, this.inlineComment,
|
||||||
this.valueClass, this.defaultValue,
|
this.valueClass, this.defaultValue,
|
||||||
this.sourceParser.andThen(this.valueParser),
|
this.sourceParser.andThen(this.valueParser),
|
||||||
this.valueSerializer.andThen(sourceSerializer)
|
this.valueSerializer.andThen(sourceSerializer)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package cc.carm.lib.configuration.core.builder.map;
|
package cc.carm.lib.configuration.core.builder.map;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.core.builder.AbstractConfigBuilder;
|
import cc.carm.lib.configuration.core.builder.CommonConfigBuilder;
|
||||||
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
|
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
|
||||||
import cc.carm.lib.configuration.core.value.type.ConfiguredMap;
|
import cc.carm.lib.configuration.core.value.type.ConfiguredMap;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -8,8 +8,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class SourceMapBuilder<M extends Map<K, V>, S, K, V>
|
public class SourceMapBuilder<M extends Map<K, V>, S, K, V> extends CommonConfigBuilder<M, SourceMapBuilder<M, S, K, V>> {
|
||||||
extends AbstractConfigBuilder<SourceMapBuilder<M, S, K, V>, M> {
|
|
||||||
|
|
||||||
protected final @NotNull Supplier<@NotNull M> supplier;
|
protected final @NotNull Supplier<@NotNull M> supplier;
|
||||||
|
|
||||||
@@ -90,7 +89,8 @@ public class SourceMapBuilder<M extends Map<K, V>, S, K, V>
|
|||||||
@Override
|
@Override
|
||||||
public @NotNull ConfiguredMap<K, V> build() {
|
public @NotNull ConfiguredMap<K, V> build() {
|
||||||
return new ConfiguredMap<>(
|
return new ConfiguredMap<>(
|
||||||
this.provider, this.path, this.comments,
|
this.provider, this.path,
|
||||||
|
this.headerComments, this.inlineComment,
|
||||||
this.defaultValue, this.supplier,
|
this.defaultValue, this.supplier,
|
||||||
this.keyClass, this.keyParser,
|
this.keyClass, this.keyParser,
|
||||||
this.valueClass, this.sourceParser.andThen(this.valueParser),
|
this.valueClass, this.sourceParser.andThen(this.valueParser),
|
||||||
|
|||||||
+2
-2
@@ -19,7 +19,7 @@ public class ConfigValueBuilder<V> {
|
|||||||
return fromSection(ConfigValueParser.required(), ConfigDataFunction.required());
|
return fromSection(ConfigValueParser.required(), ConfigDataFunction.required());
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SectionValueBuilder<V> fromSection(@NotNull ConfigValueParser<ConfigurationWrapper, V> valueParser,
|
public @NotNull SectionValueBuilder<V> fromSection(@NotNull ConfigValueParser<ConfigurationWrapper<?>, V> valueParser,
|
||||||
@NotNull ConfigDataFunction<V, ? extends Map<String, Object>> valueSerializer) {
|
@NotNull ConfigDataFunction<V, ? extends Map<String, Object>> valueSerializer) {
|
||||||
return new SectionValueBuilder<>(this.valueClass, valueParser, valueSerializer);
|
return new SectionValueBuilder<>(this.valueClass, valueParser, valueSerializer);
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,7 @@ public class ConfigValueBuilder<V> {
|
|||||||
return from(
|
return from(
|
||||||
Object.class, ConfigDataFunction.identity(),
|
Object.class, ConfigDataFunction.identity(),
|
||||||
ConfigValueParser.castObject(valueClass),
|
ConfigValueParser.castObject(valueClass),
|
||||||
ConfigDataFunction.identity(), ConfigDataFunction.toObject()
|
ConfigDataFunction.toObject(), ConfigDataFunction.toObject()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-6
@@ -1,6 +1,6 @@
|
|||||||
package cc.carm.lib.configuration.core.builder.value;
|
package cc.carm.lib.configuration.core.builder.value;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.core.builder.AbstractConfigBuilder;
|
import cc.carm.lib.configuration.core.builder.CommonConfigBuilder;
|
||||||
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
|
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
|
||||||
import cc.carm.lib.configuration.core.function.ConfigValueParser;
|
import cc.carm.lib.configuration.core.function.ConfigValueParser;
|
||||||
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
||||||
@@ -10,16 +10,16 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class SectionValueBuilder<V>
|
public class SectionValueBuilder<V>
|
||||||
extends AbstractConfigBuilder<SectionValueBuilder<V>, V> {
|
extends CommonConfigBuilder<V, SectionValueBuilder<V>> {
|
||||||
|
|
||||||
|
|
||||||
protected final @NotNull Class<V> valueClass;
|
protected final @NotNull Class<V> valueClass;
|
||||||
|
|
||||||
protected @NotNull ConfigValueParser<ConfigurationWrapper, V> parser;
|
protected @NotNull ConfigValueParser<ConfigurationWrapper<?>, V> parser;
|
||||||
protected @NotNull ConfigDataFunction<V, ? extends Map<String, Object>> serializer;
|
protected @NotNull ConfigDataFunction<V, ? extends Map<String, Object>> serializer;
|
||||||
|
|
||||||
public SectionValueBuilder(@NotNull Class<V> valueClass,
|
public SectionValueBuilder(@NotNull Class<V> valueClass,
|
||||||
@NotNull ConfigValueParser<ConfigurationWrapper, V> parser,
|
@NotNull ConfigValueParser<ConfigurationWrapper<?>, V> parser,
|
||||||
@NotNull ConfigDataFunction<V, ? extends Map<String, Object>> serializer) {
|
@NotNull ConfigDataFunction<V, ? extends Map<String, Object>> serializer) {
|
||||||
this.valueClass = valueClass;
|
this.valueClass = valueClass;
|
||||||
this.parser = parser;
|
this.parser = parser;
|
||||||
@@ -32,7 +32,7 @@ public class SectionValueBuilder<V>
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SectionValueBuilder<V> parseValue(ConfigValueParser<ConfigurationWrapper, V> valueParser) {
|
public @NotNull SectionValueBuilder<V> parseValue(ConfigValueParser<ConfigurationWrapper<?>, V> valueParser) {
|
||||||
this.parser = valueParser;
|
this.parser = valueParser;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -45,7 +45,8 @@ public class SectionValueBuilder<V>
|
|||||||
@Override
|
@Override
|
||||||
public @NotNull ConfiguredSection<V> build() {
|
public @NotNull ConfiguredSection<V> build() {
|
||||||
return new ConfiguredSection<>(
|
return new ConfiguredSection<>(
|
||||||
this.provider, this.path, this.comments,
|
this.provider, this.path,
|
||||||
|
this.headerComments, this.inlineComment,
|
||||||
this.valueClass, this.defaultValue,
|
this.valueClass, this.defaultValue,
|
||||||
this.parser, this.serializer
|
this.parser, this.serializer
|
||||||
);
|
);
|
||||||
|
|||||||
+4
-3
@@ -1,12 +1,12 @@
|
|||||||
package cc.carm.lib.configuration.core.builder.value;
|
package cc.carm.lib.configuration.core.builder.value;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.core.builder.AbstractConfigBuilder;
|
import cc.carm.lib.configuration.core.builder.CommonConfigBuilder;
|
||||||
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
|
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
|
||||||
import cc.carm.lib.configuration.core.function.ConfigValueParser;
|
import cc.carm.lib.configuration.core.function.ConfigValueParser;
|
||||||
import cc.carm.lib.configuration.core.value.type.ConfiguredValue;
|
import cc.carm.lib.configuration.core.value.type.ConfiguredValue;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class SourceValueBuilder<S, V> extends AbstractConfigBuilder<SourceValueBuilder<S, V>, V> {
|
public class SourceValueBuilder<S, V> extends CommonConfigBuilder<V, SourceValueBuilder<S, V>> {
|
||||||
|
|
||||||
protected final @NotNull Class<S> sourceClass;
|
protected final @NotNull Class<S> sourceClass;
|
||||||
protected @NotNull ConfigDataFunction<Object, S> sourceParser;
|
protected @NotNull ConfigDataFunction<Object, S> sourceParser;
|
||||||
@@ -57,7 +57,8 @@ public class SourceValueBuilder<S, V> extends AbstractConfigBuilder<SourceValueB
|
|||||||
@Override
|
@Override
|
||||||
public @NotNull ConfiguredValue<V> build() {
|
public @NotNull ConfiguredValue<V> build() {
|
||||||
return new ConfiguredValue<>(
|
return new ConfiguredValue<>(
|
||||||
this.provider, this.path, this.comments,
|
this.provider, this.path,
|
||||||
|
this.headerComments, this.inlineComment,
|
||||||
this.valueClass, this.defaultValue,
|
this.valueClass, this.defaultValue,
|
||||||
this.valueParser.compose(this.sourceParser),
|
this.valueParser.compose(this.sourceParser),
|
||||||
this.valueSerializer.andThen(sourceSerializer)
|
this.valueSerializer.andThen(sourceSerializer)
|
||||||
|
|||||||
@@ -17,7 +17,12 @@ public interface ConfigDataFunction<T, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
static <T> @NotNull ConfigDataFunction<T, ? super T> identity() {
|
static <T> @NotNull ConfigDataFunction<T, T> identity() {
|
||||||
|
return (input) -> input;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Contract(pure = true)
|
||||||
|
static <T> @NotNull ConfigDataFunction<T, T> identity(Class<T> type) {
|
||||||
return (input) -> input;
|
return (input) -> input;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +38,6 @@ public interface ConfigDataFunction<T, R> {
|
|||||||
return (input) -> input;
|
return (input) -> input;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
static <V> @NotNull ConfigDataFunction<Object, V> castObject(Class<V> valueClass) {
|
static <V> @NotNull ConfigDataFunction<Object, V> castObject(Class<V> valueClass) {
|
||||||
return (input) -> {
|
return (input) -> {
|
||||||
|
|||||||
@@ -50,6 +50,25 @@ public interface ConfigValueParser<T, R> {
|
|||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
static <V> @NotNull ConfigValueParser<Object, V> castObject(Class<V> valueClass) {
|
static <V> @NotNull ConfigValueParser<Object, V> castObject(Class<V> valueClass) {
|
||||||
return (input, defaultValue) -> {
|
return (input, defaultValue) -> {
|
||||||
|
|
||||||
|
if (Number.class.isAssignableFrom(valueClass)) {
|
||||||
|
if (Long.class.isAssignableFrom(valueClass)) {
|
||||||
|
input = longValue().parse(input, (Long) defaultValue);
|
||||||
|
} else if (Integer.class.isAssignableFrom(valueClass)) {
|
||||||
|
input = intValue().parse(input, (Integer) defaultValue);
|
||||||
|
} else if (Float.class.isAssignableFrom(valueClass)) {
|
||||||
|
input = floatValue().parse(input, (Float) defaultValue);
|
||||||
|
} else if (Double.class.isAssignableFrom(valueClass)) {
|
||||||
|
input = doubleValue().parse(input, (Double) defaultValue);
|
||||||
|
} else if (Byte.class.isAssignableFrom(valueClass)) {
|
||||||
|
input = byteValue().parse(input, (Byte) defaultValue);
|
||||||
|
} else if (Short.class.isAssignableFrom(valueClass)) {
|
||||||
|
input = shortValue().parse(input, (Short) defaultValue);
|
||||||
|
}
|
||||||
|
} else if (Boolean.class.isAssignableFrom(valueClass)) {
|
||||||
|
input = booleanValue().parse(input, (Boolean) defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
if (valueClass.isInstance(input)) return valueClass.cast(input);
|
if (valueClass.isInstance(input)) return valueClass.cast(input);
|
||||||
else throw new IllegalArgumentException("Cannot cast value to " + valueClass.getName());
|
else throw new IllegalArgumentException("Cannot cast value to " + valueClass.getName());
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package cc.carm.lib.configuration.core.source;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.annotations.Unmodifiable;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public abstract class ConfigurationComments {
|
||||||
|
|
||||||
|
protected final @NotNull Map<String, List<String>> headerComments = new HashMap<>();
|
||||||
|
protected final @NotNull Map<String, String> inlineComments = new HashMap<>();
|
||||||
|
|
||||||
|
protected @NotNull Map<String, List<String>> getHeaderComments() {
|
||||||
|
return headerComments;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected @NotNull Map<String, String> getInlineComments() {
|
||||||
|
return inlineComments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeaderComments(@Nullable String path, @Nullable List<String> comments) {
|
||||||
|
|
||||||
|
if (comments == null) {
|
||||||
|
getHeaderComments().remove(path);
|
||||||
|
} else {
|
||||||
|
getHeaderComments().put(path, comments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setInlineComment(@NotNull String path, @Nullable String comment) {
|
||||||
|
if (comment == null) {
|
||||||
|
getInlineComments().remove(path);
|
||||||
|
} else {
|
||||||
|
getInlineComments().put(path, comment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Unmodifiable
|
||||||
|
public List<String> getHeaderComment(@Nullable String path) {
|
||||||
|
return Optional.ofNullable(getHeaderComments().get(path)).map(Collections::unmodifiableList).orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable String getInlineComment(@NotNull String path) {
|
||||||
|
return getInlineComments().get(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+114
-7
@@ -2,10 +2,16 @@ package cc.carm.lib.configuration.core.source;
|
|||||||
|
|
||||||
import cc.carm.lib.configuration.core.ConfigInitializer;
|
import cc.carm.lib.configuration.core.ConfigInitializer;
|
||||||
import cc.carm.lib.configuration.core.ConfigurationRoot;
|
import cc.carm.lib.configuration.core.ConfigurationRoot;
|
||||||
|
import cc.carm.lib.configuration.core.value.ConfigValue;
|
||||||
|
import cc.carm.lib.configuration.core.value.impl.CachedConfigValue;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.annotations.Unmodifiable;
|
||||||
|
|
||||||
public abstract class ConfigurationProvider {
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public abstract class ConfigurationProvider<W extends ConfigurationWrapper<?>> {
|
||||||
|
|
||||||
protected long updateTime;
|
protected long updateTime;
|
||||||
|
|
||||||
@@ -13,26 +19,127 @@ public abstract class ConfigurationProvider {
|
|||||||
this.updateTime = System.currentTimeMillis();
|
this.updateTime = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 得到配置文件的更新(最后加载)时间。
|
||||||
|
*
|
||||||
|
* @return 更新时间
|
||||||
|
*/
|
||||||
public long getUpdateTime() {
|
public long getUpdateTime() {
|
||||||
return updateTime;
|
return updateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于 {@link CachedConfigValue} 判断缓存值是否过期(即缓存的时间早于配置文件的最后加载时间)。
|
||||||
|
*
|
||||||
|
* @param time 缓存值时的时间戳
|
||||||
|
* @return 缓存值是否过期
|
||||||
|
*/
|
||||||
public boolean isExpired(long time) {
|
public boolean isExpired(long time) {
|
||||||
return this.updateTime > time;
|
return getUpdateTime() > time;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract @NotNull ConfigurationWrapper getConfiguration();
|
/**
|
||||||
|
* 得到配置文件的原生功能类。
|
||||||
|
*
|
||||||
|
* @return 原生类
|
||||||
|
*/
|
||||||
|
public abstract @NotNull W getConfiguration();
|
||||||
|
|
||||||
public abstract void reload() throws Exception;
|
/**
|
||||||
|
* 重载当前配置文件。(将不会保存已修改的内容)
|
||||||
|
*
|
||||||
|
* @throws Exception 当重载出现错误时抛出
|
||||||
|
*/
|
||||||
|
public void reload() throws Exception {
|
||||||
|
onReload(); // 调用重写的Reload方法
|
||||||
|
this.updateTime = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将当前对配置文件的更改进行保存。
|
||||||
|
*
|
||||||
|
* @throws Exception 当保存出现错误时抛出
|
||||||
|
*/
|
||||||
public abstract void save() throws Exception;
|
public abstract void save() throws Exception;
|
||||||
|
|
||||||
public abstract void setComments(@NotNull String path, @NotNull String... comments);
|
/**
|
||||||
|
* 针对于不同配置文件类型所执行的重载操作。
|
||||||
|
*
|
||||||
|
* @throws Exception 当操作出现错误时抛出。
|
||||||
|
*/
|
||||||
|
protected abstract void onReload() throws Exception;
|
||||||
|
|
||||||
public abstract @Nullable String[] getComments(@NotNull String path);
|
public abstract @Nullable ConfigurationComments getComments();
|
||||||
|
|
||||||
|
public void setHeaderComment(@Nullable String path, @Nullable List<String> comments) {
|
||||||
|
if (getComments() == null) return;
|
||||||
|
getComments().setHeaderComments(path, comments);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInlineComment(@NotNull String path, @Nullable String comment) {
|
||||||
|
if (getComments() == null) return;
|
||||||
|
getComments().setInlineComment(path, comment);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Unmodifiable
|
||||||
|
public List<String> getHeaderComment(@Nullable String path) {
|
||||||
|
return Optional.ofNullable(getComments()).map(c -> c.getHeaderComment(path)).orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable String getInlineComment(@NotNull String path) {
|
||||||
|
return Optional.ofNullable(getComments()).map(c -> c.getInlineComment(path)).orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract @NotNull ConfigInitializer<? extends ConfigurationProvider<W>> getInitializer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化指定类以及其子类的所有 {@link ConfigValue} 对象。
|
||||||
|
*
|
||||||
|
* @param configClazz 配置文件类,须继承于 {@link ConfigurationRoot} 。
|
||||||
|
*/
|
||||||
public void initialize(Class<? extends ConfigurationRoot> configClazz) {
|
public void initialize(Class<? extends ConfigurationRoot> configClazz) {
|
||||||
ConfigInitializer.initialize(this, configClazz, true);
|
initialize(configClazz, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化指定类以及其子类的所有 {@link ConfigValue} 对象。
|
||||||
|
*
|
||||||
|
* @param configClazz 配置文件类,须继承于 {@link ConfigurationRoot} 。
|
||||||
|
* @param saveDefaults 是否写入默认值(默认为 true)。
|
||||||
|
*/
|
||||||
|
public void initialize(Class<? extends ConfigurationRoot> configClazz, boolean saveDefaults) {
|
||||||
|
this.getInitializer().initialize(configClazz, saveDefaults);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化指定类的所有 {@link ConfigValue} 对象。
|
||||||
|
*
|
||||||
|
* @param configClazz 配置文件类,须继承于 {@link ConfigurationRoot} 。
|
||||||
|
* @param saveDefaults 是否写入默认值(默认为 true)。
|
||||||
|
* @param loadSubClasses 是否加载内部子类(默认为 true)。
|
||||||
|
*/
|
||||||
|
public void initialize(Class<? extends ConfigurationRoot> configClazz, boolean saveDefaults, boolean loadSubClasses) {
|
||||||
|
this.getInitializer().initialize(configClazz, saveDefaults, loadSubClasses);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化指定实例的所有 {@link ConfigValue} 与内部 {@link ConfigurationRoot} 对象。
|
||||||
|
*
|
||||||
|
* @param config 配置文件实例类,须实现 {@link ConfigurationRoot} 。
|
||||||
|
*/
|
||||||
|
public void initialize(@NotNull ConfigurationRoot config) {
|
||||||
|
this.getInitializer().initialize(config, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化指定实例的所有 {@link ConfigValue} 与内部 {@link ConfigurationRoot} 对象。
|
||||||
|
*
|
||||||
|
* @param config 配置文件实例类,须实现 {@link ConfigurationRoot} 。
|
||||||
|
* @param saveDefaults 是否写入默认值(默认为 true)。
|
||||||
|
*/
|
||||||
|
public void initialize(@NotNull ConfigurationRoot config, boolean saveDefaults) {
|
||||||
|
this.getInitializer().initialize(config, saveDefaults);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,15 @@ import cc.carm.lib.configuration.core.function.ConfigValueParser;
|
|||||||
import org.jetbrains.annotations.Contract;
|
import org.jetbrains.annotations.Contract;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.annotations.Unmodifiable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
interface ConfigurationReader {
|
interface ConfigurationReader {
|
||||||
|
|
||||||
ConfigurationWrapper getWrapper();
|
ConfigurationWrapper<?> getWrapper();
|
||||||
|
|
||||||
default boolean isBoolean(@NotNull String path) {
|
default boolean isBoolean(@NotNull String path) {
|
||||||
return getWrapper().isType(path, Boolean.class);
|
return getWrapper().isType(path, Boolean.class);
|
||||||
@@ -26,7 +31,6 @@ interface ConfigurationReader {
|
|||||||
return getWrapper().isType(path, Byte.class);
|
return getWrapper().isType(path, Byte.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
default @Nullable Byte getByte(@NotNull String path) {
|
default @Nullable Byte getByte(@NotNull String path) {
|
||||||
return getByte(path, (byte) 0);
|
return getByte(path, (byte) 0);
|
||||||
}
|
}
|
||||||
@@ -36,12 +40,10 @@ interface ConfigurationReader {
|
|||||||
return getWrapper().get(path, def, ConfigValueParser.byteValue());
|
return getWrapper().get(path, def, ConfigValueParser.byteValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
default boolean isShort(@NotNull String path) {
|
default boolean isShort(@NotNull String path) {
|
||||||
return getWrapper().isType(path, Short.class);
|
return getWrapper().isType(path, Short.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
default @Nullable Short getShort(@NotNull String path) {
|
default @Nullable Short getShort(@NotNull String path) {
|
||||||
return getShort(path, (short) 0);
|
return getShort(path, (short) 0);
|
||||||
}
|
}
|
||||||
@@ -56,7 +58,6 @@ interface ConfigurationReader {
|
|||||||
return getWrapper().isType(path, Integer.class);
|
return getWrapper().isType(path, Integer.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
default @Nullable Integer getInt(@NotNull String path) {
|
default @Nullable Integer getInt(@NotNull String path) {
|
||||||
return getInt(path, 0);
|
return getInt(path, 0);
|
||||||
}
|
}
|
||||||
@@ -71,7 +72,6 @@ interface ConfigurationReader {
|
|||||||
return getWrapper().isType(path, Long.class);
|
return getWrapper().isType(path, Long.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
default @Nullable Long getLong(@NotNull String path) {
|
default @Nullable Long getLong(@NotNull String path) {
|
||||||
return getLong(path, 0L);
|
return getLong(path, 0L);
|
||||||
}
|
}
|
||||||
@@ -86,7 +86,6 @@ interface ConfigurationReader {
|
|||||||
return getWrapper().isType(path, Float.class);
|
return getWrapper().isType(path, Float.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
default @Nullable Float getFloat(@NotNull String path) {
|
default @Nullable Float getFloat(@NotNull String path) {
|
||||||
return getFloat(path, 0.0F);
|
return getFloat(path, 0.0F);
|
||||||
}
|
}
|
||||||
@@ -101,7 +100,6 @@ interface ConfigurationReader {
|
|||||||
return getWrapper().isType(path, Double.class);
|
return getWrapper().isType(path, Double.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
default @Nullable Double getDouble(@NotNull String path) {
|
default @Nullable Double getDouble(@NotNull String path) {
|
||||||
return getDouble(path, 0.0D);
|
return getDouble(path, 0.0D);
|
||||||
}
|
}
|
||||||
@@ -116,7 +114,6 @@ interface ConfigurationReader {
|
|||||||
return getWrapper().isType(path, Boolean.class);
|
return getWrapper().isType(path, Boolean.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
default @Nullable Character getChar(@NotNull String path) {
|
default @Nullable Character getChar(@NotNull String path) {
|
||||||
return getChar(path, null);
|
return getChar(path, null);
|
||||||
}
|
}
|
||||||
@@ -140,5 +137,54 @@ interface ConfigurationReader {
|
|||||||
return getWrapper().get(path, def, String.class);
|
return getWrapper().get(path, def, String.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Unmodifiable
|
||||||
|
default @NotNull List<String> getStringList(@NotNull String path) {
|
||||||
|
return parseList(getWrapper().getList(path), ConfigValueParser.castToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unmodifiable
|
||||||
|
default @NotNull List<Integer> getIntegerList(@NotNull String path) {
|
||||||
|
return parseList(getWrapper().getList(path), ConfigValueParser.intValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unmodifiable
|
||||||
|
default @NotNull List<Long> getLongList(@NotNull String path) {
|
||||||
|
return parseList(getWrapper().getList(path), ConfigValueParser.longValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unmodifiable
|
||||||
|
default @NotNull List<Double> getDoubleList(@NotNull String path) {
|
||||||
|
return parseList(getWrapper().getList(path), ConfigValueParser.doubleValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unmodifiable
|
||||||
|
default @NotNull List<Float> getFloatList(@NotNull String path) {
|
||||||
|
return parseList(getWrapper().getList(path), ConfigValueParser.floatValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unmodifiable
|
||||||
|
default @NotNull List<Byte> getByteList(@NotNull String path) {
|
||||||
|
return parseList(getWrapper().getList(path), ConfigValueParser.byteValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unmodifiable
|
||||||
|
default @NotNull List<Character> getCharList(@NotNull String path) {
|
||||||
|
return parseList(getWrapper().getList(path), ConfigValueParser.castObject(Character.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unmodifiable
|
||||||
|
static <T> @NotNull List<T> parseList(@Nullable List<?> list, ConfigValueParser<Object, T> parser) {
|
||||||
|
if (list == null) return Collections.emptyList();
|
||||||
|
List<T> values = new ArrayList<>();
|
||||||
|
for (Object o : list) {
|
||||||
|
try {
|
||||||
|
T parsed = parser.parse(o, null);
|
||||||
|
if (parsed != null) values.add(parsed);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,13 +9,15 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public interface ConfigurationWrapper extends ConfigurationReader{
|
public interface ConfigurationWrapper<S> extends ConfigurationReader {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default ConfigurationWrapper getWrapper() {
|
default ConfigurationWrapper<S> getWrapper() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull S getSource();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
Set<String> getKeys(boolean deep);
|
Set<String> getKeys(boolean deep);
|
||||||
|
|
||||||
@@ -66,7 +68,6 @@ public interface ConfigurationWrapper extends ConfigurationReader{
|
|||||||
boolean isConfigurationSection(@NotNull String path);
|
boolean isConfigurationSection(@NotNull String path);
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
ConfigurationWrapper getConfigurationSection(@NotNull String path);
|
ConfigurationWrapper<S> getConfigurationSection(@NotNull String path);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-8
@@ -1,6 +1,7 @@
|
|||||||
package cc.carm.lib.configuration.core.source.impl;
|
package cc.carm.lib.configuration.core.source.impl;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
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.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@@ -9,7 +10,7 @@ import java.net.URL;
|
|||||||
import java.net.URLConnection;
|
import java.net.URLConnection;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public abstract class FileConfigProvider extends ConfigurationProvider {
|
public abstract class FileConfigProvider<W extends ConfigurationWrapper<?>> extends ConfigurationProvider<W> {
|
||||||
|
|
||||||
protected final @NotNull File file;
|
protected final @NotNull File file;
|
||||||
|
|
||||||
@@ -22,17 +23,22 @@ public abstract class FileConfigProvider extends ConfigurationProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void initializeFile(@Nullable String sourcePath) throws IOException {
|
public void initializeFile(@Nullable String sourcePath) throws IOException {
|
||||||
if (getFile().exists()) return;
|
if (this.file.exists()) return;
|
||||||
if (!getFile().getParentFile().exists() && !getFile().getParentFile().mkdirs()) {
|
|
||||||
|
File parent = this.file.getParentFile();
|
||||||
|
if (parent != null && !parent.exists() && !parent.mkdirs()) {
|
||||||
throw new IOException("Failed to create directory " + file.getParentFile().getAbsolutePath());
|
throw new IOException("Failed to create directory " + file.getParentFile().getAbsolutePath());
|
||||||
}
|
}
|
||||||
if (!getFile().createNewFile()) {
|
|
||||||
|
if (!this.file.createNewFile()) {
|
||||||
throw new IOException("Failed to create file " + file.getAbsolutePath());
|
throw new IOException("Failed to create file " + file.getAbsolutePath());
|
||||||
}
|
}
|
||||||
if (sourcePath == null) return;
|
|
||||||
try {
|
if (sourcePath != null) {
|
||||||
saveResource(sourcePath, true);
|
try {
|
||||||
} catch (Exception ignored) {
|
saveResource(sourcePath, true);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,39 +5,51 @@ import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
|||||||
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.annotations.Unmodifiable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public abstract class ConfigValue<T> {
|
public abstract class ConfigValue<T> {
|
||||||
|
|
||||||
public static @NotNull ConfigBuilder builder() {
|
public static @NotNull ConfigBuilder builder() {
|
||||||
return new ConfigBuilder();
|
return new ConfigBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected @Nullable ConfigurationProvider<?> provider;
|
||||||
|
protected @Nullable String configPath;
|
||||||
|
|
||||||
|
protected @Nullable List<String> headerComments;
|
||||||
|
protected @Nullable String inlineComments;
|
||||||
|
|
||||||
protected @Nullable T defaultValue;
|
protected @Nullable T defaultValue;
|
||||||
|
|
||||||
protected @Nullable ConfigurationProvider provider;
|
public ConfigValue(@Nullable ConfigurationProvider<?> provider, @Nullable String configPath,
|
||||||
protected @Nullable String configPath;
|
@Nullable List<String> headerComments, @Nullable String inlineComments,
|
||||||
protected @NotNull String[] comments;
|
@Nullable T defaultValue) {
|
||||||
|
|
||||||
public ConfigValue(@Nullable ConfigurationProvider provider, @Nullable String configPath,
|
|
||||||
@NotNull String[] comments, @Nullable T defaultValue) {
|
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
this.configPath = configPath;
|
this.configPath = configPath;
|
||||||
this.comments = comments;
|
this.headerComments = headerComments;
|
||||||
|
this.inlineComments = inlineComments;
|
||||||
this.defaultValue = defaultValue;
|
this.defaultValue = defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize(@NotNull ConfigurationProvider provider, @NotNull String configPath,
|
public void initialize(@NotNull ConfigurationProvider<?> provider, boolean saveDefault, @NotNull String configPath,
|
||||||
@NotNull String... comments) {
|
@Nullable List<String> headerComments, @Nullable String inlineComments) {
|
||||||
if (this.provider == null) this.provider = provider;
|
if (this.provider == null) this.provider = provider;
|
||||||
if (this.configPath == null) this.configPath = configPath;
|
if (this.configPath == null) this.configPath = configPath;
|
||||||
if (this.comments.length == 0) this.comments = comments;
|
if (this.headerComments == null) this.headerComments = headerComments;
|
||||||
|
if (this.inlineComments == null) this.inlineComments = inlineComments;
|
||||||
|
if (saveDefault) setDefault();
|
||||||
|
|
||||||
|
if (getHeaderComments() != null) {
|
||||||
|
this.provider.setHeaderComment(getConfigPath(), getHeaderComments());
|
||||||
|
}
|
||||||
|
if (getInlineComments() != null) {
|
||||||
|
this.provider.setInlineComment(getConfigPath(), getInlineComments());
|
||||||
|
}
|
||||||
|
|
||||||
this.provider.setComments(this.configPath, this.comments);
|
|
||||||
get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public @Nullable T getDefaultValue() {
|
public @Nullable T getDefaultValue() {
|
||||||
@@ -48,12 +60,29 @@ public abstract class ConfigValue<T> {
|
|||||||
this.defaultValue = defaultValue;
|
this.defaultValue = defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 得到该配置的设定值(即读取到的值)。
|
||||||
|
* <br> 若初始化时未写入默认值,则可以通过 {@link #getOrDefault()} 方法在该设定值为空时获取默认值。
|
||||||
|
*
|
||||||
|
* @return 设定值
|
||||||
|
*/
|
||||||
public abstract @Nullable T get();
|
public abstract @Nullable T get();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 得到该配置的设定值,若不存在,则返回默认值。
|
||||||
|
*
|
||||||
|
* @return 设定值或默认值
|
||||||
|
*/
|
||||||
public @Nullable T getOrDefault() {
|
public @Nullable T getOrDefault() {
|
||||||
return Optional.ofNullable(get()).orElse(getDefaultValue());
|
return getOptional().orElse(getDefaultValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 得到该配置的非空值。
|
||||||
|
*
|
||||||
|
* @return 非空值
|
||||||
|
* @throws NullPointerException 对应数据为空时抛出
|
||||||
|
*/
|
||||||
public @NotNull T getNotNull() {
|
public @NotNull T getNotNull() {
|
||||||
return Objects.requireNonNull(getOrDefault(), "Value(" + configPath + ") is null.");
|
return Objects.requireNonNull(getOrDefault(), "Value(" + configPath + ") is null.");
|
||||||
}
|
}
|
||||||
@@ -62,18 +91,52 @@ public abstract class ConfigValue<T> {
|
|||||||
return Optional.ofNullable(get());
|
return Optional.ofNullable(get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设定该配置的值。
|
||||||
|
* <br> 设定后,不会自动保存配置文件;若需要保存,请调用 {@link ConfigurationProvider#save()} 方法。
|
||||||
|
*
|
||||||
|
* @param value 配置的值
|
||||||
|
*/
|
||||||
public abstract void set(@Nullable T value);
|
public abstract void set(@Nullable T value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化该配置的默认值。
|
||||||
|
* <br> 设定后,不会自动保存配置文件;若需要保存,请调用 {@link ConfigurationProvider#save()} 方法。
|
||||||
|
*/
|
||||||
public void setDefault() {
|
public void setDefault() {
|
||||||
|
setDefault(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将该配置的值设置为默认值。
|
||||||
|
* <br> 设定后,不会自动保存配置文件;若需要保存,请调用 {@link ConfigurationProvider#save()} 方法。
|
||||||
|
*
|
||||||
|
* @param override 是否覆盖已设定的值
|
||||||
|
*/
|
||||||
|
public void setDefault(boolean override) {
|
||||||
|
if (!override && getConfiguration().contains(getConfigPath())) return;
|
||||||
Optional.ofNullable(getDefaultValue()).ifPresent(this::set);
|
Optional.ofNullable(getDefaultValue()).ifPresent(this::set);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull ConfigurationProvider getProvider() {
|
/**
|
||||||
|
* 判断加载的配置是否与默认值相同。
|
||||||
|
*
|
||||||
|
* @return 获取当前值是否为默认值。
|
||||||
|
*/
|
||||||
|
public boolean isDefault() {
|
||||||
|
T defaultValue = getDefaultValue();
|
||||||
|
T value = get();
|
||||||
|
if (defaultValue == null && value == null) return true;
|
||||||
|
else if (defaultValue != null && value != null) return defaultValue.equals(value);
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull ConfigurationProvider<?> getProvider() {
|
||||||
return Optional.ofNullable(this.provider)
|
return Optional.ofNullable(this.provider)
|
||||||
.orElseThrow(() -> new IllegalStateException("Value(" + configPath + ") does not have a provider."));
|
.orElseThrow(() -> new IllegalStateException("Value(" + configPath + ") does not have a provider."));
|
||||||
}
|
}
|
||||||
|
|
||||||
public final @NotNull ConfigurationWrapper getConfiguration() {
|
public final @NotNull ConfigurationWrapper<?> getConfiguration() {
|
||||||
try {
|
try {
|
||||||
return getProvider().getConfiguration();
|
return getProvider().getConfiguration();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
@@ -94,12 +157,13 @@ public abstract class ConfigValue<T> {
|
|||||||
getConfiguration().set(getConfigPath(), value);
|
getConfiguration().set(getConfigPath(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String[] getComments() {
|
public @Nullable String getInlineComments() {
|
||||||
return comments;
|
return inlineComments;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setComments(String[] comments) {
|
@Unmodifiable
|
||||||
this.comments = comments;
|
public @Nullable List<String> getHeaderComments() {
|
||||||
|
return headerComments;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-5
@@ -1,18 +1,21 @@
|
|||||||
package cc.carm.lib.configuration.core.value;
|
package cc.carm.lib.configuration.core.value.impl;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import cc.carm.lib.configuration.core.value.ConfigValue;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public abstract class CachedConfigValue<T> extends ConfigValue<T> {
|
public abstract class CachedConfigValue<T> extends ConfigValue<T> {
|
||||||
|
|
||||||
|
|
||||||
protected @Nullable T cachedValue;
|
protected @Nullable T cachedValue;
|
||||||
protected long parsedTime = -1;
|
protected long parsedTime = -1;
|
||||||
|
|
||||||
public CachedConfigValue(@Nullable ConfigurationProvider provider, @Nullable String sectionPath,
|
public CachedConfigValue(@Nullable ConfigurationProvider<?> provider, @Nullable String sectionPath,
|
||||||
@NotNull String[] comments, @Nullable T defaultValue) {
|
@Nullable List<String> headerComments, @Nullable String inlineComments,
|
||||||
super(provider, sectionPath, comments, defaultValue);
|
@Nullable T defaultValue) {
|
||||||
|
super(provider, sectionPath, headerComments, inlineComments, defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected T updateCache(T value) {
|
protected T updateCache(T value) {
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
package cc.carm.lib.configuration.core.value.type;
|
package cc.carm.lib.configuration.core.value.type;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.core.builder.ConfigBuilder;
|
import cc.carm.lib.configuration.core.annotation.HeaderComment;
|
||||||
import cc.carm.lib.configuration.core.builder.list.ConfigListBuilder;
|
import cc.carm.lib.configuration.core.builder.list.ConfigListBuilder;
|
||||||
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
|
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
|
||||||
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
||||||
import cc.carm.lib.configuration.core.value.CachedConfigValue;
|
import cc.carm.lib.configuration.core.value.impl.CachedConfigValue;
|
||||||
import cc.carm.lib.configuration.core.value.ConfigValue;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@@ -18,17 +17,18 @@ public class ConfiguredList<V> extends CachedConfigValue<List<V>> {
|
|||||||
return builder().asList(valueClass);
|
return builder().asList(valueClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@HeaderComment
|
||||||
protected final @NotNull Class<V> valueClass;
|
protected final @NotNull Class<V> valueClass;
|
||||||
|
|
||||||
protected final @NotNull ConfigDataFunction<Object, V> parser;
|
protected final @NotNull ConfigDataFunction<Object, V> parser;
|
||||||
protected final @NotNull ConfigDataFunction<V, Object> serializer;
|
protected final @NotNull ConfigDataFunction<V, Object> serializer;
|
||||||
|
|
||||||
public ConfiguredList(@Nullable ConfigurationProvider provider,
|
public ConfiguredList(@Nullable ConfigurationProvider<?> provider, @Nullable String sectionPath,
|
||||||
@Nullable String sectionPath, @NotNull String[] comments,
|
@Nullable List<String> headerComments, @Nullable String inlineComments,
|
||||||
@NotNull Class<V> valueClass, @Nullable List<V> defaultValue,
|
@NotNull Class<V> valueClass, @Nullable List<V> defaultValue,
|
||||||
@NotNull ConfigDataFunction<Object, V> parser,
|
@NotNull ConfigDataFunction<Object, V> parser,
|
||||||
@NotNull ConfigDataFunction<V, Object> serializer) {
|
@NotNull ConfigDataFunction<V, Object> serializer) {
|
||||||
super(provider, sectionPath, comments, defaultValue);
|
super(provider, sectionPath, headerComments, inlineComments, defaultValue);
|
||||||
this.valueClass = valueClass;
|
this.valueClass = valueClass;
|
||||||
this.parser = parser;
|
this.parser = parser;
|
||||||
this.serializer = serializer;
|
this.serializer = serializer;
|
||||||
@@ -38,10 +38,8 @@ public class ConfiguredList<V> extends CachedConfigValue<List<V>> {
|
|||||||
public @NotNull List<V> get() {
|
public @NotNull List<V> get() {
|
||||||
if (isExpired()) { // 已过时的数据,需要重新解析一次。
|
if (isExpired()) { // 已过时的数据,需要重新解析一次。
|
||||||
List<V> list = new ArrayList<>();
|
List<V> list = new ArrayList<>();
|
||||||
|
|
||||||
List<?> data = getConfiguration().getList(getConfigPath());
|
List<?> data = getConfiguration().getList(getConfigPath());
|
||||||
if (data == null || data.isEmpty()) return useOrDefault(list);
|
if (data == null || data.isEmpty()) return useOrDefault(list);
|
||||||
|
|
||||||
for (Object dataVal : data) {
|
for (Object dataVal : data) {
|
||||||
if (dataVal == null) continue;
|
if (dataVal == null) continue;
|
||||||
try {
|
try {
|
||||||
@@ -50,7 +48,6 @@ public class ConfiguredList<V> extends CachedConfigValue<List<V>> {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return updateCache(list);
|
return updateCache(list);
|
||||||
} else if (getCachedValue() != null) return getCachedValue();
|
} else if (getCachedValue() != null) return getCachedValue();
|
||||||
else if (getDefaultValue() != null) return getDefaultValue();
|
else if (getDefaultValue() != null) return getDefaultValue();
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
package cc.carm.lib.configuration.core.value.type;
|
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.builder.map.ConfigMapBuilder;
|
||||||
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
|
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
|
||||||
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
||||||
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
||||||
import cc.carm.lib.configuration.core.value.CachedConfigValue;
|
import cc.carm.lib.configuration.core.value.impl.CachedConfigValue;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
@@ -32,14 +32,14 @@ public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> {
|
|||||||
protected final @NotNull ConfigDataFunction<K, String> keySerializer;
|
protected final @NotNull ConfigDataFunction<K, String> keySerializer;
|
||||||
protected final @NotNull ConfigDataFunction<V, Object> valueSerializer;
|
protected final @NotNull ConfigDataFunction<V, Object> valueSerializer;
|
||||||
|
|
||||||
public ConfiguredMap(@Nullable ConfigurationProvider provider,
|
public ConfiguredMap(@Nullable ConfigurationProvider<?> provider, @Nullable String sectionPath,
|
||||||
@Nullable String sectionPath, @NotNull String[] comments,
|
@Nullable List<String> headerComments, @Nullable String inlineComments,
|
||||||
@Nullable Map<K, V> defaultValue, @NotNull Supplier<? extends Map<K, V>> supplier,
|
@Nullable Map<K, V> defaultValue, @NotNull Supplier<? extends Map<K, V>> supplier,
|
||||||
@NotNull Class<K> keyClass, @NotNull ConfigDataFunction<String, K> keyParser,
|
@NotNull Class<K> keyClass, @NotNull ConfigDataFunction<String, K> keyParser,
|
||||||
@NotNull Class<V> valueClass, @NotNull ConfigDataFunction<Object, V> valueParser,
|
@NotNull Class<V> valueClass, @NotNull ConfigDataFunction<Object, V> valueParser,
|
||||||
@NotNull ConfigDataFunction<K, String> keySerializer,
|
@NotNull ConfigDataFunction<K, String> keySerializer,
|
||||||
@NotNull ConfigDataFunction<V, Object> valueSerializer) {
|
@NotNull ConfigDataFunction<V, Object> valueSerializer) {
|
||||||
super(provider, sectionPath, comments, defaultValue);
|
super(provider, sectionPath, headerComments, inlineComments, defaultValue);
|
||||||
this.supplier = supplier;
|
this.supplier = supplier;
|
||||||
this.keyClass = keyClass;
|
this.keyClass = keyClass;
|
||||||
this.valueClass = valueClass;
|
this.valueClass = valueClass;
|
||||||
@@ -78,7 +78,7 @@ public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> {
|
|||||||
if (isExpired()) { // 已过时的数据,需要重新解析一次。
|
if (isExpired()) { // 已过时的数据,需要重新解析一次。
|
||||||
Map<K, V> map = supplier.get();
|
Map<K, V> map = supplier.get();
|
||||||
|
|
||||||
ConfigurationWrapper section = getConfiguration().getConfigurationSection(getConfigPath());
|
ConfigurationWrapper<?> section = getConfiguration().getConfigurationSection(getConfigPath());
|
||||||
if (section == null) return useOrDefault(map);
|
if (section == null) return useOrDefault(map);
|
||||||
|
|
||||||
Set<String> keys = section.getKeys(false);
|
Set<String> keys = section.getKeys(false);
|
||||||
@@ -110,9 +110,10 @@ public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> {
|
|||||||
Map<String, Object> data = new LinkedHashMap<>();
|
Map<String, Object> data = new LinkedHashMap<>();
|
||||||
for (Map.Entry<K, V> entry : value.entrySet()) {
|
for (Map.Entry<K, V> entry : value.entrySet()) {
|
||||||
try {
|
try {
|
||||||
String key = keySerializer.parse(entry.getKey());
|
data.put(
|
||||||
Object val = valueSerializer.parse(entry.getValue());
|
keySerializer.parse(entry.getKey()),
|
||||||
data.put(key, val);
|
valueSerializer.parse(entry.getValue())
|
||||||
|
);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-10
@@ -1,15 +1,15 @@
|
|||||||
package cc.carm.lib.configuration.core.value.type;
|
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.builder.value.SectionValueBuilder;
|
||||||
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
|
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
|
||||||
import cc.carm.lib.configuration.core.function.ConfigValueParser;
|
import cc.carm.lib.configuration.core.function.ConfigValueParser;
|
||||||
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
||||||
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
||||||
import cc.carm.lib.configuration.core.value.CachedConfigValue;
|
import cc.carm.lib.configuration.core.value.impl.CachedConfigValue;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@@ -21,15 +21,15 @@ public class ConfiguredSection<V> extends CachedConfigValue<V> {
|
|||||||
|
|
||||||
protected final @NotNull Class<V> valueClass;
|
protected final @NotNull Class<V> valueClass;
|
||||||
|
|
||||||
protected final @NotNull ConfigValueParser<ConfigurationWrapper, V> parser;
|
protected final @NotNull ConfigValueParser<ConfigurationWrapper<?>, V> parser;
|
||||||
protected final @NotNull ConfigDataFunction<V, ? extends Map<String, Object>> serializer;
|
protected final @NotNull ConfigDataFunction<V, ? extends Map<String, Object>> serializer;
|
||||||
|
|
||||||
public ConfiguredSection(@Nullable ConfigurationProvider provider,
|
public ConfiguredSection(@Nullable ConfigurationProvider<?> provider, @Nullable String sectionPath,
|
||||||
@Nullable String sectionPath, @NotNull String[] comments,
|
@Nullable List<String> headerComments, @Nullable String inlineComments,
|
||||||
@NotNull Class<V> valueClass, @Nullable V defaultValue,
|
@NotNull Class<V> valueClass, @Nullable V defaultValue,
|
||||||
@NotNull ConfigValueParser<ConfigurationWrapper, V> parser,
|
@NotNull ConfigValueParser<ConfigurationWrapper<?>, V> parser,
|
||||||
@NotNull ConfigDataFunction<V, ? extends Map<String, Object>> serializer) {
|
@NotNull ConfigDataFunction<V, ? extends Map<String, Object>> serializer) {
|
||||||
super(provider, sectionPath, comments, defaultValue);
|
super(provider, sectionPath, headerComments, inlineComments, defaultValue);
|
||||||
this.valueClass = valueClass;
|
this.valueClass = valueClass;
|
||||||
this.parser = parser;
|
this.parser = parser;
|
||||||
this.serializer = serializer;
|
this.serializer = serializer;
|
||||||
@@ -39,7 +39,7 @@ public class ConfiguredSection<V> extends CachedConfigValue<V> {
|
|||||||
return valueClass;
|
return valueClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull ConfigValueParser<ConfigurationWrapper, V> getParser() {
|
public @NotNull ConfigValueParser<ConfigurationWrapper<?>, V> getParser() {
|
||||||
return parser;
|
return parser;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ public class ConfiguredSection<V> extends CachedConfigValue<V> {
|
|||||||
@Override
|
@Override
|
||||||
public @Nullable V get() {
|
public @Nullable V get() {
|
||||||
if (isExpired()) { // 已过时的数据,需要重新解析一次。
|
if (isExpired()) { // 已过时的数据,需要重新解析一次。
|
||||||
ConfigurationWrapper section = getConfiguration().getConfigurationSection(getConfigPath());
|
ConfigurationWrapper<?> section = getConfiguration().getConfigurationSection(getConfigPath());
|
||||||
if (section == null) return useDefault();
|
if (section == null) return useDefault();
|
||||||
try {
|
try {
|
||||||
// 若未出现错误,则直接更新缓存并返回。
|
// 若未出现错误,则直接更新缓存并返回。
|
||||||
@@ -70,7 +70,6 @@ public class ConfiguredSection<V> extends CachedConfigValue<V> {
|
|||||||
else {
|
else {
|
||||||
try {
|
try {
|
||||||
setValue(serializer.parse(value));
|
setValue(serializer.parse(value));
|
||||||
// getConfiguration().createSection(getSectionPath(), serializer.parse(value));
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
package cc.carm.lib.configuration.core.value.type;
|
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.builder.value.ConfigValueBuilder;
|
||||||
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
|
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
|
||||||
import cc.carm.lib.configuration.core.function.ConfigValueParser;
|
import cc.carm.lib.configuration.core.function.ConfigValueParser;
|
||||||
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
||||||
import cc.carm.lib.configuration.core.value.CachedConfigValue;
|
import cc.carm.lib.configuration.core.value.impl.CachedConfigValue;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public class ConfiguredValue<V> extends CachedConfigValue<V> {
|
public class ConfiguredValue<V> extends CachedConfigValue<V> {
|
||||||
@@ -30,13 +30,13 @@ public class ConfiguredValue<V> extends CachedConfigValue<V> {
|
|||||||
protected final @NotNull ConfigValueParser<Object, V> parser;
|
protected final @NotNull ConfigValueParser<Object, V> parser;
|
||||||
protected final @NotNull ConfigDataFunction<V, Object> serializer;
|
protected final @NotNull ConfigDataFunction<V, Object> serializer;
|
||||||
|
|
||||||
public ConfiguredValue(@Nullable ConfigurationProvider provider,
|
public ConfiguredValue(@Nullable ConfigurationProvider<?> provider, @Nullable String sectionPath,
|
||||||
@Nullable String sectionPath, @NotNull String[] comments,
|
@Nullable List<String> headerComments, @Nullable String inlineComments,
|
||||||
@NotNull Class<V> valueClass, @Nullable V defaultValue,
|
@NotNull Class<V> valueClass, @Nullable V defaultValue,
|
||||||
@NotNull ConfigValueParser<Object, V> parser,
|
@NotNull ConfigValueParser<Object, V> parser,
|
||||||
@NotNull ConfigDataFunction<V, Object> serializer) {
|
@NotNull ConfigDataFunction<V, Object> serializer) {
|
||||||
|
|
||||||
super(provider, sectionPath, comments, defaultValue);
|
super(provider, sectionPath, headerComments, inlineComments, defaultValue);
|
||||||
this.valueClass = valueClass;
|
this.valueClass = valueClass;
|
||||||
this.parser = parser;
|
this.parser = parser;
|
||||||
this.serializer = serializer;
|
this.serializer = serializer;
|
||||||
@@ -53,7 +53,7 @@ public class ConfiguredValue<V> extends CachedConfigValue<V> {
|
|||||||
@Override
|
@Override
|
||||||
public V get() {
|
public V get() {
|
||||||
if (isExpired()) { // 已过时的数据,需要重新解析一次。
|
if (isExpired()) { // 已过时的数据,需要重新解析一次。
|
||||||
Object value = getConfiguration().get(getConfigPath());
|
Object value = getValue();
|
||||||
if (value == null) return useDefault(); // 获取的值不存在,直接使用默认值。
|
if (value == null) return useDefault(); // 获取的值不存在,直接使用默认值。
|
||||||
try {
|
try {
|
||||||
// 若未出现错误,则直接更新缓存并返回。
|
// 若未出现错误,则直接更新缓存并返回。
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import cc.carm.lib.configuration.core.ConfigInitializer;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class NameTest {
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onTest() {
|
||||||
|
|
||||||
|
System.out.println(ConfigInitializer.getPathFromName("LoveGames")); // -> love-games
|
||||||
|
System.out.println(ConfigInitializer.getPathFromName("EASY_GAME")); // -> easy-game
|
||||||
|
System.out.println(ConfigInitializer.getPathFromName("F")); //-? f
|
||||||
|
System.out.println(ConfigInitializer.getPathFromName("Test123123")); // -? test123123123
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package cc.carm.test.config.offset;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Chris2018998
|
||||||
|
*/
|
||||||
|
public class FieldOffset implements Comparable<FieldOffset> {
|
||||||
|
private final Field field;
|
||||||
|
private Long offsetValue;
|
||||||
|
private List<FieldOffset> subFieldOffsetList;
|
||||||
|
|
||||||
|
public FieldOffset(Field field) {
|
||||||
|
this.field = field;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getOffsetValue() {
|
||||||
|
return offsetValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOffsetValue(Long offsetValue) {
|
||||||
|
this.offsetValue = offsetValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
if (subFieldOffsetList == null)
|
||||||
|
return field.getName();
|
||||||
|
else {
|
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
builder.append("[");
|
||||||
|
|
||||||
|
for (int i = 0; i < subFieldOffsetList.size(); i++) {
|
||||||
|
FieldOffset offset = subFieldOffsetList.get(i);
|
||||||
|
if (i > 0) builder.append(",");
|
||||||
|
builder.append(field.getName()).append(".").append(offset.toString());
|
||||||
|
}
|
||||||
|
builder.append("]");
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<FieldOffset> getSubFieldOffsetList() {
|
||||||
|
return subFieldOffsetList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubFieldOffsetList(List<FieldOffset> subFieldOffsetList) {
|
||||||
|
this.subFieldOffsetList = subFieldOffsetList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Field getField() {
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(@NotNull FieldOffset that) {
|
||||||
|
return this.offsetValue.compareTo(that.offsetValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
//package config.offset;
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//import sun.misc.Unsafe;
|
||||||
|
//
|
||||||
|
//import java.lang.reflect.Field;
|
||||||
|
//import java.lang.reflect.Modifier;
|
||||||
|
//import java.util.Collections;
|
||||||
|
//import java.util.LinkedList;
|
||||||
|
//import java.util.List;
|
||||||
|
//
|
||||||
|
///**
|
||||||
|
// * @author Chris2018998
|
||||||
|
// */
|
||||||
|
//public class OffsetUtil {
|
||||||
|
// private static Unsafe unsafe;
|
||||||
|
//
|
||||||
|
// static {
|
||||||
|
// try {
|
||||||
|
// // 获取 Unsafe 内部的私有的实例化单例对象
|
||||||
|
// Field field = Unsafe.class.getDeclaredField("theUnsafe");
|
||||||
|
// // 无视权限
|
||||||
|
// field.setAccessible(true);
|
||||||
|
// unsafe = (Unsafe) field.get(null);
|
||||||
|
// } catch (NoSuchFieldException | IllegalAccessException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
//// try {
|
||||||
|
//// unsafe = AccessController.doPrivileged((PrivilegedExceptionAction<Unsafe>) () -> {
|
||||||
|
//// Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
|
||||||
|
//// theUnsafe.setAccessible(true);
|
||||||
|
//// return (Unsafe) theUnsafe.get(null);
|
||||||
|
//// });
|
||||||
|
//// } catch (Throwable e) {
|
||||||
|
//// System.err.println("Unable to load unsafe");
|
||||||
|
//// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public static List<FieldOffset> getClassMemberOffset(Class<?> beanClass) {
|
||||||
|
// List<FieldOffset> offsetsList = new LinkedList<>();
|
||||||
|
// for (Field field : beanClass.getDeclaredFields()) {
|
||||||
|
// FieldOffset fieldOffset = new FieldOffset(field);
|
||||||
|
// offsetsList.add(fieldOffset);
|
||||||
|
// if (Modifier.isStatic(field.getModifiers()))
|
||||||
|
// fieldOffset.setOffsetValue(unsafe.staticFieldOffset(field));
|
||||||
|
// else
|
||||||
|
// fieldOffset.setOffsetValue(unsafe.objectFieldOffset(field));
|
||||||
|
// Class<?> fieldType = field.getType();
|
||||||
|
// if (!fieldType.getName().startsWith("java")) {
|
||||||
|
// Field[] subfields = fieldType.getDeclaredFields();
|
||||||
|
// if (subfields.length > 0) {
|
||||||
|
// fieldOffset.setSubFieldOffsetList(getClassMemberOffset(fieldType));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Collections.sort(offsetsList);
|
||||||
|
// return offsetsList;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
//
|
||||||
@@ -5,16 +5,16 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>easyconfiguration-parent</artifactId>
|
<artifactId>easyconfiguration-parent</artifactId>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<version>1.0.3</version>
|
<version>3.3.1</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<properties>
|
<properties>
|
||||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
<artifactId>easyconfiguration-demo</artifactId>
|
||||||
<artifactId>easyconfiguration-spigot</artifactId>
|
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -26,13 +26,6 @@
|
|||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.spigotmc</groupId>
|
|
||||||
<artifactId>spigot-api</artifactId>
|
|
||||||
<version>1.18.2-R0.1-SNAPSHOT</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
@@ -56,5 +49,4 @@
|
|||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package cc.carm.lib.configuration.demo;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.core.ConfigurationRoot;
|
||||||
|
import cc.carm.lib.configuration.core.annotation.ConfigPath;
|
||||||
|
import cc.carm.lib.configuration.core.annotation.HeaderComment;
|
||||||
|
import cc.carm.lib.configuration.core.value.ConfigValue;
|
||||||
|
import cc.carm.lib.configuration.core.value.type.ConfiguredValue;
|
||||||
|
|
||||||
|
@HeaderComment({"", "数据库配置", " 用于提供数据库连接,进行数据库操作。"})
|
||||||
|
public class DatabaseConfiguration extends ConfigurationRoot {
|
||||||
|
|
||||||
|
@ConfigPath("driver")
|
||||||
|
@HeaderComment({
|
||||||
|
"数据库驱动配置,请根据数据库类型设置。",
|
||||||
|
"- MySQL(旧): com.mysql.jdbc.Driver",
|
||||||
|
"- MySQL(新): com.mysql.cj.jdbc.Driver",
|
||||||
|
"- MariaDB(推荐): org.mariadb.jdbc.Driver",
|
||||||
|
})
|
||||||
|
protected static final ConfigValue<String> DRIVER_NAME = ConfiguredValue.of(
|
||||||
|
String.class, "com.mysql.cj.jdbc.Driver"
|
||||||
|
);
|
||||||
|
|
||||||
|
protected static final ConfigValue<String> HOST = ConfiguredValue.of(String.class, "127.0.0.1");
|
||||||
|
protected static final ConfigValue<Integer> PORT = ConfiguredValue.of(Integer.class, 3306);
|
||||||
|
protected static final ConfigValue<String> DATABASE = ConfiguredValue.of(String.class, "minecraft");
|
||||||
|
protected static final ConfigValue<String> USERNAME = ConfiguredValue.of(String.class, "root");
|
||||||
|
protected static final ConfigValue<String> PASSWORD = ConfiguredValue.of(String.class, "password");
|
||||||
|
protected static final ConfigValue<String> EXTRA = ConfiguredValue.of(String.class, "?useSSL=false");
|
||||||
|
|
||||||
|
protected static String buildJDBC() {
|
||||||
|
return String.format("jdbc:mysql://%s:%s/%s%s", HOST.get(), PORT.get(), DATABASE.get(), EXTRA.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package cc.carm.lib.configuration.demo.tests;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
||||||
|
import cc.carm.lib.configuration.demo.tests.model.TestModel;
|
||||||
|
import cc.carm.lib.configuration.demo.tests.conf.DemoConfiguration;
|
||||||
|
import cc.carm.lib.configuration.demo.tests.conf.TestConfiguration;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
public class ConfigurationTest {
|
||||||
|
|
||||||
|
public static void testDemo(ConfigurationProvider<?> provider) {
|
||||||
|
provider.initialize(DemoConfiguration.class);
|
||||||
|
|
||||||
|
System.out.println("----------------------------------------------------");
|
||||||
|
|
||||||
|
System.out.println("Test Number: ");
|
||||||
|
|
||||||
|
System.out.println("before: " + DemoConfiguration.TEST_NUMBER.get());
|
||||||
|
DemoConfiguration.TEST_NUMBER.set((long) (Long.MAX_VALUE * Math.random()));
|
||||||
|
System.out.println("after: " + DemoConfiguration.TEST_NUMBER.get());
|
||||||
|
|
||||||
|
System.out.println("> Test Value:");
|
||||||
|
System.out.println("before: " + DemoConfiguration.Sub.UUID_CONFIG_VALUE.get());
|
||||||
|
DemoConfiguration.Sub.UUID_CONFIG_VALUE.set(UUID.randomUUID());
|
||||||
|
System.out.println("after: " + DemoConfiguration.Sub.UUID_CONFIG_VALUE.get());
|
||||||
|
|
||||||
|
System.out.println("> Test List:");
|
||||||
|
DemoConfiguration.Sub.That.OPERATORS.getNotNull().forEach(System.out::println);
|
||||||
|
List<UUID> operators = IntStream.range(0, 5).mapToObj(i -> UUID.randomUUID()).collect(Collectors.toList());
|
||||||
|
DemoConfiguration.Sub.That.OPERATORS.set(operators);
|
||||||
|
|
||||||
|
System.out.println("> Test Section:");
|
||||||
|
System.out.println(DemoConfiguration.MODEL_TEST.get());
|
||||||
|
DemoConfiguration.MODEL_TEST.set(TestModel.random());
|
||||||
|
|
||||||
|
System.out.println("> Test Maps:");
|
||||||
|
DemoConfiguration.USERS.getNotNull().forEach((k, v) -> System.out.println(k + ": " + v));
|
||||||
|
LinkedHashMap<Integer, UUID> data = new LinkedHashMap<>();
|
||||||
|
for (int i = 1; i <= 5; i++) {
|
||||||
|
data.put(i, UUID.randomUUID());
|
||||||
|
}
|
||||||
|
DemoConfiguration.USERS.set(data);
|
||||||
|
System.out.println("----------------------------------------------------");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void testInner(ConfigurationProvider<?> provider) {
|
||||||
|
|
||||||
|
TestConfiguration TEST = new TestConfiguration();
|
||||||
|
|
||||||
|
provider.initialize(TEST, true);
|
||||||
|
|
||||||
|
System.out.println("> Test Inner value before:");
|
||||||
|
System.out.println(TEST.INNER.INNER_VALUE.getNotNull());
|
||||||
|
|
||||||
|
double after = Math.random() * 200D;
|
||||||
|
System.out.println("> Test Inner value -> " + after);
|
||||||
|
TEST.INNER.INNER_VALUE.set(after);
|
||||||
|
|
||||||
|
System.out.println("> Test Inner value after:");
|
||||||
|
System.out.println(TEST.INNER.INNER_VALUE.getNotNull());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void save(ConfigurationProvider<?> provider) {
|
||||||
|
try {
|
||||||
|
provider.save();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package cc.carm.lib.configuration.demo.tests.conf;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.core.ConfigInitializer;
|
||||||
|
import cc.carm.lib.configuration.core.ConfigurationRoot;
|
||||||
|
import cc.carm.lib.configuration.core.annotation.ConfigPath;
|
||||||
|
import cc.carm.lib.configuration.core.annotation.HeaderComment;
|
||||||
|
import cc.carm.lib.configuration.core.annotation.InlineComment;
|
||||||
|
import cc.carm.lib.configuration.core.value.ConfigValue;
|
||||||
|
import cc.carm.lib.configuration.core.value.type.ConfiguredList;
|
||||||
|
import cc.carm.lib.configuration.core.value.type.ConfiguredMap;
|
||||||
|
import cc.carm.lib.configuration.core.value.type.ConfiguredSection;
|
||||||
|
import cc.carm.lib.configuration.core.value.type.ConfiguredValue;
|
||||||
|
import cc.carm.lib.configuration.demo.tests.model.TestModel;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
||||||
|
@HeaderComment({
|
||||||
|
"此处内容将显示在配置文件的最上方",
|
||||||
|
""/*添加一个空行与其他配置的注释分割*/
|
||||||
|
})
|
||||||
|
public class DemoConfiguration extends ConfigurationRoot {
|
||||||
|
|
||||||
|
@ConfigPath(root = true)
|
||||||
|
protected static final ConfigValue<Double> VERSION = ConfiguredValue.of(Double.class, 1.0D);
|
||||||
|
|
||||||
|
@ConfigPath(root = true)
|
||||||
|
public static final ConfigValue<Long> TEST_NUMBER = ConfiguredValue.of(Long.class, 1000000L);
|
||||||
|
|
||||||
|
// 支持通过 Class<?> 变量标注子配置,一并注册。
|
||||||
|
// 注意: 若对应类也有注解,则优先使用类的注解。
|
||||||
|
@ConfigPath("other-class-config") //支持通过注解修改子配置的主路径,若不修改则以变量名自动生成。
|
||||||
|
@HeaderComment({"", "Something..."}) // 支持给子路径直接打注释
|
||||||
|
@InlineComment("InlineComments for class path")
|
||||||
|
public static final Class<?> OTHER = OtherConfiguration.class;
|
||||||
|
|
||||||
|
@ConfigPath("user") // 通过注解规定配置文件中的路径,若不进行注解则以变量名自动生成。
|
||||||
|
@HeaderComment({"", "Section类型数据测试"}) // 通过注解给配置添加注释。
|
||||||
|
@InlineComment("Section数据也支持InlineComment注释")
|
||||||
|
public static final ConfigValue<TestModel> MODEL_TEST = ConfiguredSection
|
||||||
|
.builder(TestModel.class)
|
||||||
|
.defaults(new TestModel("Carm", UUID.randomUUID()))
|
||||||
|
.parseValue((section, defaultValue) -> TestModel.deserialize(section))
|
||||||
|
.serializeValue(TestModel::serialize).build();
|
||||||
|
|
||||||
|
@HeaderComment({"", "[ID - UUID]对照表", "", "用于测试Map类型的解析与序列化保存"})
|
||||||
|
public static final ConfigValue<Map<Integer, UUID>> USERS = ConfiguredMap
|
||||||
|
.builder(Integer.class, UUID.class).fromString()
|
||||||
|
.parseKey(Integer::parseInt)
|
||||||
|
.parseValue(v -> Objects.requireNonNull(UUID.fromString(v)))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支持内部类的直接注册。
|
||||||
|
* 注意,需要使用 {@link ConfigInitializer#initialize(Class, boolean, boolean)} 方法,并设定第三个参数为 true。
|
||||||
|
*/
|
||||||
|
public static class Sub extends ConfigurationRoot {
|
||||||
|
|
||||||
|
@ConfigPath(value = "uuid-value", root = true)
|
||||||
|
@InlineComment("This is an inline comment")
|
||||||
|
public static final ConfigValue<UUID> UUID_CONFIG_VALUE = ConfiguredValue
|
||||||
|
.builder(UUID.class).fromString()
|
||||||
|
.parseValue((data, defaultValue) -> UUID.fromString(data))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public static class That extends ConfigurationRoot {
|
||||||
|
|
||||||
|
public static final ConfigValue<List<UUID>> OPERATORS = ConfiguredList
|
||||||
|
.builder(UUID.class).fromString()
|
||||||
|
.parseValue(s -> Objects.requireNonNull(UUID.fromString(s)))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
package cc.carm.lib.configuration.demo.tests.conf;
|
||||||
|
|
||||||
|
public class OtherConfiguration {
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package cc.carm.lib.configuration.demo.tests.conf;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.core.ConfigurationRoot;
|
||||||
|
import cc.carm.lib.configuration.core.annotation.ConfigPath;
|
||||||
|
import cc.carm.lib.configuration.core.annotation.HeaderComment;
|
||||||
|
import cc.carm.lib.configuration.core.annotation.InlineComment;
|
||||||
|
import cc.carm.lib.configuration.core.value.ConfigValue;
|
||||||
|
import cc.carm.lib.configuration.core.value.type.ConfiguredSection;
|
||||||
|
import cc.carm.lib.configuration.core.value.type.ConfiguredValue;
|
||||||
|
import cc.carm.lib.configuration.demo.tests.model.TestModel;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class TestConfiguration extends ConfigurationRoot {
|
||||||
|
|
||||||
|
public final TestInnerConfiguration INNER = new TestInnerConfiguration();
|
||||||
|
|
||||||
|
public final ConfigValue<Double> CLASS_VALUE = ConfiguredValue.of(Double.class, 1.0D);
|
||||||
|
|
||||||
|
@ConfigPath("test.user") // 通过注解规定配置文件中的路径,若不进行注解则以变量名自动生成。
|
||||||
|
@HeaderComment({"", "Section类型数据测试"}) // 通过注解给配置添加注释。
|
||||||
|
@InlineComment("Section数据也支持InlineComment注释")
|
||||||
|
public final ConfigValue<TestModel> TEST_MODEL = ConfiguredSection
|
||||||
|
.builder(TestModel.class)
|
||||||
|
.defaults(new TestModel("Carm", UUID.randomUUID()))
|
||||||
|
.parseValue((section, defaultValue) -> TestModel.deserialize(section))
|
||||||
|
.serializeValue(TestModel::serialize).build();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
package cc.carm.lib.configuration.demo.tests.conf;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.core.ConfigurationRoot;
|
||||||
|
import cc.carm.lib.configuration.core.annotation.HeaderComment;
|
||||||
|
import cc.carm.lib.configuration.core.value.ConfigValue;
|
||||||
|
import cc.carm.lib.configuration.core.value.type.ConfiguredValue;
|
||||||
|
|
||||||
|
@HeaderComment("Inner Test")
|
||||||
|
public class TestInnerConfiguration extends ConfigurationRoot {
|
||||||
|
|
||||||
|
public final ConfigValue<Double> INNER_VALUE = ConfiguredValue.of(Double.class, 1.0D);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package cc.carm.lib.configuration.demo.tests.model;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public abstract class AbstractModel {
|
||||||
|
|
||||||
|
protected final @NotNull String name;
|
||||||
|
|
||||||
|
public AbstractModel(@NotNull String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package cc.carm.lib.configuration.demo.tests.model;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class TestModel extends AbstractModel {
|
||||||
|
|
||||||
|
public UUID uuid;
|
||||||
|
|
||||||
|
public TestModel(String name, UUID uuid) {
|
||||||
|
super(name);
|
||||||
|
this.uuid = uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUuid(UUID uuid) {
|
||||||
|
this.uuid = uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getUuid() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull Map<String, Object> serialize() {
|
||||||
|
Map<String, Object> map = new HashMap<>();
|
||||||
|
map.put("name", name);
|
||||||
|
Map<String, Object> map2 = new HashMap<>();
|
||||||
|
map2.put("uuid", uuid.toString());
|
||||||
|
map.put("info", map2);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TestModel deserialize(ConfigurationWrapper<?> section) {
|
||||||
|
String name = section.getString("name");
|
||||||
|
if (name == null) throw new NullPointerException("name is null");
|
||||||
|
String uuidString = section.getString("info.uuid");
|
||||||
|
if (uuidString == null) throw new NullPointerException("uuid is null");
|
||||||
|
return new TestModel(name, UUID.fromString(uuidString));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TestModel random() {
|
||||||
|
return new TestModel(UUID.randomUUID().toString().substring(0, 5), UUID.randomUUID());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "TestUser{" +
|
||||||
|
"name='" + name + '\'' +
|
||||||
|
", uuid=" + uuid +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,16 +5,17 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>easyconfiguration-parent</artifactId>
|
<artifactId>easyconfiguration-parent</artifactId>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<version>1.0.3</version>
|
<version>3.3.1</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<properties>
|
<properties>
|
||||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
<artifactId>easyconfiguration-json</artifactId>
|
||||||
<artifactId>easyconfiguration-bungee</artifactId>
|
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -27,19 +28,17 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>${project.parent.groupId}</groupId>
|
||||||
<artifactId>bungeecord-api</artifactId>
|
<artifactId>easyconfiguration-demo</artifactId>
|
||||||
<version>1.18-R0.1-SNAPSHOT</version>
|
<version>${project.parent.version}</version>
|
||||||
<type>jar</type>
|
<scope>test</scope>
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>com.google.code.gson</groupId>
|
||||||
<artifactId>bungeecord-api</artifactId>
|
<artifactId>gson</artifactId>
|
||||||
<version>1.18-R0.1-SNAPSHOT</version>
|
<version>2.10</version>
|
||||||
<type>javadoc</type>
|
<scope>compile</scope>
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
+6
-7
@@ -1,14 +1,14 @@
|
|||||||
package cc.carm.lib.configuration;
|
package cc.carm.lib.configuration;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.bungee.BungeeConfigProvider;
|
import cc.carm.lib.configuration.json.JSONConfigProvider;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class EasyConfiguration {
|
public class EasyConfiguration {
|
||||||
|
|
||||||
public static BungeeConfigProvider from(File file, String source) {
|
public static JSONConfigProvider from(File file, String source) {
|
||||||
BungeeConfigProvider provider = new BungeeConfigProvider(file);
|
JSONConfigProvider provider = new JSONConfigProvider(file);
|
||||||
try {
|
try {
|
||||||
provider.initializeFile(source);
|
provider.initializeFile(source);
|
||||||
provider.initializeConfig();
|
provider.initializeConfig();
|
||||||
@@ -18,17 +18,16 @@ public class EasyConfiguration {
|
|||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BungeeConfigProvider from(File file) {
|
public static JSONConfigProvider from(File file) {
|
||||||
return from(file, file.getName());
|
return from(file, file.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BungeeConfigProvider from(String fileName) {
|
public static JSONConfigProvider from(String fileName) {
|
||||||
return from(fileName, fileName);
|
return from(fileName, fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BungeeConfigProvider from(String fileName, String source) {
|
public static JSONConfigProvider from(String fileName, String source) {
|
||||||
return from(new File(fileName), source);
|
return from(new File(fileName), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package cc.carm.lib.configuration.json;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.core.ConfigInitializer;
|
||||||
|
import cc.carm.lib.configuration.core.source.ConfigurationComments;
|
||||||
|
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
||||||
|
import cc.carm.lib.configuration.core.source.impl.FileConfigProvider;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.JsonSerializer;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some code comes from BungeeCord's implementation of the JsonConfiguration.
|
||||||
|
*
|
||||||
|
* @author md_5, CarmJos
|
||||||
|
*/
|
||||||
|
public class JSONConfigProvider extends FileConfigProvider<JSONConfigWrapper> {
|
||||||
|
|
||||||
|
protected final Gson gson = new GsonBuilder()
|
||||||
|
.serializeNulls().disableHtmlEscaping().setPrettyPrinting()
|
||||||
|
.registerTypeAdapter(
|
||||||
|
JSONConfigWrapper.class,
|
||||||
|
(JsonSerializer<JSONConfigWrapper>) (src, typeOfSrc, context) -> context.serialize(src.data)
|
||||||
|
).create();
|
||||||
|
|
||||||
|
protected JSONConfigWrapper configuration;
|
||||||
|
protected ConfigInitializer<JSONConfigProvider> initializer;
|
||||||
|
|
||||||
|
public JSONConfigProvider(@NotNull File file) {
|
||||||
|
super(file);
|
||||||
|
this.initializer = new ConfigInitializer<>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initializeConfig() {
|
||||||
|
LinkedHashMap<?, ?> map = null;
|
||||||
|
|
||||||
|
try (FileInputStream is = new FileInputStream(file)) {
|
||||||
|
map = gson.fromJson(new InputStreamReader(is, StandardCharsets.UTF_8), LinkedHashMap.class);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (map == null) map = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
this.configuration = new JSONConfigWrapper(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull JSONConfigWrapper getConfiguration() {
|
||||||
|
return this.configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onReload() throws Exception {
|
||||||
|
super.reload();
|
||||||
|
initializeConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable ConfigurationComments getComments() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save() throws Exception {
|
||||||
|
try (Writer writer = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)) {
|
||||||
|
gson.toJson(configuration.data, writer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull ConfigInitializer<? extends ConfigurationProvider<JSONConfigWrapper>> getInitializer() {
|
||||||
|
return this.initializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
package cc.carm.lib.configuration.json;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some code comes from BungeeCord's implementation of the JsonConfiguration.
|
||||||
|
*
|
||||||
|
* @author md_5, CarmJos
|
||||||
|
*/
|
||||||
|
public class JSONConfigWrapper implements ConfigurationWrapper<Map<String, Object>> {
|
||||||
|
|
||||||
|
private static final char SEPARATOR = '.';
|
||||||
|
protected final Map<String, Object> data;
|
||||||
|
|
||||||
|
JSONConfigWrapper(Map<?, ?> map) {
|
||||||
|
this.data = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
for (Map.Entry<?, ?> entry : map.entrySet()) {
|
||||||
|
String key = (entry.getKey() == null) ? "null" : entry.getKey().toString();
|
||||||
|
|
||||||
|
if (entry.getValue() instanceof Map) {
|
||||||
|
this.data.put(key, new JSONConfigWrapper((Map<?, ?>) entry.getValue()));
|
||||||
|
} else {
|
||||||
|
this.data.put(key, entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Map<String, Object> getSource() {
|
||||||
|
return this.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Set<String> getKeys(boolean deep) {
|
||||||
|
return getValues(deep).keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Map<String, Object> getValues(boolean deep) {
|
||||||
|
if (deep) {
|
||||||
|
Map<String, Object> values = new LinkedHashMap<>();
|
||||||
|
mapChildrenValues(values, this, null, true);
|
||||||
|
return values;
|
||||||
|
} else return new LinkedHashMap<>(this.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(@NotNull String path, @Nullable Object value) {
|
||||||
|
if (value instanceof Map) {
|
||||||
|
value = new JSONConfigWrapper((Map<?, ?>) value);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONConfigWrapper section = getSectionFor(path);
|
||||||
|
if (section == this) {
|
||||||
|
if (value == null) {
|
||||||
|
this.data.remove(path);
|
||||||
|
} else {
|
||||||
|
this.data.put(path, value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
section.set(getChild(path), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(@NotNull String path) {
|
||||||
|
return get(path) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable Object get(@NotNull String path) {
|
||||||
|
JSONConfigWrapper section = getSectionFor(path);
|
||||||
|
return section == this ? data.get(path) : section.get(getChild(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isList(@NotNull String path) {
|
||||||
|
return get(path) instanceof List<?>;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable List<?> getList(@NotNull String path) {
|
||||||
|
Object val = get(path);
|
||||||
|
return (val instanceof List<?>) ? (List<?>) val : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isConfigurationSection(@NotNull String path) {
|
||||||
|
return get(path) instanceof JSONConfigWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable JSONConfigWrapper getConfigurationSection(@NotNull String path) {
|
||||||
|
Object val = get(path);
|
||||||
|
return (val instanceof JSONConfigWrapper) ? (JSONConfigWrapper) val : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JSONConfigWrapper getSectionFor(String path) {
|
||||||
|
int index = path.indexOf(SEPARATOR);
|
||||||
|
if (index == -1) return this;
|
||||||
|
|
||||||
|
String root = path.substring(0, index);
|
||||||
|
Object section = this.data.get(root);
|
||||||
|
if (section == null) {
|
||||||
|
section = new JSONConfigWrapper(new LinkedHashMap<>());
|
||||||
|
this.data.put(root, section);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (JSONConfigWrapper) section;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getChild(String path) {
|
||||||
|
int index = path.indexOf(SEPARATOR);
|
||||||
|
return (index == -1) ? path : path.substring(index + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void mapChildrenValues(@NotNull Map<String, Object> output, @NotNull JSONConfigWrapper section,
|
||||||
|
@Nullable String parent, boolean deep) {
|
||||||
|
for (Map.Entry<String, Object> entry : section.data.entrySet()) {
|
||||||
|
String path = (parent == null ? "" : parent + ".") + entry.getKey();
|
||||||
|
output.remove(path);
|
||||||
|
output.put(path, entry.getValue());
|
||||||
|
if (deep && entry.getValue() instanceof JSONConfigWrapper) {
|
||||||
|
this.mapChildrenValues(output, (JSONConfigWrapper) entry.getValue(), path, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package config;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.EasyConfiguration;
|
||||||
|
import cc.carm.lib.configuration.demo.tests.ConfigurationTest;
|
||||||
|
import cc.carm.lib.configuration.json.JSONConfigProvider;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class JSONConfigTest {
|
||||||
|
|
||||||
|
protected final JSONConfigProvider provider = EasyConfiguration.from("target/config.json", "config.json");
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onTest() {
|
||||||
|
|
||||||
|
ConfigurationTest.testDemo(this.provider);
|
||||||
|
ConfigurationTest.testInner(this.provider);
|
||||||
|
|
||||||
|
System.out.println("----------------------------------------------------");
|
||||||
|
provider.getConfiguration().getValues(true).forEach((k, v) -> System.out.println(k + ": " + v));
|
||||||
|
System.out.println("----------------------------------------------------");
|
||||||
|
provider.getConfiguration().getValues(false).forEach((k, v) -> System.out.println(k + ": " + v));
|
||||||
|
System.out.println("----------------------------------------------------");
|
||||||
|
|
||||||
|
ConfigurationTest.save(this.provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
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>
|
||||||
|
<groupId>cc.carm.lib</groupId>
|
||||||
|
<version>3.3.1</version>
|
||||||
|
<relativePath>../../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||||
|
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
||||||
|
|
||||||
|
<maven.deploy.skip>true</maven.deploy.skip>
|
||||||
|
</properties>
|
||||||
|
<artifactId>easyconfiguration-sql</artifactId>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.parent.groupId}</groupId>
|
||||||
|
<artifactId>easyconfiguration-core</artifactId>
|
||||||
|
<version>${project.parent.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package cc.carm.lib.configuration;
|
||||||
|
|
||||||
|
public class EasyConfiguration {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package cc.carm.lib.configuration.sql;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.core.ConfigInitializer;
|
||||||
|
import cc.carm.lib.configuration.core.source.ConfigurationComments;
|
||||||
|
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public class SQLConfigProvider extends ConfigurationProvider<SQLSectionWrapper> {
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull SQLSectionWrapper getConfiguration() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save() throws Exception {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onReload() throws Exception {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable ConfigurationComments getComments() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull ConfigInitializer<? extends ConfigurationProvider<SQLSectionWrapper>> getInitializer() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package cc.carm.lib.configuration.sql;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class SQLSectionWrapper implements ConfigurationWrapper<Map<String, Object>> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Map<String, Object> getSource() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Set<String> getKeys(boolean deep) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Map<String, Object> getValues(boolean deep) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(@NotNull String path, @Nullable Object value) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(@NotNull String path) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable Object get(@NotNull String path) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isList(@NotNull String path) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable List<?> getList(@NotNull String path) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isConfigurationSection(@NotNull String path) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable SQLSectionWrapper getConfigurationSection(@NotNull String path) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package cc.carm.lib.configuration.sql;
|
||||||
|
|
||||||
|
public class SQLValueParser {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS conf
|
||||||
|
(
|
||||||
|
`namespace` VARCHAR(255) NOT NULL, # 命名空间
|
||||||
|
`section` VARCHAR(255) NOT NULL, # 配置路径 (ConfigPath)
|
||||||
|
`type` VARCHAR(255) NOT NULL, # 数据类型 (Integer/Byte/List/Map/...)
|
||||||
|
`value` MEDIUMTEXT, # 配置项的值 (可能为JSON格式)
|
||||||
|
`inline_comments` TINYTEXT, # 行内注释
|
||||||
|
`header_comments` TEXT, # 顶部注释
|
||||||
|
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (`namespace`, `section`)
|
||||||
|
) ENGINE = InnoDB
|
||||||
|
DEFAULT CHARSET = utf8mb4;
|
||||||
|
|
||||||
+13
-4
@@ -5,13 +5,15 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>easyconfiguration-parent</artifactId>
|
<artifactId>easyconfiguration-parent</artifactId>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<version>1.0.3</version>
|
<version>3.3.1</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<properties>
|
<properties>
|
||||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<artifactId>easyconfiguration-yaml</artifactId>
|
<artifactId>easyconfiguration-yaml</artifactId>
|
||||||
@@ -27,9 +29,16 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>${project.parent.groupId}</groupId>
|
||||||
<artifactId>yamlconfiguration-commented</artifactId>
|
<artifactId>easyconfiguration-demo</artifactId>
|
||||||
<version>2.0.2</version>
|
<version>${project.parent.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.bspfsystems</groupId>
|
||||||
|
<artifactId>yamlconfiguration</artifactId>
|
||||||
|
<version>1.3.0</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
package cc.carm.lib.configuration;
|
package cc.carm.lib.configuration;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.yaml.YamlConfigProvider;
|
import cc.carm.lib.configuration.yaml.YAMLConfigProvider;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class EasyConfiguration {
|
public class EasyConfiguration {
|
||||||
|
|
||||||
public static YamlConfigProvider from(File file, String source) {
|
public static YAMLConfigProvider from(File file, String source) {
|
||||||
YamlConfigProvider provider = new YamlConfigProvider(file);
|
YAMLConfigProvider provider = new YAMLConfigProvider(file);
|
||||||
try {
|
try {
|
||||||
provider.initializeFile(source);
|
provider.initializeFile(source);
|
||||||
provider.initializeConfig();
|
provider.initializeConfig();
|
||||||
@@ -18,17 +18,16 @@ public class EasyConfiguration {
|
|||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static YamlConfigProvider from(File file) {
|
public static YAMLConfigProvider from(File file) {
|
||||||
return from(file, file.getName());
|
return from(file, file.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static YamlConfigProvider from(String fileName) {
|
public static YAMLConfigProvider from(String fileName) {
|
||||||
return from(fileName, fileName);
|
return from(fileName, fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static YamlConfigProvider from(String fileName, String source) {
|
public static YAMLConfigProvider from(String fileName, String source) {
|
||||||
return from(new File(fileName), source);
|
return from(new File(fileName), source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
package cc.carm.lib.configuration.yaml;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.core.source.ConfigurationComments;
|
||||||
|
import org.bspfsystems.yamlconfiguration.configuration.ConfigurationSection;
|
||||||
|
import org.bspfsystems.yamlconfiguration.file.FileConfiguration;
|
||||||
|
import org.bspfsystems.yamlconfiguration.file.YamlConfiguration;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.StringJoiner;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
import static cc.carm.lib.configuration.yaml.YAMLConfigProvider.SEPARATOR;
|
||||||
|
|
||||||
|
@SuppressWarnings("SpellCheckingInspection")
|
||||||
|
public class YAMLComments extends ConfigurationComments {
|
||||||
|
|
||||||
|
public @Nullable String buildHeaderComments(@Nullable String path, @NotNull String indents) {
|
||||||
|
List<String> comments = getHeaderComment(path);
|
||||||
|
if (comments == null || comments.size() == 0) return null;
|
||||||
|
|
||||||
|
StringJoiner joiner = new StringJoiner("\n");
|
||||||
|
for (String comment : comments) {
|
||||||
|
if (comment.length() == 0) joiner.add(" ");
|
||||||
|
else joiner.add(indents + "# " + comment);
|
||||||
|
}
|
||||||
|
return joiner + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从一个文件读取配置并写入注释到某个写入器中。
|
||||||
|
* 该方法的部分源代码借鉴自 tchristofferson/ConfigUpdater 项目。
|
||||||
|
*
|
||||||
|
* @param source 源配置文件
|
||||||
|
* @param writer 配置写入器
|
||||||
|
* @throws IOException 当写入发生错误时抛出
|
||||||
|
*/
|
||||||
|
public void writeComments(@NotNull YamlConfiguration source, @NotNull BufferedWriter writer) throws IOException {
|
||||||
|
FileConfiguration temp = new YamlConfiguration(); // 该对象用于临时记录配置内容
|
||||||
|
|
||||||
|
String configHeader = buildHeaderComments(null, "");
|
||||||
|
if (configHeader != null) writer.write(configHeader);
|
||||||
|
|
||||||
|
for (String fullKey : source.getKeys(true)) {
|
||||||
|
Object currentValue = source.get(fullKey);
|
||||||
|
|
||||||
|
String indents = getIndents(fullKey);
|
||||||
|
String headerComments = buildHeaderComments(fullKey, indents);
|
||||||
|
String inlineComment = getInlineComment(fullKey);
|
||||||
|
|
||||||
|
if (headerComments != null) writer.write(headerComments);
|
||||||
|
|
||||||
|
String[] splitFullKey = fullKey.split("[" + SEPARATOR + "]");
|
||||||
|
String trailingKey = splitFullKey[splitFullKey.length - 1];
|
||||||
|
|
||||||
|
if (currentValue instanceof ConfigurationSection) {
|
||||||
|
ConfigurationSection section = (ConfigurationSection) currentValue;
|
||||||
|
writer.write(indents + trailingKey + ":");
|
||||||
|
if (inlineComment != null && inlineComment.length() > 0) {
|
||||||
|
writer.write(" # " + inlineComment);
|
||||||
|
}
|
||||||
|
if (!section.getKeys(false).isEmpty()) {
|
||||||
|
writer.write("\n");
|
||||||
|
} else {
|
||||||
|
writer.write(" {}\n");
|
||||||
|
if (indents.length() == 0) writer.write("\n");
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
temp.set(trailingKey, currentValue);
|
||||||
|
String yaml = temp.saveToString();
|
||||||
|
temp.set(trailingKey, null);
|
||||||
|
|
||||||
|
yaml = yaml.substring(0, yaml.length() - 1);
|
||||||
|
|
||||||
|
if (inlineComment != null && inlineComment.length() > 0) {
|
||||||
|
if (yaml.contains("\n")) {
|
||||||
|
// section为多行内容,需要 InlineComment 加在首行末尾
|
||||||
|
String[] splitLine = yaml.split("\n", 2);
|
||||||
|
yaml = splitLine[0] + " # " + inlineComment + "\n" + splitLine[1];
|
||||||
|
} else {
|
||||||
|
// 其他情况下就直接加载后面就好。
|
||||||
|
yaml += " # " + inlineComment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.write(indents + yaml.replace("\n", "\n" + indents) + "\n");
|
||||||
|
if (indents.length() == 0) writer.write("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 得到一个键的缩进。
|
||||||
|
* 该方法的源代码来自 tchristofferson/ConfigUpdater 项目。
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @return 该键的缩进文本
|
||||||
|
*/
|
||||||
|
protected static String getIndents(String key) {
|
||||||
|
String[] splitKey = key.split("[" + YAMLConfigProvider.SEPARATOR + "]");
|
||||||
|
return IntStream.range(1, splitKey.length).mapToObj(i -> " ").collect(Collectors.joining());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
package cc.carm.lib.configuration.yaml;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.core.ConfigInitializer;
|
||||||
|
import cc.carm.lib.configuration.core.source.ConfigurationComments;
|
||||||
|
import cc.carm.lib.configuration.core.source.impl.FileConfigProvider;
|
||||||
|
import org.bspfsystems.yamlconfiguration.file.YamlConfiguration;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
public class YAMLConfigProvider extends FileConfigProvider<YAMLSectionWrapper> {
|
||||||
|
|
||||||
|
protected static final char SEPARATOR = '.';
|
||||||
|
|
||||||
|
protected final @NotNull YAMLComments comments = new YAMLComments();
|
||||||
|
protected YamlConfiguration configuration;
|
||||||
|
protected ConfigInitializer<YAMLConfigProvider> initializer;
|
||||||
|
|
||||||
|
public YAMLConfigProvider(@NotNull File file) {
|
||||||
|
super(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initializeConfig() {
|
||||||
|
this.configuration = YamlConfiguration.loadConfiguration(file);
|
||||||
|
this.initializer = new ConfigInitializer<>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull YAMLSectionWrapper getConfiguration() {
|
||||||
|
return YAMLSectionWrapper.of(configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onReload() throws Exception {
|
||||||
|
configuration.load(getFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable ConfigurationComments getComments() {
|
||||||
|
return this.comments;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("SpellCheckingInspection")
|
||||||
|
public void save() throws Exception {
|
||||||
|
configuration.save(getFile());
|
||||||
|
|
||||||
|
// tchristofferson/ConfigUpdater start
|
||||||
|
StringWriter writer = new StringWriter();
|
||||||
|
this.comments.writeComments(configuration, new BufferedWriter(writer));
|
||||||
|
String value = writer.toString(); // config contents
|
||||||
|
|
||||||
|
Path toUpdatePath = getFile().toPath();
|
||||||
|
if (!value.equals(new String(Files.readAllBytes(toUpdatePath), StandardCharsets.UTF_8))) {
|
||||||
|
// if updated contents are not the same as current file contents, update
|
||||||
|
Files.write(toUpdatePath, value.getBytes(StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
// tchristofferson/ConfigUpdater end
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull ConfigInitializer<YAMLConfigProvider> getInitializer() {
|
||||||
|
return this.initializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+23
-5
@@ -2,6 +2,7 @@ package cc.carm.lib.configuration.yaml;
|
|||||||
|
|
||||||
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
||||||
import org.bspfsystems.yamlconfiguration.configuration.ConfigurationSection;
|
import org.bspfsystems.yamlconfiguration.configuration.ConfigurationSection;
|
||||||
|
import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerializable;
|
||||||
import org.jetbrains.annotations.Contract;
|
import org.jetbrains.annotations.Contract;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -11,17 +12,22 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class YamlSectionWrapper implements ConfigurationWrapper {
|
public class YAMLSectionWrapper implements ConfigurationWrapper<ConfigurationSection> {
|
||||||
|
|
||||||
private final ConfigurationSection section;
|
private final ConfigurationSection section;
|
||||||
|
|
||||||
private YamlSectionWrapper(ConfigurationSection section) {
|
private YAMLSectionWrapper(ConfigurationSection section) {
|
||||||
this.section = section;
|
this.section = section;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Contract("!null->!null")
|
@Contract("!null->!null")
|
||||||
public static @Nullable YamlSectionWrapper of(@Nullable ConfigurationSection section) {
|
public static @Nullable YAMLSectionWrapper of(@Nullable ConfigurationSection section) {
|
||||||
return section == null ? null : new YamlSectionWrapper(section);
|
return section == null ? null : new YAMLSectionWrapper(section);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull ConfigurationSection getSource() {
|
||||||
|
return this.section;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -65,7 +71,19 @@ public class YamlSectionWrapper implements ConfigurationWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable ConfigurationWrapper getConfigurationSection(@NotNull String path) {
|
public @Nullable YAMLSectionWrapper getConfigurationSection(@NotNull String path) {
|
||||||
return of(this.section.getConfigurationSection(path));
|
return of(this.section.getConfigurationSection(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public <T extends ConfigurationSerializable> T getSerializable(@NotNull String path, @NotNull Class<T> clazz) {
|
||||||
|
return getSerializable(path, clazz, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Contract("_, _, !null -> !null")
|
||||||
|
public <T extends ConfigurationSerializable> T getSerializable(@NotNull String path, @NotNull Class<T> clazz, @Nullable T defaultValue) {
|
||||||
|
return this.section.getSerializable(path, clazz, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package cc.carm.lib.configuration.yaml;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
||||||
|
import cc.carm.lib.configuration.core.value.impl.CachedConfigValue;
|
||||||
|
import cc.carm.lib.configuration.yaml.builder.YAMLConfigBuilder;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public abstract class YAMLValue<T> extends CachedConfigValue<T> {
|
||||||
|
|
||||||
|
public static @NotNull YAMLConfigBuilder builder() {
|
||||||
|
return new YAMLConfigBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public YAMLValue(@Nullable YAMLConfigProvider provider, @Nullable String configPath,
|
||||||
|
@Nullable List<String> headerComments, @Nullable String inlineComments,
|
||||||
|
@Nullable T defaultValue) {
|
||||||
|
super(provider, configPath, headerComments, inlineComments, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public YAMLConfigProvider getYAMLProvider() {
|
||||||
|
ConfigurationProvider<?> provider = getProvider();
|
||||||
|
if (provider instanceof YAMLConfigProvider) return (YAMLConfigProvider) getProvider();
|
||||||
|
else throw new IllegalStateException("Provider is not a YamlConfigProvider");
|
||||||
|
}
|
||||||
|
|
||||||
|
public YAMLSectionWrapper getYAMLConfig() {
|
||||||
|
return getYAMLProvider().getConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
package cc.carm.lib.configuration.yaml;
|
|
||||||
|
|
||||||
import org.bspfsystems.yamlconfiguration.commented.CommentsProvider;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class YamlComments implements CommentsProvider {
|
|
||||||
|
|
||||||
Map<String, String[]> comments = new HashMap<>();
|
|
||||||
|
|
||||||
protected Map<String, String[]> getComments() {
|
|
||||||
return comments;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void set(@NotNull String path, @NotNull String... comments) {
|
|
||||||
if (comments.length == 0) {
|
|
||||||
getComments().remove(path);
|
|
||||||
} else {
|
|
||||||
getComments().put(path, comments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public @Nullable String[] get(@NotNull String path) {
|
|
||||||
return getComments().get(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] apply(String s) {
|
|
||||||
return get(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
package cc.carm.lib.configuration.yaml;
|
|
||||||
|
|
||||||
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
|
||||||
import cc.carm.lib.configuration.core.source.impl.FileConfigProvider;
|
|
||||||
import org.bspfsystems.yamlconfiguration.commented.CommentedYamlConfiguration;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
public class YamlConfigProvider extends FileConfigProvider {
|
|
||||||
|
|
||||||
YamlComments comments = new YamlComments();
|
|
||||||
CommentedYamlConfiguration configuration;
|
|
||||||
|
|
||||||
public YamlConfigProvider(@NotNull File file) {
|
|
||||||
super(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initializeConfig() {
|
|
||||||
this.configuration = CommentedYamlConfiguration.loadConfiguration(comments, file);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull ConfigurationWrapper getConfiguration() {
|
|
||||||
return YamlSectionWrapper.of(configuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reload() throws Exception {
|
|
||||||
configuration.load(getFile());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void save() throws Exception {
|
|
||||||
configuration.save(getFile());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setComments(@NotNull String path, @NotNull String... comments) {
|
|
||||||
this.comments.set(path, comments);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable String[] getComments(@NotNull String path) {
|
|
||||||
return this.comments.get(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
package cc.carm.lib.configuration.yaml.builder;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.core.builder.AbstractConfigBuilder;
|
||||||
|
import cc.carm.lib.configuration.yaml.YAMLConfigProvider;
|
||||||
|
|
||||||
|
public abstract class AbstractYAMLBuilder<T, B extends AbstractYAMLBuilder<T, B>>
|
||||||
|
extends AbstractConfigBuilder<T, B, YAMLConfigProvider> {
|
||||||
|
|
||||||
|
public AbstractYAMLBuilder() {
|
||||||
|
super(YAMLConfigProvider.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package cc.carm.lib.configuration.yaml.builder;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.core.builder.ConfigBuilder;
|
||||||
|
import cc.carm.lib.configuration.yaml.builder.serializable.SerializableBuilder;
|
||||||
|
import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerializable;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class YAMLConfigBuilder extends ConfigBuilder {
|
||||||
|
|
||||||
|
public <V extends ConfigurationSerializable> @NotNull SerializableBuilder<V> ofSerializable(@NotNull Class<V> valueClass) {
|
||||||
|
return new SerializableBuilder<>(valueClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
package cc.carm.lib.configuration.yaml.builder.serializable;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.yaml.builder.AbstractYAMLBuilder;
|
||||||
|
import cc.carm.lib.configuration.yaml.value.ConfiguredSerializable;
|
||||||
|
import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerializable;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class SerializableBuilder<T extends ConfigurationSerializable>
|
||||||
|
extends AbstractYAMLBuilder<T, SerializableBuilder<T>> {
|
||||||
|
|
||||||
|
protected final @NotNull Class<T> valueClass;
|
||||||
|
|
||||||
|
public SerializableBuilder(@NotNull Class<T> valueClass) {
|
||||||
|
this.valueClass = valueClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull SerializableBuilder<T> getThis() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull ConfiguredSerializable<T> build() {
|
||||||
|
return new ConfiguredSerializable<>(this.provider, this.path, this.headerComments, this.inlineComment, this.valueClass, this.defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
+53
@@ -0,0 +1,53 @@
|
|||||||
|
package cc.carm.lib.configuration.yaml.value;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.yaml.YAMLConfigProvider;
|
||||||
|
import cc.carm.lib.configuration.yaml.YAMLValue;
|
||||||
|
import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerializable;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class ConfiguredSerializable<T extends ConfigurationSerializable> extends YAMLValue<T> {
|
||||||
|
|
||||||
|
public static <V extends ConfigurationSerializable> ConfiguredSerializable<V> of(@NotNull Class<V> valueClass) {
|
||||||
|
return of(valueClass, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <V extends ConfigurationSerializable> ConfiguredSerializable<V> of(@NotNull Class<V> valueClass,
|
||||||
|
@Nullable V defaultValue) {
|
||||||
|
return builder().ofSerializable(valueClass).defaults(defaultValue).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final @NotNull Class<T> valueClass;
|
||||||
|
|
||||||
|
public ConfiguredSerializable(@Nullable YAMLConfigProvider provider, @Nullable String configPath,
|
||||||
|
@Nullable List<String> headerComments, @Nullable String inlineComments,
|
||||||
|
@NotNull Class<T> valueClass, @Nullable T defaultValue) {
|
||||||
|
super(provider, configPath, headerComments, inlineComments, defaultValue);
|
||||||
|
this.valueClass = valueClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable T get() {
|
||||||
|
if (isExpired()) { // 已过时的数据,需要重新解析一次。
|
||||||
|
try {
|
||||||
|
// 若未出现错误,则直接更新缓存并返回。
|
||||||
|
return updateCache(getYAMLConfig().getSerializable(getConfigPath(), valueClass, getDefaultValue()));
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 出现了解析错误,提示并返回默认值。
|
||||||
|
e.printStackTrace();
|
||||||
|
return useDefault();
|
||||||
|
}
|
||||||
|
} else return Optional.ofNullable(getCachedValue()).orElse(defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(@Nullable T value) {
|
||||||
|
updateCache(value);
|
||||||
|
setValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
package config;
|
|
||||||
|
|
||||||
import cc.carm.lib.configuration.EasyConfiguration;
|
|
||||||
import cc.carm.lib.configuration.core.ConfigInitializer;
|
|
||||||
import cc.carm.lib.configuration.yaml.YamlConfigProvider;
|
|
||||||
import config.misc.TestUser;
|
|
||||||
import config.source.TestConfiguration;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.IntStream;
|
|
||||||
|
|
||||||
public class ConfigTester {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void onTest() {
|
|
||||||
|
|
||||||
YamlConfigProvider provider = EasyConfiguration.from("target/config.yml", "config.yml");
|
|
||||||
ConfigInitializer.initialize(provider, TestConfiguration.class, true);
|
|
||||||
|
|
||||||
System.out.println("before: " + TestConfiguration.Sub.UUID_CONFIG_VALUE.get());
|
|
||||||
TestConfiguration.Sub.UUID_CONFIG_VALUE.set(UUID.randomUUID());
|
|
||||||
System.out.println("after: " + TestConfiguration.Sub.UUID_CONFIG_VALUE.get());
|
|
||||||
|
|
||||||
|
|
||||||
TestConfiguration.Sub.That.Operators.getNotNull().forEach(System.out::println);
|
|
||||||
List<UUID> operators = IntStream.range(0, 5).mapToObj(i -> UUID.randomUUID()).collect(Collectors.toList());
|
|
||||||
TestConfiguration.Sub.That.Operators.set(operators);
|
|
||||||
|
|
||||||
System.out.println(TestConfiguration.USER.get());
|
|
||||||
TestUser b = new TestUser(UUID.randomUUID().toString().substring(0, 3), UUID.randomUUID());
|
|
||||||
TestConfiguration.USER.set(b);
|
|
||||||
|
|
||||||
TestConfiguration.USERS.getNotNull().forEach((k, v) -> System.out.println(k + ": " + v));
|
|
||||||
LinkedHashMap<Integer, UUID> data = new LinkedHashMap<>();
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
data.put((int) (1000 * Math.random()), UUID.randomUUID());
|
|
||||||
}
|
|
||||||
TestConfiguration.USERS.set(data);
|
|
||||||
|
|
||||||
try {
|
|
||||||
provider.save();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package config;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.EasyConfiguration;
|
||||||
|
import cc.carm.lib.configuration.demo.tests.ConfigurationTest;
|
||||||
|
import cc.carm.lib.configuration.demo.tests.model.AbstractModel;
|
||||||
|
import cc.carm.lib.configuration.yaml.YAMLConfigProvider;
|
||||||
|
import config.model.AnyModel;
|
||||||
|
import config.model.SomeModel;
|
||||||
|
import config.source.ModelConfiguration;
|
||||||
|
import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerialization;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class DemoConfigTest {
|
||||||
|
|
||||||
|
static {
|
||||||
|
ConfigurationSerialization.registerClass(SomeModel.class);
|
||||||
|
ConfigurationSerialization.registerClass(AnyModel.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final YAMLConfigProvider provider = EasyConfiguration.from("target/config.yml", "config.yml");
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onTest() {
|
||||||
|
ConfigurationTest.testDemo(this.provider);
|
||||||
|
ConfigurationTest.testInner(this.provider);
|
||||||
|
|
||||||
|
testSerialization(this.provider);
|
||||||
|
|
||||||
|
ConfigurationTest.save(this.provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void testSerialization(YAMLConfigProvider provider) {
|
||||||
|
provider.initialize(ModelConfiguration.class);
|
||||||
|
System.out.println("----------------------------------------------------");
|
||||||
|
|
||||||
|
AbstractModel someModel = ModelConfiguration.SOME_MODEL.get();
|
||||||
|
if (someModel != null) System.out.println(someModel.getName());
|
||||||
|
|
||||||
|
AbstractModel anyModel = ModelConfiguration.ANY_MODEL.get();
|
||||||
|
if (anyModel != null) System.out.println(anyModel.getName());
|
||||||
|
|
||||||
|
System.out.println("----------------------------------------------------");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
package config.misc;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class TestUser {
|
|
||||||
|
|
||||||
public String name;
|
|
||||||
public UUID uuid;
|
|
||||||
|
|
||||||
public TestUser(String name, UUID uuid) {
|
|
||||||
this.name = name;
|
|
||||||
this.uuid = uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUuid(UUID uuid) {
|
|
||||||
this.uuid = uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UUID getUuid() {
|
|
||||||
return uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "TestUser{" +
|
|
||||||
"name='" + name + '\'' +
|
|
||||||
", uuid=" + uuid +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package config.model;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.demo.tests.model.AbstractModel;
|
||||||
|
import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerializable;
|
||||||
|
import org.bspfsystems.yamlconfiguration.serialization.SerializableAs;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.TestOnly;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@SerializableAs("AnyModel")
|
||||||
|
public class AnyModel extends AbstractModel implements ConfigurationSerializable {
|
||||||
|
|
||||||
|
public final boolean bool;
|
||||||
|
|
||||||
|
public AnyModel(@NotNull String name, boolean bool) {
|
||||||
|
super(name);
|
||||||
|
this.bool = bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "AnyModel{" +
|
||||||
|
"name='" + name + '\'' +
|
||||||
|
", bool=" + bool +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Map<String, Object> serialize() {
|
||||||
|
Map<String, Object> map = new HashMap<>();
|
||||||
|
map.put("name", name);
|
||||||
|
map.put("state", bool);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AnyModel random() {
|
||||||
|
return new AnyModel(UUID.randomUUID().toString().substring(0, 5), Math.random() > 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@TestOnly
|
||||||
|
public static AnyModel deserialize(Map<String, ?> args) {
|
||||||
|
return new AnyModel((String) args.get("name"), (Boolean) args.get("state"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package config.model;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.demo.tests.model.AbstractModel;
|
||||||
|
import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerializable;
|
||||||
|
import org.bspfsystems.yamlconfiguration.serialization.SerializableAs;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.TestOnly;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@SerializableAs("SomeModel")
|
||||||
|
public class SomeModel extends AbstractModel implements ConfigurationSerializable {
|
||||||
|
|
||||||
|
public final int num;
|
||||||
|
|
||||||
|
public SomeModel(@NotNull String name, int num) {
|
||||||
|
super(name);
|
||||||
|
this.num = num;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "SomeModel{" +
|
||||||
|
"name='" + name + '\'' +
|
||||||
|
", num=" + num +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Map<String, Object> serialize() {
|
||||||
|
Map<String, Object> map = new HashMap<>();
|
||||||
|
map.put("name", name);
|
||||||
|
map.put("num", num);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SomeModel random() {
|
||||||
|
return new SomeModel(UUID.randomUUID().toString().substring(0, 5), (int) (Math.random() * 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@TestOnly
|
||||||
|
public static SomeModel deserialize(Map<String, ?> args) {
|
||||||
|
return new SomeModel((String) args.get("name"), (Integer) args.get("num"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package config.source;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.core.ConfigurationRoot;
|
||||||
|
import cc.carm.lib.configuration.core.annotation.ConfigPath;
|
||||||
|
import cc.carm.lib.configuration.core.value.ConfigValue;
|
||||||
|
import cc.carm.lib.configuration.demo.tests.model.AbstractModel;
|
||||||
|
import cc.carm.lib.configuration.yaml.value.ConfiguredSerializable;
|
||||||
|
import config.model.AnyModel;
|
||||||
|
import config.model.SomeModel;
|
||||||
|
|
||||||
|
@ConfigPath("model-test")
|
||||||
|
public class ModelConfiguration extends ConfigurationRoot {
|
||||||
|
|
||||||
|
public static final ConfigValue<? extends AbstractModel> SOME_MODEL = ConfiguredSerializable.of(
|
||||||
|
SomeModel.class, SomeModel.random()
|
||||||
|
);
|
||||||
|
|
||||||
|
public static final ConfigValue<? extends AbstractModel> ANY_MODEL = ConfiguredSerializable.of(
|
||||||
|
AnyModel.class, AnyModel.random()
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
package config.source;
|
|
||||||
|
|
||||||
import cc.carm.lib.configuration.core.ConfigurationRoot;
|
|
||||||
import cc.carm.lib.configuration.core.annotation.ConfigComment;
|
|
||||||
import cc.carm.lib.configuration.core.annotation.ConfigPath;
|
|
||||||
import cc.carm.lib.configuration.core.util.MapFactory;
|
|
||||||
import cc.carm.lib.configuration.core.value.ConfigValue;
|
|
||||||
import cc.carm.lib.configuration.core.value.type.ConfiguredList;
|
|
||||||
import cc.carm.lib.configuration.core.value.type.ConfiguredMap;
|
|
||||||
import cc.carm.lib.configuration.core.value.type.ConfiguredSection;
|
|
||||||
import cc.carm.lib.configuration.core.value.type.ConfiguredValue;
|
|
||||||
import config.misc.TestUser;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class TestConfiguration extends ConfigurationRoot {
|
|
||||||
|
|
||||||
@ConfigComment({"User测试"})
|
|
||||||
public static final ConfigValue<TestUser> USER = ConfiguredSection
|
|
||||||
.builder(TestUser.class)
|
|
||||||
.defaults(new TestUser("Carm", UUID.randomUUID()))
|
|
||||||
.parseValue((section, defaultValue) -> new TestUser(
|
|
||||||
section.getString("name"),
|
|
||||||
UUID.fromString(section.getString("user.uuid", UUID.randomUUID().toString()))
|
|
||||||
)).serializeValue(user -> MapFactory.<String, Object>linkedMap()
|
|
||||||
.put("name", user.getName())
|
|
||||||
.put("user.uuid", user.getUuid().toString())
|
|
||||||
.build()
|
|
||||||
).build();
|
|
||||||
|
|
||||||
@ConfigComment({"[ID-UUID] 对照表", "", "用于测试Map类型的解析与序列化保存"})
|
|
||||||
public static final ConfigValue<Map<Integer, UUID>> USERS = ConfiguredMap
|
|
||||||
.builder(Integer.class, UUID.class).fromString()
|
|
||||||
.parseKey(Integer::parseInt)
|
|
||||||
.parseValue(v -> Objects.requireNonNull(UUID.fromString(v)))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
public static class Sub {
|
|
||||||
|
|
||||||
@ConfigPath("uuid")
|
|
||||||
public static final ConfigValue<UUID> UUID_CONFIG_VALUE = ConfiguredValue
|
|
||||||
.builder(UUID.class).fromString()
|
|
||||||
.parseValue((data, defaultValue) -> UUID.fromString(data))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
@ConfigPath("nothing")
|
|
||||||
public static class That {
|
|
||||||
|
|
||||||
public static final ConfigValue<List<UUID>> Operators = ConfiguredList
|
|
||||||
.builder(UUID.class).fromString()
|
|
||||||
.parseValue(s -> Objects.requireNonNull(UUID.fromString(s)))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1 +1,2 @@
|
|||||||
something: 123123
|
# Test Header
|
||||||
|
version: 1.0
|
||||||
-54
@@ -1,54 +0,0 @@
|
|||||||
package cc.carm.lib.configuration.bungee;
|
|
||||||
|
|
||||||
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
|
||||||
import cc.carm.lib.configuration.core.source.impl.FileConfigProvider;
|
|
||||||
import net.md_5.bungee.config.Configuration;
|
|
||||||
import net.md_5.bungee.config.ConfigurationProvider;
|
|
||||||
import net.md_5.bungee.config.YamlConfiguration;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class BungeeConfigProvider extends FileConfigProvider {
|
|
||||||
|
|
||||||
Configuration configuration;
|
|
||||||
|
|
||||||
public BungeeConfigProvider(@NotNull File file) {
|
|
||||||
super(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initializeConfig() throws IOException {
|
|
||||||
this.configuration = getLoader().load(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull ConfigurationWrapper getConfiguration() {
|
|
||||||
return BungeeSectionWrapper.of(configuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reload() throws Exception {
|
|
||||||
this.configuration = getLoader().load(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void save() throws Exception {
|
|
||||||
getLoader().save(configuration, file);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setComments(@NotNull String path, @NotNull String... comments) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable String[] getComments(@NotNull String path) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ConfigurationProvider getLoader() {
|
|
||||||
return ConfigurationProvider.getProvider(YamlConfiguration.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
-70
@@ -1,70 +0,0 @@
|
|||||||
package cc.carm.lib.configuration.bungee;
|
|
||||||
|
|
||||||
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
|
||||||
import net.md_5.bungee.config.Configuration;
|
|
||||||
import org.jetbrains.annotations.Contract;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class BungeeSectionWrapper implements ConfigurationWrapper {
|
|
||||||
|
|
||||||
private final Configuration section;
|
|
||||||
|
|
||||||
private BungeeSectionWrapper(Configuration section) {
|
|
||||||
this.section = section;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Contract("!null->!null")
|
|
||||||
public static @Nullable BungeeSectionWrapper of(@Nullable Configuration section) {
|
|
||||||
return section == null ? null : new BungeeSectionWrapper(section);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Set<String> getKeys(boolean deep) {
|
|
||||||
return new LinkedHashSet<>(section.getKeys());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Map<String, Object> getValues(boolean deep) {
|
|
||||||
return section.getKeys().stream()
|
|
||||||
.collect(Collectors.toMap(key -> key, section::get, (a, b) -> b, LinkedHashMap::new));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void set(@NotNull String path, @Nullable Object value) {
|
|
||||||
this.section.set(path, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean contains(@NotNull String path) {
|
|
||||||
return this.section.contains(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable Object get(@NotNull String path) {
|
|
||||||
return this.section.get(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isList(@NotNull String path) {
|
|
||||||
return get(path) instanceof List<?>;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable List<?> getList(@NotNull String path) {
|
|
||||||
return this.section.getList(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isConfigurationSection(@NotNull String path) {
|
|
||||||
return true; // No provided functions :( SRY
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable ConfigurationWrapper getConfigurationSection(@NotNull String path) {
|
|
||||||
return of(this.section.getSection(path));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
package cc.carm.lib.configuration;
|
|
||||||
|
|
||||||
import cc.carm.lib.configuration.spigot.SpigotConfigProvider;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class EasyConfiguration {
|
|
||||||
|
|
||||||
|
|
||||||
public static SpigotConfigProvider from(File file, String source) {
|
|
||||||
SpigotConfigProvider provider = new SpigotConfigProvider(file);
|
|
||||||
try {
|
|
||||||
provider.initializeFile(source);
|
|
||||||
provider.initializeConfig();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return provider;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SpigotConfigProvider from(File file) {
|
|
||||||
return from(file, file.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SpigotConfigProvider from(String fileName) {
|
|
||||||
return from(fileName, fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SpigotConfigProvider from(String fileName, String source) {
|
|
||||||
return from(new File(fileName), source);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
-1513
File diff suppressed because it is too large
Load Diff
@@ -1,73 +0,0 @@
|
|||||||
package cc.carm.lib.configuration.commented;
|
|
||||||
|
|
||||||
import org.yaml.snakeyaml.DumperOptions;
|
|
||||||
import org.yaml.snakeyaml.Yaml;
|
|
||||||
import org.yaml.snakeyaml.constructor.BaseConstructor;
|
|
||||||
import org.yaml.snakeyaml.error.YAMLException;
|
|
||||||
import org.yaml.snakeyaml.nodes.Node;
|
|
||||||
import org.yaml.snakeyaml.nodes.Tag;
|
|
||||||
import org.yaml.snakeyaml.representer.Representer;
|
|
||||||
import org.yaml.snakeyaml.serializer.Serializer;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.io.Writer;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An hacky extension of {@link Yaml} that allows to write comments when dumping.
|
|
||||||
*/
|
|
||||||
public class CommentedYaml extends Yaml {
|
|
||||||
|
|
||||||
private final CommentsProvider commentsProvider;
|
|
||||||
|
|
||||||
public CommentedYaml(BaseConstructor constructor, Representer representer, DumperOptions dumperOptions, CommentsProvider commentsProvider) {
|
|
||||||
super(constructor, representer, dumperOptions);
|
|
||||||
this.commentsProvider = commentsProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String dump(Object data) {
|
|
||||||
List<Object> list = new ArrayList<>(1);
|
|
||||||
list.add(data);
|
|
||||||
return this.dumpAll(list.iterator());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void dump(Object data, Writer output) {
|
|
||||||
List<Object> list = new ArrayList<>(1);
|
|
||||||
list.add(data);
|
|
||||||
this.dumpAll(list.iterator(), output, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String dumpAll(Iterator<?> data) {
|
|
||||||
StringWriter buffer = new StringWriter();
|
|
||||||
this.dumpAll(data, buffer, null);
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void dumpAll(Iterator<?> data, Writer output) {
|
|
||||||
this.dumpAll(data, output, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void dumpAll(Iterator<?> data, Writer output, Tag rootTag) {
|
|
||||||
Serializer serializer = new Serializer(new CommentedEmitter(output, this.dumperOptions, this.commentsProvider), this.resolver, this.dumperOptions, rootTag);
|
|
||||||
|
|
||||||
try {
|
|
||||||
serializer.open();
|
|
||||||
|
|
||||||
while (data.hasNext()) {
|
|
||||||
Node node = this.representer.represent(data.next());
|
|
||||||
serializer.serialize(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
serializer.close();
|
|
||||||
} catch (IOException var6) {
|
|
||||||
throw new YAMLException(var6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-69
@@ -1,69 +0,0 @@
|
|||||||
package cc.carm.lib.configuration.commented;
|
|
||||||
|
|
||||||
import org.bukkit.configuration.InvalidConfigurationException;
|
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
|
||||||
import org.bukkit.configuration.file.YamlConstructor;
|
|
||||||
import org.bukkit.configuration.file.YamlRepresenter;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.yaml.snakeyaml.DumperOptions;
|
|
||||||
import org.yaml.snakeyaml.representer.Representer;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.Reader;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A yaml file with comments on certain properties, as returned by the given {@link CommentsProvider}.
|
|
||||||
* Unlike {@link YamlConfiguration}, this class does not provide a header support.
|
|
||||||
*/
|
|
||||||
public class CommentedYamlConfiguration extends YamlConfiguration {
|
|
||||||
|
|
||||||
private final DumperOptions yamlOptions = new DumperOptions();
|
|
||||||
private final Representer yamlRepresenter = new YamlRepresenter();
|
|
||||||
private final CommentedYaml yaml;
|
|
||||||
|
|
||||||
public CommentedYamlConfiguration(CommentsProvider commentsProvider) {
|
|
||||||
this.yaml = new CommentedYaml(new YamlConstructor(), this.yamlRepresenter, this.yamlOptions, commentsProvider);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CommentedYamlConfiguration loadConfiguration(CommentsProvider commentsProvider, File file) {
|
|
||||||
CommentedYamlConfiguration config = new CommentedYamlConfiguration(commentsProvider);
|
|
||||||
|
|
||||||
try {
|
|
||||||
config.load(file);
|
|
||||||
} catch (FileNotFoundException ignored) {
|
|
||||||
} catch (IOException | InvalidConfigurationException var4) {
|
|
||||||
var4.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CommentedYamlConfiguration loadConfiguration(CommentsProvider commentsProvider, Reader reader) {
|
|
||||||
CommentedYamlConfiguration config = new CommentedYamlConfiguration(commentsProvider);
|
|
||||||
|
|
||||||
try {
|
|
||||||
config.load(reader);
|
|
||||||
} catch (IOException | InvalidConfigurationException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull String saveToString() {
|
|
||||||
this.yamlOptions.setIndent(this.options().indent());
|
|
||||||
this.yamlOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
|
||||||
this.yamlRepresenter.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
|
||||||
String dump = this.yaml.dump(this.getValues(false));
|
|
||||||
if (dump.equals("{}\n")) {
|
|
||||||
dump = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// No header support.
|
|
||||||
|
|
||||||
return dump;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-7
@@ -1,7 +0,0 @@
|
|||||||
package cc.carm.lib.configuration.commented;
|
|
||||||
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
|
|
||||||
public interface CommentsProvider extends Function<String, String[]> {
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
package cc.carm.lib.configuration.spigot;
|
|
||||||
|
|
||||||
import cc.carm.lib.configuration.commented.CommentsProvider;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class ConfigComments implements CommentsProvider {
|
|
||||||
|
|
||||||
Map<String, String[]> comments = new HashMap<>();
|
|
||||||
|
|
||||||
protected Map<String, String[]> getComments() {
|
|
||||||
return comments;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void set(@NotNull String path, @NotNull String... comments) {
|
|
||||||
if (comments.length == 0) {
|
|
||||||
getComments().remove(path);
|
|
||||||
} else {
|
|
||||||
getComments().put(path, comments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public @Nullable String[] get(@NotNull String path) {
|
|
||||||
return getComments().get(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] apply(String s) {
|
|
||||||
return get(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
-49
@@ -1,49 +0,0 @@
|
|||||||
package cc.carm.lib.configuration.spigot;
|
|
||||||
|
|
||||||
import cc.carm.lib.configuration.commented.CommentedYamlConfiguration;
|
|
||||||
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
|
||||||
import cc.carm.lib.configuration.core.source.impl.FileConfigProvider;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
public class SpigotConfigProvider extends FileConfigProvider {
|
|
||||||
|
|
||||||
ConfigComments comments = new ConfigComments();
|
|
||||||
CommentedYamlConfiguration configuration;
|
|
||||||
|
|
||||||
public SpigotConfigProvider(@NotNull File file) {
|
|
||||||
super(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initializeConfig() {
|
|
||||||
this.configuration = CommentedYamlConfiguration.loadConfiguration(comments, file);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull ConfigurationWrapper getConfiguration() {
|
|
||||||
return SpigotSectionWrapper.of(configuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reload() throws Exception {
|
|
||||||
configuration.load(getFile());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void save() throws Exception {
|
|
||||||
configuration.save(getFile());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setComments(@NotNull String path, @NotNull String... comments) {
|
|
||||||
this.comments.set(path, comments);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable String[] getComments(@NotNull String path) {
|
|
||||||
return this.comments.get(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
-71
@@ -1,71 +0,0 @@
|
|||||||
package cc.carm.lib.configuration.spigot;
|
|
||||||
|
|
||||||
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
|
||||||
import org.jetbrains.annotations.Contract;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class SpigotSectionWrapper implements ConfigurationWrapper {
|
|
||||||
|
|
||||||
private final ConfigurationSection section;
|
|
||||||
|
|
||||||
private SpigotSectionWrapper(ConfigurationSection section) {
|
|
||||||
this.section = section;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Contract("!null->!null")
|
|
||||||
public static @Nullable SpigotSectionWrapper of(@Nullable ConfigurationSection section) {
|
|
||||||
return section == null ? null : new SpigotSectionWrapper(section);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Set<String> getKeys(boolean deep) {
|
|
||||||
return new LinkedHashSet<>(section.getKeys(deep));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Map<String, Object> getValues(boolean deep) {
|
|
||||||
return section.getValues(deep);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void set(@NotNull String path, @Nullable Object value) {
|
|
||||||
this.section.set(path, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean contains(@NotNull String path) {
|
|
||||||
return this.section.contains(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable Object get(@NotNull String path) {
|
|
||||||
return this.section.get(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isList(@NotNull String path) {
|
|
||||||
return this.section.isList(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable List<?> getList(@NotNull String path) {
|
|
||||||
return this.section.getList(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isConfigurationSection(@NotNull String path) {
|
|
||||||
return this.section.isConfigurationSection(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable ConfigurationWrapper getConfigurationSection(@NotNull String path) {
|
|
||||||
return of(this.section.getConfigurationSection(path));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>8</java.version>
|
<java.version>1.8</java.version>
|
||||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
@@ -15,14 +15,13 @@
|
|||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<artifactId>easyconfiguration-parent</artifactId>
|
<artifactId>easyconfiguration-parent</artifactId>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<version>1.0.3</version>
|
<version>3.3.1</version>
|
||||||
<modules>
|
<modules>
|
||||||
<module>core</module>
|
<module>core</module>
|
||||||
|
|
||||||
<module>impl/yaml</module>
|
<module>impl/yaml</module>
|
||||||
|
<module>impl/json</module>
|
||||||
<module>platform/spigot</module>
|
<module>impl/sql</module>
|
||||||
<module>platform/bungee</module>
|
<module>demo</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<name>EasyConfiguration</name>
|
<name>EasyConfiguration</name>
|
||||||
@@ -48,8 +47,8 @@
|
|||||||
|
|
||||||
<licenses>
|
<licenses>
|
||||||
<license>
|
<license>
|
||||||
<name>The MIT License</name>
|
<name>GNU LESSER GENERAL PUBLIC LICENSE</name>
|
||||||
<url>https://opensource.org/licenses/MIT</url>
|
<url>https://www.gnu.org/licenses/lgpl-3.0.html</url>
|
||||||
</license>
|
</license>
|
||||||
</licenses>
|
</licenses>
|
||||||
|
|
||||||
@@ -93,7 +92,7 @@
|
|||||||
<downloadUrl>https://github.com/CarmJos/EasyConfiguration/releases</downloadUrl>
|
<downloadUrl>https://github.com/CarmJos/EasyConfiguration/releases</downloadUrl>
|
||||||
<site>
|
<site>
|
||||||
<id>javadoc</id>
|
<id>javadoc</id>
|
||||||
<name>EasySQL JavaDoc (on Github Pages)</name>
|
<name>EasyConfiguration JavaDoc (on GitHub Pages)</name>
|
||||||
<url>https://CarmJos.github.io/EasyConfiguration</url>
|
<url>https://CarmJos.github.io/EasyConfiguration</url>
|
||||||
</site>
|
</site>
|
||||||
</distributionManagement>
|
</distributionManagement>
|
||||||
@@ -167,7 +166,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
<version>3.3.2</version>
|
<version>3.4.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<classifier>javadoc</classifier>
|
<classifier>javadoc</classifier>
|
||||||
<detectJavaApiLink>false</detectJavaApiLink>
|
<detectJavaApiLink>false</detectJavaApiLink>
|
||||||
@@ -206,7 +205,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
<version>3.2.2</version>
|
<version>3.3.0</version>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
<plugin>
|
<plugin>
|
||||||
@@ -226,7 +225,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
<version>3.3.0</version>
|
<version>3.4.1</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<phase>package</phase>
|
<phase>package</phase>
|
||||||
|
|||||||
Reference in New Issue
Block a user