mirror of
https://github.com/CarmJos/EasyConfiguration.git
synced 2026-06-04 18:48:20 +08:00
Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 505b86ec9c | |||
| 374f646f9e | |||
| aa50345329 | |||
| db8b227317 | |||
| 60eed8a14d | |||
| d41630be72 | |||
| 1c3a2b01ea | |||
| 1ede74c692 | |||
| 67456a8aac | |||
| f422900fb5 | |||
| b3e0007eba | |||
| 89c8ec8adf | |||
| e8f49bf8bc | |||
| 8ac980fdbb | |||
| 9f2e4bc0cb | |||
| ae16d131c3 | |||
| bd8470a6e8 | |||
| 6af2d3fef5 | |||
| 00f83002c5 | |||
| 0aa548cbbf | |||
| 9c0ed1c5c2 | |||
| bb0998cbac | |||
| 1eb16f00b6 | |||
| 5ccf63b423 | |||
| f1c0c74574 |
@@ -0,0 +1,16 @@
|
||||
# 欢迎使用 EasyConfiguration !
|
||||
|
||||
这个项目刚刚创建,详细的Javadoc与开发指南还在补充,请给我一点时间~
|
||||
|
||||
|
||||
## 基本定义
|
||||
|
||||
Value: 实际配置的单例值。
|
||||
|
||||
Manifest: 用于描述值基本配置的对象。
|
||||
|
||||
Provider: 用于提供配置文件的接口。
|
||||
|
||||
Wrapper: 用于包装配置文件的接口。
|
||||
|
||||
Initializer: 用于初始化的接口
|
||||
@@ -1,3 +0,0 @@
|
||||
# 欢迎使用 EasyConfiguration !
|
||||
|
||||
这个项目刚刚创建,详细的Javadoc与开发指南还在补充,请给我一点时间~
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
rm -rf docs
|
||||
mkdir -vp docs
|
||||
cp -vrf core/target/apidocs/* docs/
|
||||
cp -vrf .documentation/JAVADOC-README.md docs/README.md
|
||||
cp -vrf .doc/JAVADOC-README.md docs/README.md
|
||||
|
||||
- name: "Generate the Javadoc sitemap"
|
||||
id: sitemap
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
```text
|
||||
____ _____ ____ __ _
|
||||
/ __/__ ____ __ __ / ___/__ ___ / _(_)__ ___ _________ _/ /_(_)__ ___
|
||||
/ _// _ `(_-</ // / / /__/ _ \/ _ \/ _/ / _ `/ // / __/ _ `/ __/ / _ \/ _ \
|
||||
/___/\_,_/___/\_, / \___/\___/_//_/_//_/\_, /\_,_/_/ \_,_/\__/_/\___/_//_/
|
||||
/___/ /___/
|
||||
```
|
||||
|
||||
README LANGUAGES [ [**English**](README.md) | [中文](README_CN.md) ]
|
||||
|
||||
# EasyConfiguration
|
||||
|
||||
@@ -15,56 +10,55 @@
|
||||

|
||||

|
||||
|
||||
轻松(做)配置,简单便捷的通用配置文件加载、读取与更新工具,可自定义配置格式。
|
||||
**Easy _(to make)_ Configurations!**
|
||||
|
||||
## 优势
|
||||
A simple, easy-to-use and universal solution for managing configuration files.
|
||||
Enjoy the ease of use with customizable formats for loading, reading, and updating your configuration files.
|
||||
|
||||
- 基于类的配置文件初始化、加载、获取与更新机制,方便快捷。
|
||||
- 支持复杂配置的手动序列化、反序列化。
|
||||
- 提供多种builder形式,快速构建 `ConfigValue<?>` 对象。
|
||||
- 支持通过注解规定配置对应的路径、注释等信息。
|
||||
## Features & Advantages
|
||||
|
||||
## 开发
|
||||
- Class-based mechanism for initializing, loading, retrieving, and updating configuration files, ensuring convenience and efficiency.
|
||||
- Supports manual serialization and deserialization of complex configurations.
|
||||
- Offers multiple builder forms for rapid construction of `ConfigValue<?>` objects.
|
||||
- Enables specification of configuration paths, comments, and more via annotations.
|
||||
|
||||
详细开发介绍请 [点击这里](.documentation/README.md) , JavaDoc(最新Release) 请 [点击这里](https://CarmJos.github.io/EasyConfiguration) 。
|
||||
## Development
|
||||
|
||||
### 示例代码
|
||||
For a detailed development guide, [CLICK HERE](.doc/README.md).
|
||||
|
||||
您可以 [点击这里](demo/src/main/java/cc/carm/lib/configuration/demo/DatabaseConfiguration.java) 查看部分代码演示,更多演示详见 [开发介绍](.documentation/README.md) 。
|
||||
For the latest JavaDoc release, [CLICK HERE](https://CarmJos.github.io/EasyConfiguration).
|
||||
|
||||
### 依赖方式
|
||||
### Code Samples
|
||||
|
||||
#### Maven 依赖
|
||||
Check out some code demonstrations [HERE](demo/src/main/java/cc/carm/lib/configuration/demo/DatabaseConfiguration.java).
|
||||
|
||||
For more examples, see the [Development Guide](.doc/README.md).
|
||||
|
||||
### Dependencies
|
||||
|
||||
#### Maven Dependency
|
||||
|
||||
<details>
|
||||
<summary>远程库配置</summary>
|
||||
<summary>Remote Repository Configuration</summary>
|
||||
|
||||
```xml
|
||||
|
||||
<project>
|
||||
<repositories>
|
||||
|
||||
<repository>
|
||||
<!--采用Maven中心库,安全稳定,但版本更新需要等待同步-->
|
||||
<!-- Using Maven Central Repository for secure and stable updates, though synchronization might be needed. -->
|
||||
<id>maven</id>
|
||||
<name>Maven Central</name>
|
||||
<url>https://repo1.maven.org/maven2</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<!--采用github依赖库,实时更新,但需要配置 (推荐) -->
|
||||
<!-- Using GitHub dependencies for real-time updates, configuration required (recommended). -->
|
||||
<id>EasyConfiguration</id>
|
||||
<name>GitHub Packages</name>
|
||||
<url>https://maven.pkg.github.com/CarmJos/EasyConfiguration</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<!--采用我的私人依赖库,简单方便,但可能因为变故而无法使用-->
|
||||
<id>carm-repo</id>
|
||||
<name>Carm's Repo</name>
|
||||
<url>https://repo.carm.cc/repository/maven-public/</url>
|
||||
</repository>
|
||||
|
||||
</repositories>
|
||||
</project>
|
||||
```
|
||||
@@ -72,13 +66,12 @@
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>通用原生依赖</summary>
|
||||
<summary>Generic Native Dependency</summary>
|
||||
|
||||
```xml
|
||||
|
||||
<project>
|
||||
<dependencies>
|
||||
<!--基础实现部分,需要自行实现“Provider”与“Wrapper”。-->
|
||||
<!-- Basic implementation part, requiring custom implementation of “Provider” and “Wrapper”. -->
|
||||
<dependency>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easyconfiguration-core</artifactId>
|
||||
@@ -86,7 +79,7 @@
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<!--基于YAML文件的实现版本,可用于全部Java环境。-->
|
||||
<!-- YAML file-based implementation, compatible with all Java environments. -->
|
||||
<dependency>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easyconfiguration-yaml</artifactId>
|
||||
@@ -94,8 +87,7 @@
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<!--基于JSON文件的实现版本,可用于全部Java环境。-->
|
||||
<!--需要注意的是,JSON不支持文件注释。-->
|
||||
<!-- JSON file-based implementation, compatible with all Java environments. Note: JSON does not support file comments. -->
|
||||
<dependency>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easyconfiguration-json</artifactId>
|
||||
@@ -109,42 +101,39 @@
|
||||
|
||||
</details>
|
||||
|
||||
#### Gradle 依赖
|
||||
#### Gradle Dependency
|
||||
|
||||
<details>
|
||||
<summary>远程库配置</summary>
|
||||
<summary>Remote Repository Configuration</summary>
|
||||
|
||||
```groovy
|
||||
repositories {
|
||||
|
||||
// 采用Maven中心库,安全稳定,但版本更新需要等待同步
|
||||
// Using Maven Central Repository for secure and stable updates, though synchronization might be needed.
|
||||
mavenCentral()
|
||||
|
||||
// 采用github依赖库,实时更新,但需要配置 (推荐)
|
||||
// Using GitHub dependencies for real-time updates, configuration required (recommended).
|
||||
maven { url 'https://maven.pkg.github.com/CarmJos/EasyConfiguration' }
|
||||
|
||||
// 采用我的私人依赖库,简单方便,但可能因为变故而无法使用
|
||||
maven { url 'https://repo.carm.cc/repository/maven-public/' }
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>通用原生依赖</summary>
|
||||
<summary>Generic Native Dependency</summary>
|
||||
|
||||
```groovy
|
||||
|
||||
dependencies {
|
||||
|
||||
//基础实现部分,需要自行实现“Provider”与“Wrapper”。
|
||||
// Basic implementation part, requiring custom implementation of “Provider” and “Wrapper”.
|
||||
api "cc.carm.lib:easyconfiguration-core:[LATEST RELEASE]"
|
||||
|
||||
//基于YAML文件的实现版本,可用于全部Java环境。
|
||||
// YAML file-based implementation, compatible with all Java environments.
|
||||
api "cc.carm.lib:easyconfiguration-yaml:[LATEST RELEASE]"
|
||||
|
||||
//基于JSON文件的实现版本,可用于全部Java环境。
|
||||
//需要注意的是,JSON不支持文件注释。
|
||||
// JSON file-based implementation, compatible with all Java environments. Note: JSON does not support file comments.
|
||||
api "cc.carm.lib:easyconfiguration-json:[LATEST RELEASE]"
|
||||
|
||||
}
|
||||
@@ -152,23 +141,26 @@ dependencies {
|
||||
|
||||
</details>
|
||||
|
||||
## 衍生项目
|
||||
## Derived Projects
|
||||
|
||||
### [**MineConfiguration**](https://github.com/CarmJos/MineConfiguration) (by @CarmJos)
|
||||
|
||||
EasyConfiguration for MineCraft!
|
||||
开始在 MineCraft 相关服务器平台上轻松(做)配置吧!
|
||||
Easily manage configurations on MineCraft-related server platforms.
|
||||
|
||||
目前支持 BungeeCord, Bukkit(Spigot) 服务端,后续将支持更多平台。
|
||||
Currently supports BungeeCord, Bukkit (Spigot) servers, with more platforms to be supported soon.
|
||||
|
||||
## 支持与捐赠
|
||||
## Support and Donation
|
||||
|
||||
若您觉得本插件做的不错,您可以通过捐赠支持我!
|
||||
If you appreciate this plugin, consider supporting me with a donation!
|
||||
|
||||
感谢您对开源项目的支持!
|
||||
Thank you for supporting open-source projects!
|
||||
|
||||
<img height=25% width=25% src="https://raw.githubusercontent.com/CarmJos/CarmJos/main/img/donate-code.jpg" alt=""/>
|
||||
Many thanks to Jetbrains for kindly providing a license for us to work on this and other open-source projects.
|
||||
|
||||
## 开源协议
|
||||
[](https://www.jetbrains.com/?from=https://github.com/ArtformGames/ResidenceList)
|
||||
|
||||
本项目源码采用 [GNU LESSER GENERAL PUBLIC LICENSE](https://www.gnu.org/licenses/lgpl-3.0.html) 开源协议。
|
||||
|
||||
## Open Source License
|
||||
|
||||
This project's source code is licensed under the [GNU LESSER GENERAL PUBLIC LICENSE](https://www.gnu.org/licenses/lgpl-3.0.html).
|
||||
|
||||
+180
@@ -0,0 +1,180 @@
|
||||
```text
|
||||
____ _____ ____ __ _
|
||||
/ __/__ ____ __ __ / ___/__ ___ / _(_)__ ___ _________ _/ /_(_)__ ___
|
||||
/ _// _ `(_-</ // / / /__/ _ \/ _ \/ _/ / _ `/ // / __/ _ `/ __/ / _ \/ _ \
|
||||
/___/\_,_/___/\_, / \___/\___/_//_/_//_/\_, /\_,_/_/ \_,_/\__/_/\___/_//_/
|
||||
/___/ /___/
|
||||
```
|
||||
|
||||
README LANGUAGES [ [English](README.md) | [**中文**](README_CN.md) ]
|
||||
|
||||
# EasyConfiguration
|
||||
|
||||
[](https://github.com/CarmJos/EasyConfiguration/releases)
|
||||
[](https://www.gnu.org/licenses/lgpl-3.0.html)
|
||||
[](https://github.com/CarmJos/EasyConfiguration/actions/workflows/maven.yml)
|
||||
[](https://www.codefactor.io/repository/github/carmjos/easyconfiguration)
|
||||

|
||||

|
||||
|
||||
**轻松(做)配置!**
|
||||
|
||||
一款简单便捷的通用配置文件加载、读取与更新工具,可自定义配置的格式。
|
||||
|
||||
## 特性 & 优势
|
||||
|
||||
- 基于类的配置文件初始化、加载、获取与更新机制,方便快捷。
|
||||
- 支持复杂配置的手动序列化、反序列化。
|
||||
- 提供多种builder形式,快速构建 `ConfigValue<?>` 对象。
|
||||
- 支持通过注解规定配置对应的路径、注释等信息。
|
||||
|
||||
## 开发
|
||||
|
||||
详细开发介绍请 [点击这里](.doc/README.md) , JavaDoc(最新Release) 请 [点击这里](https://CarmJos.github.io/EasyConfiguration) 。
|
||||
|
||||
### 示例代码
|
||||
|
||||
您可以 [点击这里](demo/src/main/java/cc/carm/lib/configuration/demo/DatabaseConfiguration.java) 查看部分代码演示,更多演示详见 [开发介绍](.doc/README.md) 。
|
||||
|
||||
### 依赖方式
|
||||
|
||||
#### Maven 依赖
|
||||
|
||||
<details>
|
||||
<summary>远程库配置</summary>
|
||||
|
||||
```xml
|
||||
|
||||
<project>
|
||||
<repositories>
|
||||
|
||||
<repository>
|
||||
<!--采用Maven中心库,安全稳定,但版本更新需要等待同步-->
|
||||
<id>maven</id>
|
||||
<name>Maven Central</name>
|
||||
<url>https://repo1.maven.org/maven2</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<!--采用github依赖库,实时更新,但需要配置 (推荐) -->
|
||||
<id>EasyConfiguration</id>
|
||||
<name>GitHub Packages</name>
|
||||
<url>https://maven.pkg.github.com/CarmJos/EasyConfiguration</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<!--采用我的私人依赖库,简单方便,但可能因为变故而无法使用-->
|
||||
<id>carm-repo</id>
|
||||
<name>Carm's Repo</name>
|
||||
<url>https://repo.carm.cc/repository/maven-public/</url>
|
||||
</repository>
|
||||
|
||||
</repositories>
|
||||
</project>
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>通用原生依赖</summary>
|
||||
|
||||
```xml
|
||||
|
||||
<project>
|
||||
<dependencies>
|
||||
<!--基础实现部分,需要自行实现“Provider”与“Wrapper”。-->
|
||||
<dependency>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easyconfiguration-core</artifactId>
|
||||
<version>[LATEST RELEASE]</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<!--基于YAML文件的实现版本,可用于全部Java环境。-->
|
||||
<dependency>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easyconfiguration-yaml</artifactId>
|
||||
<version>[LATEST RELEASE]</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<!--基于JSON文件的实现版本,可用于全部Java环境。-->
|
||||
<!--需要注意的是,JSON不支持文件注释。-->
|
||||
<dependency>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easyconfiguration-json</artifactId>
|
||||
<version>[LATEST RELEASE]</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
#### Gradle 依赖
|
||||
|
||||
<details>
|
||||
<summary>远程库配置</summary>
|
||||
|
||||
```groovy
|
||||
repositories {
|
||||
|
||||
// 采用Maven中心库,安全稳定,但版本更新需要等待同步
|
||||
mavenCentral()
|
||||
|
||||
// 采用github依赖库,实时更新,但需要配置 (推荐)
|
||||
maven { url 'https://maven.pkg.github.com/CarmJos/EasyConfiguration' }
|
||||
|
||||
// 采用我的私人依赖库,简单方便,但可能因为变故而无法使用
|
||||
maven { url 'https://repo.carm.cc/repository/maven-public/' }
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>通用原生依赖</summary>
|
||||
|
||||
```groovy
|
||||
|
||||
dependencies {
|
||||
|
||||
//基础实现部分,需要自行实现“Provider”与“Wrapper”。
|
||||
api "cc.carm.lib:easyconfiguration-core:[LATEST RELEASE]"
|
||||
|
||||
//基于YAML文件的实现版本,可用于全部Java环境。
|
||||
api "cc.carm.lib:easyconfiguration-yaml:[LATEST RELEASE]"
|
||||
|
||||
//基于JSON文件的实现版本,可用于全部Java环境。
|
||||
//需要注意的是,JSON不支持文件注释。
|
||||
api "cc.carm.lib:easyconfiguration-json:[LATEST RELEASE]"
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## 衍生项目
|
||||
|
||||
### [**MineConfiguration**](https://github.com/CarmJos/MineConfiguration) (by @CarmJos )
|
||||
|
||||
EasyConfiguration for MineCraft!
|
||||
开始在 MineCraft 相关服务器平台上轻松(做)配置吧!
|
||||
|
||||
目前支持 BungeeCord, Bukkit(Spigot) 服务端,后续将支持更多平台。
|
||||
|
||||
## 支持与捐赠
|
||||
|
||||
若您觉得本插件做的不错,您可以通过捐赠支持我!
|
||||
|
||||
感谢您对开源项目的支持!
|
||||
|
||||
万分感谢 Jetbrains 为我们提供了从事此项目和其他开源项目的许可!
|
||||
|
||||
[](https://www.jetbrains.com/?from=https://github.com/ArtformGames/ResidenceList)
|
||||
|
||||
## 开源协议
|
||||
|
||||
本项目源码采用 [GNU LESSER GENERAL PUBLIC LICENSE](https://www.gnu.org/licenses/lgpl-3.0.html) 开源协议。
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<version>3.8.0</version>
|
||||
<version>3.9.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<properties>
|
||||
|
||||
@@ -14,7 +14,7 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* 配置文件类初始化方法
|
||||
* 用于初始化 {@link ConfigurationRoot} 中的每个 {@link ConfigValue} 对象
|
||||
* 用于初始化 {@link Configuration} 中的每个 {@link ConfigValue} 对象
|
||||
*
|
||||
* @param <T> {@link ConfigurationProvider} 配置文件的数据来源
|
||||
* @author CarmJos
|
||||
@@ -30,21 +30,21 @@ public class ConfigInitializer<T extends ConfigurationProvider<?>> {
|
||||
/**
|
||||
* 初始化指定类以及其子类的所有 {@link ConfigValue} 对象。
|
||||
*
|
||||
* @param clazz 配置文件类,须继承于 {@link ConfigurationRoot} 。
|
||||
* @param clazz 配置文件类,须继承于 {@link Configuration} 。
|
||||
* @param saveDefaults 是否写入默认值(默认为 true)。
|
||||
*/
|
||||
public void initialize(@NotNull Class<? extends ConfigurationRoot> clazz, boolean saveDefaults) {
|
||||
public void initialize(@NotNull Class<? extends Configuration> clazz, boolean saveDefaults) {
|
||||
initialize(clazz, saveDefaults, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化指定类的所有 {@link ConfigValue} 对象。
|
||||
*
|
||||
* @param clazz 配置文件类,须继承于 {@link ConfigurationRoot} 。
|
||||
* @param clazz 配置文件类,须继承于 {@link Configuration} 。
|
||||
* @param saveDefaults 是否写入默认值(默认为 true)。
|
||||
* @param loadSubClasses 是否加载内部子类(默认为 true)。
|
||||
*/
|
||||
public void initialize(@NotNull Class<? extends ConfigurationRoot> clazz,
|
||||
public void initialize(@NotNull Class<? extends Configuration> clazz,
|
||||
boolean saveDefaults, boolean loadSubClasses) {
|
||||
initializeStaticClass(
|
||||
clazz, null, null,
|
||||
@@ -61,21 +61,21 @@ public class ConfigInitializer<T extends ConfigurationProvider<?>> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化指定实例的所有 {@link ConfigValue} 与内部 {@link ConfigurationRoot} 对象。
|
||||
* 初始化指定实例的所有 {@link ConfigValue} 与内部 {@link Configuration} 对象。
|
||||
*
|
||||
* @param config 配置文件实例类,须实现 {@link ConfigurationRoot} 。
|
||||
* @param config 配置文件实例类,须实现 {@link Configuration} 。
|
||||
*/
|
||||
public void initialize(@NotNull ConfigurationRoot config) {
|
||||
public void initialize(@NotNull Configuration config) {
|
||||
initialize(config, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化指定实例的所有 {@link ConfigValue} 与内部 {@link ConfigurationRoot} 对象。
|
||||
* 初始化指定实例的所有 {@link ConfigValue} 与内部 {@link Configuration} 对象。
|
||||
*
|
||||
* @param config 配置文件实例类,须实现 {@link ConfigurationRoot} 。
|
||||
* @param config 配置文件实例类,须实现 {@link Configuration} 。
|
||||
* @param saveDefaults 是否写入默认值(默认为 true)。
|
||||
*/
|
||||
public void initialize(@NotNull ConfigurationRoot config, boolean saveDefaults) {
|
||||
public void initialize(@NotNull Configuration config, boolean saveDefaults) {
|
||||
initializeInstance(
|
||||
config, null, null,
|
||||
null, null, null,
|
||||
@@ -92,7 +92,7 @@ public class ConfigInitializer<T extends ConfigurationProvider<?>> {
|
||||
|
||||
|
||||
// 针对实例类的初始化方法
|
||||
private void initializeInstance(@NotNull ConfigurationRoot root,
|
||||
private void initializeInstance(@NotNull Configuration root,
|
||||
@Nullable String parentPath, @Nullable String fieldName,
|
||||
@Nullable ConfigPath fieldPath,
|
||||
@Nullable HeaderComment fieldHeaderComments,
|
||||
@@ -114,7 +114,7 @@ public class ConfigInitializer<T extends ConfigurationProvider<?>> {
|
||||
@Nullable HeaderComment fieldHeaderComments,
|
||||
@Nullable InlineComment fieldInlineComments,
|
||||
boolean saveDefaults, boolean loadSubClasses) {
|
||||
if (!ConfigurationRoot.class.isAssignableFrom(clazz)) return; // 只解析继承了 ConfigurationRoot 的类
|
||||
if (!Configuration.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));
|
||||
@@ -147,10 +147,10 @@ public class ConfigInitializer<T extends ConfigurationProvider<?>> {
|
||||
field.getAnnotation(InlineComment.class),
|
||||
saveDefaults
|
||||
);
|
||||
} else if (source instanceof ConfigurationRoot && object instanceof ConfigurationRoot) {
|
||||
} else if (source instanceof Configuration && object instanceof Configuration) {
|
||||
// 当且仅当 源字段与字段 均为ConfigurationRoot实例时,才对目标字段进行下一步初始化加载。
|
||||
initializeInstance(
|
||||
(ConfigurationRoot) object, parent, field.getName(),
|
||||
(Configuration) object, parent, field.getName(),
|
||||
field.getAnnotation(ConfigPath.class),
|
||||
field.getAnnotation(HeaderComment.class),
|
||||
field.getAnnotation(InlineComment.class),
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package cc.carm.lib.configuration.core;
|
||||
|
||||
/**
|
||||
* The root interface of the configuration file interfaces,
|
||||
* which is used to label and record the configuration information.
|
||||
*/
|
||||
public interface Configuration {
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
package cc.carm.lib.configuration.core;
|
||||
|
||||
/**
|
||||
* 配置文件类的根节点,用于标注该类用于记录配置文件中的配置信息。
|
||||
* The root node of the configuration file class,
|
||||
* which is used to label and record the configuration information.
|
||||
*/
|
||||
public abstract class ConfigurationRoot {
|
||||
public abstract class ConfigurationRoot implements Configuration {
|
||||
}
|
||||
|
||||
@@ -50,22 +50,21 @@ public interface ConfigValueParser<T, R> {
|
||||
@Contract(pure = true)
|
||||
static <V> @NotNull ConfigValueParser<Object, V> castObject(Class<V> valueClass) {
|
||||
return (input, defaultValue) -> {
|
||||
|
||||
if (Number.class.isAssignableFrom(valueClass)) {
|
||||
if (Long.class.isAssignableFrom(valueClass)) {
|
||||
if (Long.class.isAssignableFrom(valueClass) || long.class.isAssignableFrom(valueClass)) {
|
||||
input = longValue().parse(input, (Long) defaultValue);
|
||||
} else if (Integer.class.isAssignableFrom(valueClass)) {
|
||||
} else if (Integer.class.isAssignableFrom(valueClass) || int.class.isAssignableFrom(valueClass)) {
|
||||
input = intValue().parse(input, (Integer) defaultValue);
|
||||
} else if (Float.class.isAssignableFrom(valueClass)) {
|
||||
} else if (Float.class.isAssignableFrom(valueClass) || float.class.isAssignableFrom(valueClass)) {
|
||||
input = floatValue().parse(input, (Float) defaultValue);
|
||||
} else if (Double.class.isAssignableFrom(valueClass)) {
|
||||
} else if (Double.class.isAssignableFrom(valueClass) || double.class.isAssignableFrom(valueClass)) {
|
||||
input = doubleValue().parse(input, (Double) defaultValue);
|
||||
} else if (Byte.class.isAssignableFrom(valueClass)) {
|
||||
} else if (Byte.class.isAssignableFrom(valueClass) || byte.class.isAssignableFrom(valueClass)) {
|
||||
input = byteValue().parse(input, (Byte) defaultValue);
|
||||
} else if (Short.class.isAssignableFrom(valueClass)) {
|
||||
} else if (Short.class.isAssignableFrom(valueClass) || short.class.isAssignableFrom(valueClass)) {
|
||||
input = shortValue().parse(input, (Short) defaultValue);
|
||||
}
|
||||
} else if (Boolean.class.isAssignableFrom(valueClass)) {
|
||||
} else if (Boolean.class.isAssignableFrom(valueClass) || boolean.class.isAssignableFrom(valueClass)) {
|
||||
input = booleanValue().parse(input, (Boolean) defaultValue);
|
||||
} else if (Enum.class.isAssignableFrom(valueClass) && input instanceof String) {
|
||||
String enumName = (String) input;
|
||||
|
||||
+14
-13
@@ -1,7 +1,8 @@
|
||||
package cc.carm.lib.configuration.core.source;
|
||||
|
||||
import cc.carm.lib.configuration.core.ConfigInitializer;
|
||||
import cc.carm.lib.configuration.core.ConfigurationRoot;
|
||||
import cc.carm.lib.configuration.core.Configuration;
|
||||
import cc.carm.lib.configuration.core.Configuration;
|
||||
import cc.carm.lib.configuration.core.value.ConfigValue;
|
||||
import cc.carm.lib.configuration.core.value.impl.CachedConfigValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -101,49 +102,49 @@ public abstract class ConfigurationProvider<W extends ConfigurationWrapper<?>> {
|
||||
/**
|
||||
* 初始化指定类以及其子类的所有 {@link ConfigValue} 对象。
|
||||
*
|
||||
* @param configClazz 配置文件类,须继承于 {@link ConfigurationRoot} 。
|
||||
* @param configClazz 配置文件类,须继承于 {@link Configuration} 。
|
||||
*/
|
||||
public void initialize(Class<? extends ConfigurationRoot> configClazz) {
|
||||
public void initialize(Class<? extends Configuration> configClazz) {
|
||||
initialize(configClazz, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化指定类以及其子类的所有 {@link ConfigValue} 对象。
|
||||
*
|
||||
* @param configClazz 配置文件类,须继承于 {@link ConfigurationRoot} 。
|
||||
* @param configClazz 配置文件类,须继承于 {@link Configuration} 。
|
||||
* @param saveDefaults 是否写入默认值(默认为 true)。
|
||||
*/
|
||||
public void initialize(Class<? extends ConfigurationRoot> configClazz, boolean saveDefaults) {
|
||||
public void initialize(Class<? extends Configuration> configClazz, boolean saveDefaults) {
|
||||
this.getInitializer().initialize(configClazz, saveDefaults);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化指定类的所有 {@link ConfigValue} 对象。
|
||||
*
|
||||
* @param configClazz 配置文件类,须继承于 {@link ConfigurationRoot} 。
|
||||
* @param configClazz 配置文件类,须继承于 {@link Configuration} 。
|
||||
* @param saveDefaults 是否写入默认值(默认为 true)。
|
||||
* @param loadSubClasses 是否加载内部子类(默认为 true)。
|
||||
*/
|
||||
public void initialize(Class<? extends ConfigurationRoot> configClazz, boolean saveDefaults, boolean loadSubClasses) {
|
||||
public void initialize(Class<? extends Configuration> configClazz, boolean saveDefaults, boolean loadSubClasses) {
|
||||
this.getInitializer().initialize(configClazz, saveDefaults, loadSubClasses);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化指定实例的所有 {@link ConfigValue} 与内部 {@link ConfigurationRoot} 对象。
|
||||
* 初始化指定实例的所有 {@link ConfigValue} 与内部 {@link Configuration} 对象。
|
||||
*
|
||||
* @param config 配置文件实例类,须实现 {@link ConfigurationRoot} 。
|
||||
* @param config 配置文件实例类,须实现 {@link Configuration} 。
|
||||
*/
|
||||
public void initialize(@NotNull ConfigurationRoot config) {
|
||||
public void initialize(@NotNull Configuration config) {
|
||||
this.getInitializer().initialize(config, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化指定实例的所有 {@link ConfigValue} 与内部 {@link ConfigurationRoot} 对象。
|
||||
* 初始化指定实例的所有 {@link ConfigValue} 与内部 {@link Configuration} 对象。
|
||||
*
|
||||
* @param config 配置文件实例类,须实现 {@link ConfigurationRoot} 。
|
||||
* @param config 配置文件实例类,须实现 {@link Configuration} 。
|
||||
* @param saveDefaults 是否写入默认值(默认为 true)。
|
||||
*/
|
||||
public void initialize(@NotNull ConfigurationRoot config, boolean saveDefaults) {
|
||||
public void initialize(@NotNull Configuration config, boolean saveDefaults) {
|
||||
this.getInitializer().initialize(config, saveDefaults);
|
||||
}
|
||||
|
||||
|
||||
@@ -137,39 +137,43 @@ interface ConfigurationReader {
|
||||
return getWrapper().get(path, def, String.class);
|
||||
}
|
||||
|
||||
default <V> @NotNull List<V> getList(@NotNull String path, @NotNull ConfigValueParser<Object, V> parser) {
|
||||
return parseList(getWrapper().getList(path), parser);
|
||||
}
|
||||
|
||||
@Unmodifiable
|
||||
default @NotNull List<String> getStringList(@NotNull String path) {
|
||||
return parseList(getWrapper().getList(path), ConfigValueParser.castToString());
|
||||
return getList(path, ConfigValueParser.castToString());
|
||||
}
|
||||
|
||||
@Unmodifiable
|
||||
default @NotNull List<Integer> getIntegerList(@NotNull String path) {
|
||||
return parseList(getWrapper().getList(path), ConfigValueParser.intValue());
|
||||
return getList(path, ConfigValueParser.intValue());
|
||||
}
|
||||
|
||||
@Unmodifiable
|
||||
default @NotNull List<Long> getLongList(@NotNull String path) {
|
||||
return parseList(getWrapper().getList(path), ConfigValueParser.longValue());
|
||||
return getList(path, ConfigValueParser.longValue());
|
||||
}
|
||||
|
||||
@Unmodifiable
|
||||
default @NotNull List<Double> getDoubleList(@NotNull String path) {
|
||||
return parseList(getWrapper().getList(path), ConfigValueParser.doubleValue());
|
||||
return getList(path, ConfigValueParser.doubleValue());
|
||||
}
|
||||
|
||||
@Unmodifiable
|
||||
default @NotNull List<Float> getFloatList(@NotNull String path) {
|
||||
return parseList(getWrapper().getList(path), ConfigValueParser.floatValue());
|
||||
return getList(path, ConfigValueParser.floatValue());
|
||||
}
|
||||
|
||||
@Unmodifiable
|
||||
default @NotNull List<Byte> getByteList(@NotNull String path) {
|
||||
return parseList(getWrapper().getList(path), ConfigValueParser.byteValue());
|
||||
return getList(path, ConfigValueParser.byteValue());
|
||||
}
|
||||
|
||||
@Unmodifiable
|
||||
default @NotNull List<Character> getCharList(@NotNull String path) {
|
||||
return parseList(getWrapper().getList(path), ConfigValueParser.castObject(Character.class));
|
||||
return getList(path, ConfigValueParser.castObject(Character.class));
|
||||
}
|
||||
|
||||
@Unmodifiable
|
||||
|
||||
@@ -43,8 +43,7 @@ public class ConfiguredList<V> extends CachedConfigValue<List<V>> implements Lis
|
||||
@Override
|
||||
public @NotNull List<V> get() {
|
||||
if (!isExpired()) return getCachedOrDefault(new ArrayList<>());
|
||||
|
||||
// 已过时的数据,需要重新解析一次。
|
||||
// Data that is outdated and needs to be parsed again.
|
||||
List<V> list = new ArrayList<>();
|
||||
List<?> data = getConfiguration().contains(getConfigPath()) ?
|
||||
getConfiguration().getList(getConfigPath()) : null;
|
||||
|
||||
+21
-3
@@ -31,37 +31,55 @@ public class ConfiguredSection<V> extends CachedConfigValue<V> {
|
||||
this.serializer = serializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Value's type class
|
||||
*/
|
||||
public @NotNull Class<V> getValueClass() {
|
||||
return valueClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Value's parser, cast value from section.
|
||||
*/
|
||||
public @NotNull ConfigValueParser<ConfigurationWrapper<?>, V> getParser() {
|
||||
return parser;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Value's serializer, serialize value to section.
|
||||
*/
|
||||
public @NotNull ConfigDataFunction<V, ? extends Map<String, Object>> getSerializer() {
|
||||
return serializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Get the value that parsed from the configuration section.
|
||||
*/
|
||||
@Override
|
||||
public @Nullable V get() {
|
||||
if (!isExpired()) return getCachedOrDefault();
|
||||
// 已过时的数据,需要重新解析一次。
|
||||
// Data that is outdated and needs to be parsed again.
|
||||
|
||||
ConfigurationWrapper<?> section = getConfiguration().getConfigurationSection(getConfigPath());
|
||||
if (section == null) return getDefaultValue();
|
||||
|
||||
try {
|
||||
// 若未出现错误,则直接更新缓存并返回。
|
||||
// If there are no errors, update the cache and return.
|
||||
return updateCache(this.parser.parse(section, this.defaultValue));
|
||||
} catch (Exception e) {
|
||||
// 出现了解析错误,提示并返回默认值。
|
||||
// There was a parsing error, prompted and returned the default value.
|
||||
e.printStackTrace();
|
||||
return getDefaultValue();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the specified value to update the configuration section.
|
||||
* Will use {@link #getSerializer()} to serialize the value to section.
|
||||
*
|
||||
* @param value The value that needs to be set in the configuration.
|
||||
*/
|
||||
@Override
|
||||
public void set(V value) {
|
||||
updateCache(value);
|
||||
|
||||
@@ -14,6 +14,11 @@ public class ConfiguredValue<V> extends CachedConfigValue<V> {
|
||||
return builder().asValue(valueClass);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <V> ConfiguredValue<V> of(@NotNull V defaultValue) {
|
||||
return of((Class<V>) defaultValue.getClass(), defaultValue);
|
||||
}
|
||||
|
||||
public static <V> ConfiguredValue<V> of(Class<V> valueClass) {
|
||||
return of(valueClass, null);
|
||||
}
|
||||
@@ -36,32 +41,51 @@ public class ConfiguredValue<V> extends CachedConfigValue<V> {
|
||||
this.serializer = serializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Value's type class
|
||||
*/
|
||||
public @NotNull Class<V> getValueClass() {
|
||||
return valueClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Value's parser, cast value from base object.
|
||||
*/
|
||||
public @NotNull ConfigValueParser<Object, V> getParser() {
|
||||
return parser;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Value's serializer, serialize value to base object.
|
||||
*/
|
||||
public @NotNull ConfigDataFunction<V, Object> getSerializer() {
|
||||
return serializer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get() {
|
||||
if (!isExpired()) return getCachedOrDefault();
|
||||
// 已过时的数据,需要重新解析一次。
|
||||
// Data that is outdated and needs to be parsed again.
|
||||
|
||||
Object value = getValue();
|
||||
if (value == null) return getDefaultValue(); // 获取的值不存在,直接使用默认值。
|
||||
try {
|
||||
// 若未出现错误,则直接更新缓存并返回。
|
||||
// If there are no errors, update the cache and return.
|
||||
return updateCache(this.parser.parse(value, this.defaultValue));
|
||||
} catch (Exception e) {
|
||||
// 出现了解析错误,提示并返回默认值。
|
||||
// There was a parsing error, prompted and returned the default value.
|
||||
e.printStackTrace();
|
||||
return getDefaultValue();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of the configuration path.
|
||||
* Will use {@link #getSerializer()} to serialize the value.
|
||||
*
|
||||
* @param value The value to be set
|
||||
*/
|
||||
@Override
|
||||
public void set(V value) {
|
||||
updateCache(value);
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<version>3.8.0</version>
|
||||
<version>3.9.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<properties>
|
||||
|
||||
+9
-10
@@ -1,6 +1,7 @@
|
||||
package cc.carm.lib.configuration.demo.tests.conf;
|
||||
|
||||
import cc.carm.lib.configuration.core.ConfigInitializer;
|
||||
import cc.carm.lib.configuration.core.Configuration;
|
||||
import cc.carm.lib.configuration.core.ConfigurationRoot;
|
||||
import cc.carm.lib.configuration.core.annotation.ConfigPath;
|
||||
import cc.carm.lib.configuration.core.annotation.HeaderComment;
|
||||
@@ -18,35 +19,33 @@ import java.util.UUID;
|
||||
|
||||
|
||||
@HeaderComment({"此处内容将显示在配置文件的最上方"})
|
||||
public class DemoConfiguration extends ConfigurationRoot {
|
||||
public interface DemoConfiguration extends Configuration {
|
||||
|
||||
@ConfigPath(root = true)
|
||||
protected static final ConfigValue<Double> VERSION = ConfiguredValue.of(Double.class, 1.0D);
|
||||
ConfigValue<Double> VERSION = ConfiguredValue.of(Double.class, 1.0D);
|
||||
|
||||
@ConfigPath(root = true)
|
||||
public static final ConfigValue<Long> TEST_NUMBER = ConfiguredValue.of(Long.class, 1000000L);
|
||||
ConfigValue<Long> TEST_NUMBER = ConfiguredValue.of(1000000L);
|
||||
|
||||
public static final ConfigValue<ChronoUnit> TEST_ENUM = ConfiguredValue.of(ChronoUnit.class, ChronoUnit.DAYS);
|
||||
ConfigValue<ChronoUnit> TEST_ENUM = ConfiguredValue.of(ChronoUnit.class, ChronoUnit.DAYS);
|
||||
|
||||
// 支持通过 Class<?> 变量标注子配置,一并注册。
|
||||
// 注意: 若对应类也有注解,则优先使用类的注解。
|
||||
@ConfigPath("other-class-config") //支持通过注解修改子配置的主路径,若不修改则以变量名自动生成。
|
||||
@HeaderComment({"", "Something..."}) // 支持给子路径直接打注释
|
||||
@InlineComment("InlineComments for class path")
|
||||
public static final Class<?> OTHER = OtherConfiguration.class;
|
||||
Class<?> OTHER = OtherConfiguration.class;
|
||||
|
||||
@ConfigPath("user") // 通过注解规定配置文件中的路径,若不进行注解则以变量名自动生成。
|
||||
@HeaderComment({"Section类型数据测试"}) // 通过注解给配置添加注释。
|
||||
@InlineComment("Section数据也支持InlineComment注释")
|
||||
public static final ConfigValue<TestModel> MODEL_TEST = ConfiguredSection
|
||||
.builderOf(TestModel.class)
|
||||
ConfigValue<TestModel> MODEL_TEST = ConfiguredSection.builderOf(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 ConfiguredMap<Integer, UUID> USERS = ConfiguredMap
|
||||
.builderOf(Integer.class, UUID.class)
|
||||
ConfiguredMap<Integer, UUID> USERS = ConfiguredMap.builderOf(Integer.class, UUID.class)
|
||||
.asLinkedMap().fromString()
|
||||
.parseKey(Integer::parseInt)
|
||||
.parseValue(v -> Objects.requireNonNull(UUID.fromString(v)))
|
||||
@@ -57,7 +56,7 @@ public class DemoConfiguration extends ConfigurationRoot {
|
||||
* 支持内部类的直接注册。
|
||||
* 注意,需要使用 {@link ConfigInitializer#initialize(Class, boolean, boolean)} 方法,并设定第三个参数为 true。
|
||||
*/
|
||||
public static class Sub extends ConfigurationRoot {
|
||||
class Sub extends ConfigurationRoot {
|
||||
|
||||
@ConfigPath(value = "uuid-value", root = true)
|
||||
@InlineComment("This is an inline comment")
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<version>3.8.0</version>
|
||||
<version>3.9.0</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<properties>
|
||||
@@ -36,7 +36,7 @@
|
||||
<dependency>
|
||||
<groupId>com.typesafe</groupId>
|
||||
<artifactId>config</artifactId>
|
||||
<version>1.4.2</version>
|
||||
<version>1.4.3</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
package online.flowerinsnow.test.easyconfiguration;
|
||||
|
||||
import cc.carm.lib.configuration.EasyConfiguration;
|
||||
//import cc.carm.lib.configuration.demo.DatabaseConfiguration;
|
||||
//import cc.carm.lib.configuration.demo.tests.conf.DemoConfiguration;
|
||||
import cc.carm.lib.configuration.hocon.HOCONFileConfigProvider;
|
||||
import online.flowerinsnow.test.easyconfiguration.config.Config;
|
||||
import online.flowerinsnow.test.easyconfiguration.config.SimpleConfig;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
@@ -13,9 +11,15 @@ public class HOCONTest {
|
||||
@Test
|
||||
public void onTest() {
|
||||
HOCONFileConfigProvider provider = EasyConfiguration.from(new File("target/hocon.conf"));
|
||||
provider.initialize(Config.class);
|
||||
provider.initialize(SimpleConfig.class);
|
||||
// provider.initialize(DatabaseConfiguration.class);
|
||||
|
||||
System.out.println(SimpleConfig.TEST_INT.getNotNull());
|
||||
SimpleConfig.TEST_INT.set((int) (Math.random() * 100 * 5));
|
||||
System.out.println(SimpleConfig.TEST_INT.getNotNull());
|
||||
|
||||
try {
|
||||
provider.save();
|
||||
provider.reload();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
||||
+10
-7
@@ -1,25 +1,28 @@
|
||||
package online.flowerinsnow.test.easyconfiguration.config;
|
||||
|
||||
import cc.carm.lib.configuration.core.ConfigurationRoot;
|
||||
import cc.carm.lib.configuration.core.Configuration;
|
||||
import cc.carm.lib.configuration.core.annotation.HeaderComment;
|
||||
import cc.carm.lib.configuration.core.value.type.ConfiguredList;
|
||||
import cc.carm.lib.configuration.core.value.type.ConfiguredValue;
|
||||
|
||||
public class Config extends ConfigurationRoot {
|
||||
public interface SimpleConfig extends Configuration {
|
||||
@HeaderComment("测试字段 int")
|
||||
public static final ConfiguredValue<Integer> TEST_INT = ConfiguredValue.of(Integer.class, 15);
|
||||
ConfiguredValue<Integer> TEST_INT = ConfiguredValue.of(Integer.class, 15);
|
||||
|
||||
@HeaderComment("测试字段 List<String>")
|
||||
public static final ConfiguredList<String> TEST_LIST_STRING = ConfiguredList.of(String.class, "li", "li", "li1");
|
||||
ConfiguredList<String> TEST_LIST_STRING = ConfiguredList.of(String.class, "li", "li", "li1");
|
||||
|
||||
@HeaderComment("测试对象")
|
||||
public static class TestObject extends ConfigurationRoot {
|
||||
interface TestObject extends Configuration {
|
||||
|
||||
@HeaderComment("测试字段 Boolean")
|
||||
public static final ConfiguredValue<Boolean> TEST_BOOLEAN = ConfiguredValue.of(Boolean.class, true);
|
||||
ConfiguredValue<Boolean> TEST_BOOLEAN = ConfiguredValue.of(Boolean.class, true);
|
||||
|
||||
@HeaderComment("inner")
|
||||
public static class InnerObject extends ConfigurationRoot {
|
||||
interface InnerObject extends Configuration {
|
||||
@HeaderComment("测试字段")
|
||||
public static final ConfiguredValue<Boolean> TEST_BOOLEAN_1 = ConfiguredValue.of(Boolean.class, true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<version>3.8.0</version>
|
||||
<version>3.9.0</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
/**
|
||||
@@ -37,6 +38,16 @@ public class JSONConfigProvider extends FileConfigProvider<JSONConfigWrapper> {
|
||||
}
|
||||
|
||||
public void initializeConfig() {
|
||||
onReload();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull JSONConfigWrapper getConfiguration() {
|
||||
return this.configuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onReload() {
|
||||
LinkedHashMap<?, ?> map = null;
|
||||
|
||||
try (FileInputStream is = new FileInputStream(file)) {
|
||||
@@ -50,17 +61,6 @@ public class JSONConfigProvider extends FileConfigProvider<JSONConfigWrapper> {
|
||||
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;
|
||||
@@ -68,7 +68,7 @@ public class JSONConfigProvider extends FileConfigProvider<JSONConfigWrapper> {
|
||||
|
||||
@Override
|
||||
public void save() throws Exception {
|
||||
try (Writer writer = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)) {
|
||||
try (Writer writer = new OutputStreamWriter(Files.newOutputStream(file.toPath()), StandardCharsets.UTF_8)) {
|
||||
gson.toJson(configuration.data, writer);
|
||||
}
|
||||
}
|
||||
|
||||
+50
-2
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<version>3.8.0</version>
|
||||
<version>3.9.0</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@@ -15,7 +15,7 @@
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
||||
|
||||
<maven.deploy.skip>true</maven.deploy.skip>
|
||||
<log4j.version>2.22.0</log4j.version>
|
||||
</properties>
|
||||
<artifactId>easyconfiguration-sql</artifactId>
|
||||
|
||||
@@ -28,6 +28,54 @@
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.10.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easysql-beecp</artifactId>
|
||||
<version>0.4.7</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>2.1.210</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>${project.parent.groupId}</groupId>
|
||||
<artifactId>easyconfiguration-demo</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-api</artifactId>
|
||||
<version>${log4j.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-core</artifactId>
|
||||
<version>${log4j.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-slf4j-impl</artifactId>
|
||||
<version>${log4j.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -1,8 +1,26 @@
|
||||
package cc.carm.lib.configuration;
|
||||
|
||||
import cc.carm.lib.configuration.sql.SQLConfigProvider;
|
||||
import cc.carm.lib.easysql.api.SQLManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class EasyConfiguration {
|
||||
|
||||
private EasyConfiguration() {
|
||||
}
|
||||
|
||||
public static SQLConfigProvider from(@NotNull SQLManager sqlManager, @NotNull String tableName, @NotNull String namespace) {
|
||||
SQLConfigProvider provider = new SQLConfigProvider(sqlManager, tableName, namespace);
|
||||
try {
|
||||
provider.initializeConfig();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return provider;
|
||||
}
|
||||
|
||||
public static SQLConfigProvider from(@NotNull SQLManager sqlManager, @NotNull String tableName) {
|
||||
return from(sqlManager, tableName, "base");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,36 +3,184 @@ 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 cc.carm.lib.easysql.api.SQLManager;
|
||||
import cc.carm.lib.easysql.api.SQLQuery;
|
||||
import cc.carm.lib.easysql.api.SQLTable;
|
||||
import cc.carm.lib.easysql.api.enums.IndexType;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class SQLConfigProvider extends ConfigurationProvider<SQLSectionWrapper> {
|
||||
import java.sql.ResultSet;
|
||||
import java.util.*;
|
||||
|
||||
public class SQLConfigProvider extends ConfigurationProvider<SQLConfigWrapper> {
|
||||
|
||||
@Override
|
||||
public @NotNull SQLSectionWrapper getConfiguration() {
|
||||
return null;
|
||||
public static Gson GSON = new GsonBuilder().serializeNulls().disableHtmlEscaping().setPrettyPrinting().create();
|
||||
|
||||
protected final @NotNull SQLManager sqlManager;
|
||||
protected final @NotNull SQLTable table;
|
||||
protected final @NotNull String namespace;
|
||||
|
||||
protected ConfigInitializer<SQLConfigProvider> initializer;
|
||||
protected ConfigurationComments comments = new ConfigurationComments();
|
||||
protected SQLConfigWrapper rootConfiguration;
|
||||
|
||||
protected final @NotNull Set<String> updated = new HashSet<>();
|
||||
|
||||
public SQLConfigProvider(@NotNull SQLManager sqlManager, @NotNull String tableName, @NotNull String namespace) {
|
||||
this.sqlManager = sqlManager;
|
||||
this.table = SQLTable.of(tableName, builder -> {
|
||||
|
||||
builder.addColumn("namespace", "VARCHAR(32) NOT NULL");
|
||||
builder.addColumn("path", "VARCHAR(96) NOT NULL");
|
||||
|
||||
builder.addColumn("type", "TINYINT NOT NULL DEFAULT 0");
|
||||
builder.addColumn("value", "TEXT");
|
||||
|
||||
builder.addColumn("inline_comment", "TEXT");
|
||||
builder.addColumn("header_comments", "MEDIUMTEXT");
|
||||
|
||||
builder.addColumn("create_time", "TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP");
|
||||
builder.addColumn("update_time", "TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP");
|
||||
|
||||
builder.setIndex(
|
||||
IndexType.PRIMARY_KEY, "pk_" + tableName.toLowerCase(),
|
||||
"namespace", "path"
|
||||
);
|
||||
builder.setTableSettings("ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
|
||||
});
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() throws Exception {
|
||||
public @NotNull SQLConfigWrapper getConfiguration() {
|
||||
return rootConfiguration;
|
||||
}
|
||||
|
||||
public void initializeConfig() throws Exception {
|
||||
this.table.create(this.sqlManager);
|
||||
this.initializer = new ConfigInitializer<>(this);
|
||||
onReload();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onReload() throws Exception {
|
||||
this.comments = new ConfigurationComments();
|
||||
LinkedHashMap<String, Object> values = new LinkedHashMap<>();
|
||||
|
||||
try (SQLQuery query = this.table.createQuery()
|
||||
.addCondition("namespace", namespace)
|
||||
.build().execute()) {
|
||||
ResultSet rs = query.getResultSet();
|
||||
while (rs.next()) {
|
||||
String path = rs.getString("path");
|
||||
int type = rs.getInt("type");
|
||||
try {
|
||||
SQLValueResolver<?> resolver = SQLValueTypes.get(type);
|
||||
if (resolver == null) throw new IllegalStateException("No resolver for type #" + type);
|
||||
String value = rs.getString("value");
|
||||
values.put(path, resolver.resolve(value));
|
||||
|
||||
loadInlineComment(path, rs.getString("inline_comment"));
|
||||
loadHeaderComment(path, rs.getString("header_comments"));
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.rootConfiguration = new SQLConfigWrapper(this, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ConfigurationComments getComments() {
|
||||
return null;
|
||||
public void save() throws Exception {
|
||||
if (this.updated.isEmpty()) return;
|
||||
|
||||
Date date = new Date();
|
||||
List<Object[]> values = new ArrayList<>();
|
||||
List<String> deletes = new ArrayList<>();
|
||||
|
||||
for (String path : this.updated) {
|
||||
Object value = this.rootConfiguration.get(path);
|
||||
if (value == null) {
|
||||
deletes.add(path);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (value instanceof SQLConfigWrapper) {
|
||||
value = getSourceMap(((SQLConfigWrapper) value).getSource());
|
||||
}
|
||||
|
||||
SQLValueResolver<?> type = SQLValueTypes.get(value.getClass());
|
||||
if (type != null) {
|
||||
values.add(new Object[]{
|
||||
this.namespace, path, date,
|
||||
type.getID(), type.serializeObject(value),
|
||||
getComments().getInlineComment(path),
|
||||
GSON.toJson(getComments().getHeaderComment(path))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.updated.clear();
|
||||
|
||||
this.table.createReplaceBatch()
|
||||
.setColumnNames("namespace", "path", "update_time", "type", "value", "inline_comment", "header_comments")
|
||||
.setAllParams(values)
|
||||
.execute();
|
||||
|
||||
for (String path : deletes) {
|
||||
this.table.createDelete()
|
||||
.addCondition("namespace", this.namespace)
|
||||
.addCondition("path", path)
|
||||
.build().execute();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull ConfigurationComments getComments() {
|
||||
return this.comments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ConfigInitializer<? extends ConfigurationProvider<SQLSectionWrapper>> getInitializer() {
|
||||
return null;
|
||||
public @NotNull ConfigInitializer<? extends ConfigurationProvider<SQLConfigWrapper>> getInitializer() {
|
||||
return this.initializer;
|
||||
}
|
||||
|
||||
|
||||
protected void loadInlineComment(String path, String comment) {
|
||||
if (comment == null) return;
|
||||
comment = comment.trim();
|
||||
if (comment.isEmpty()) return;
|
||||
|
||||
this.comments.setInlineComment(path, comment);
|
||||
}
|
||||
|
||||
protected void loadHeaderComment(String path, String commentJson) {
|
||||
if (commentJson == null) return;
|
||||
commentJson = commentJson.trim();
|
||||
if (commentJson.isEmpty()) return;
|
||||
|
||||
List<String> headerComments = GSON.fromJson(commentJson, new TypeToken<List<String>>() {
|
||||
}.getType());
|
||||
if (headerComments == null || headerComments.isEmpty()) return;
|
||||
|
||||
this.comments.setHeaderComments(path, headerComments);
|
||||
}
|
||||
|
||||
protected static Map<String, Object> getSourceMap(Map<String, Object> map) {
|
||||
Map<String, Object> source = new LinkedHashMap<>();
|
||||
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
||||
if (entry.getValue() instanceof SQLConfigWrapper) {
|
||||
source.put(entry.getKey(), getSourceMap(((SQLConfigWrapper) entry.getValue()).getSource()));
|
||||
} else {
|
||||
source.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
return source;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
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.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* For SQL configs, that primary path will be directly mapped to the value.
|
||||
*
|
||||
* @author CarmJos
|
||||
*/
|
||||
public class SQLConfigWrapper implements ConfigurationWrapper<Map<String, Object>> {
|
||||
|
||||
private static final char SEPARATOR = '.';
|
||||
protected final @NotNull SQLConfigProvider provider;
|
||||
protected final @NotNull Map<String, Object> data;
|
||||
|
||||
SQLConfigWrapper(@NotNull SQLConfigProvider provider, @NotNull Map<?, ?> map) {
|
||||
this.provider = provider;
|
||||
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 SQLConfigWrapper(provider, (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) {
|
||||
// Deep is not supported for SQL configs.
|
||||
return new LinkedHashMap<>(this.data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(@NotNull String path, @Nullable Object value) {
|
||||
if (value instanceof Map) {
|
||||
value = new SQLConfigWrapper(this.provider, (Map<?, ?>) value);
|
||||
}
|
||||
|
||||
SQLConfigWrapper 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);
|
||||
}
|
||||
|
||||
this.provider.updated.add(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(@NotNull String path) {
|
||||
return get(path) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Object get(@NotNull String path) {
|
||||
SQLConfigWrapper 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 SQLConfigWrapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable SQLConfigWrapper getConfigurationSection(@NotNull String path) {
|
||||
Object val = get(path);
|
||||
return (val instanceof SQLConfigWrapper) ? (SQLConfigWrapper) val : null;
|
||||
}
|
||||
|
||||
private SQLConfigWrapper getSectionFor(String path) {
|
||||
int index = path.indexOf(SEPARATOR);
|
||||
if (index == -1) return this;
|
||||
|
||||
String root = path.substring(0, index);
|
||||
Object section = this.data.computeIfAbsent(root, k -> new SQLConfigWrapper(this.provider, new LinkedHashMap<>()));
|
||||
|
||||
return (SQLConfigWrapper) section;
|
||||
}
|
||||
|
||||
private String getChild(String path) {
|
||||
int index = path.indexOf(SEPARATOR);
|
||||
return (index == -1) ? path : path.substring(index + 1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package cc.carm.lib.configuration.sql;
|
||||
|
||||
public class SQLValueParser {
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package cc.carm.lib.configuration.sql;
|
||||
|
||||
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class SQLValueResolver<T> {
|
||||
|
||||
public static <V> SQLValueResolver<V> of(int id, @NotNull Class<V> clazz,
|
||||
@NotNull ConfigDataFunction<String, V> resolver) {
|
||||
return of(id, clazz, resolver, String::valueOf);
|
||||
}
|
||||
|
||||
public static <V> SQLValueResolver<V> of(int id, @NotNull Class<V> clazz,
|
||||
@NotNull ConfigDataFunction<String, V> resolver,
|
||||
@NotNull Function<V, String> serializer) {
|
||||
return new SQLValueResolver<>(id, clazz, resolver, serializer);
|
||||
}
|
||||
|
||||
protected final int id;
|
||||
protected final @NotNull Class<T> clazz;
|
||||
protected final @NotNull ConfigDataFunction<String, T> resolver;
|
||||
protected final @NotNull Function<T, String> serializer;
|
||||
|
||||
protected SQLValueResolver(int id, @NotNull Class<T> clazz,
|
||||
@NotNull ConfigDataFunction<String, T> resolver,
|
||||
@NotNull Function<T, String> serializer) {
|
||||
this.id = id;
|
||||
this.clazz = clazz;
|
||||
this.resolver = resolver;
|
||||
this.serializer = serializer;
|
||||
}
|
||||
|
||||
public int getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public @NotNull Class<T> getClazz() {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
public boolean isTypeOf(@NotNull Class<?> clazz) {
|
||||
return this.clazz.isAssignableFrom(clazz);
|
||||
}
|
||||
|
||||
public @NotNull T resolve(String data) throws Exception {
|
||||
return resolver.parse(data);
|
||||
}
|
||||
|
||||
public @Nullable String serialize(T value) {
|
||||
return String.valueOf(value);
|
||||
}
|
||||
|
||||
public @Nullable String serializeObject(Object value) {
|
||||
return isTypeOf(value.getClass()) ? serialize(clazz.cast(value)) : null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package cc.carm.lib.configuration.sql;
|
||||
|
||||
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
interface SQLValueTypes {
|
||||
|
||||
SQLValueResolver<String> STRING = SQLValueResolver.of(0, String.class, ConfigDataFunction.identity());
|
||||
SQLValueResolver<Byte> BYTE = SQLValueResolver.of(1, Byte.class, Byte::parseByte);
|
||||
SQLValueResolver<Short> SHORT = SQLValueResolver.of(2, Short.class, Short::parseShort);
|
||||
SQLValueResolver<Integer> INTEGER = SQLValueResolver.of(3, Integer.class, Integer::parseInt);
|
||||
SQLValueResolver<Long> LONG = SQLValueResolver.of(4, Long.class, Long::parseLong);
|
||||
SQLValueResolver<Float> FLOAT = SQLValueResolver.of(5, Float.class, Float::parseFloat);
|
||||
SQLValueResolver<Double> DOUBLE = SQLValueResolver.of(6, Double.class, Double::parseDouble);
|
||||
SQLValueResolver<Boolean> BOOLEAN = SQLValueResolver.of(7, Boolean.class, Boolean::parseBoolean);
|
||||
SQLValueResolver<Character> CHAR = SQLValueResolver.of(8, Character.class, s -> s.charAt(0));
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
SQLValueResolver<List> LIST = SQLValueResolver.of(10, List.class,
|
||||
array -> SQLConfigProvider.GSON.fromJson(array, List.class),
|
||||
list -> SQLConfigProvider.GSON.toJson(list)
|
||||
);
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
SQLValueResolver<Map> SECTION = SQLValueResolver.of(20, Map.class,
|
||||
section -> SQLConfigProvider.GSON.fromJson(section, LinkedHashMap.class),
|
||||
section -> SQLConfigProvider.GSON.toJson(section)
|
||||
);
|
||||
|
||||
static @NotNull SQLValueResolver<?>[] values() {
|
||||
return new SQLValueResolver<?>[]{
|
||||
STRING, BYTE, SHORT, INTEGER, LONG, FLOAT, DOUBLE, BOOLEAN, CHAR, LIST, SECTION
|
||||
};
|
||||
}
|
||||
|
||||
static SQLValueResolver<?> valueOf(int index) {
|
||||
return values()[index];
|
||||
}
|
||||
|
||||
static @Nullable SQLValueResolver<?> get(int id) {
|
||||
return Arrays.stream(values()).filter(v -> v.id == id).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
static @Nullable SQLValueResolver<?> get(Class<?> typeClazz) {
|
||||
return Arrays.stream(values()).filter(v -> v.isTypeOf(typeClazz)).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package config;
|
||||
|
||||
import cc.carm.lib.configuration.EasyConfiguration;
|
||||
import cc.carm.lib.configuration.demo.tests.ConfigurationTest;
|
||||
import cc.carm.lib.configuration.sql.SQLConfigProvider;
|
||||
import cc.carm.lib.easysql.EasySQL;
|
||||
import cc.carm.lib.easysql.api.SQLManager;
|
||||
import cc.carm.lib.easysql.beecp.BeeDataSourceConfig;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SQLConfigTest {
|
||||
|
||||
@Test
|
||||
public void onTest() {
|
||||
// test();
|
||||
}
|
||||
|
||||
|
||||
public void test() {
|
||||
BeeDataSourceConfig config = new BeeDataSourceConfig();
|
||||
config.setDriverClassName("org.h2.Driver");
|
||||
config.setJdbcUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;MODE=MySQL;");
|
||||
SQLManager manager = EasySQL.createManager(config);
|
||||
manager.setDebugMode(true);
|
||||
|
||||
SQLConfigProvider provider = EasyConfiguration.from(manager, "conf_test", "TESTING");
|
||||
|
||||
ConfigurationTest.testDemo(provider);
|
||||
ConfigurationTest.testInner(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(provider);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Configuration status="WARN" packages="config.SQLConfigTest">
|
||||
<Appenders>
|
||||
<console name="Console" target="SYSTEM_OUT">
|
||||
<PatternLayout pattern="[%d{HH:mm:ss} %level]: %msg%n"/>
|
||||
</console>
|
||||
</Appenders>
|
||||
<Loggers>
|
||||
<Root level="info">
|
||||
<filters>
|
||||
<MarkerFilter marker="NETWORK_PACKETS" onMatch="DENY" onMismatch="NEUTRAL"/>
|
||||
<RegexFilter regex=".*\$\{[^}]*\}.*" onMatch="DENY" onMismatch="NEUTRAL"/>
|
||||
</filters>
|
||||
<AppenderRef ref="File"/>
|
||||
<appender-ref ref="Console"/>
|
||||
</Root>
|
||||
</Loggers>
|
||||
</Configuration>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
CREATE TABLE IF NOT EXISTS conf
|
||||
(
|
||||
`namespace` VARCHAR(255) NOT NULL, # 命名空间
|
||||
`path` VARCHAR(255) NOT NULL, # 配置路径 (ConfigPath)
|
||||
`namespace` VARCHAR(32) NOT NULL, # 命名空间 (代表其属于谁,类似于单个配置文件地址的概念)
|
||||
`path` VARCHAR(96) NOT NULL, # 配置路径 (ConfigPath)
|
||||
`type` TINYINT UNSIGNED NOT NULL DEFAULT 0, # 数据类型 (Integer/Byte/List/Map/...)
|
||||
`value` MEDIUMTEXT, # 配置项的值 (可能为JSON格式)
|
||||
`inline_comments` TEXT, # 行内注释
|
||||
|
||||
+3
-2
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<version>3.8.0</version>
|
||||
<version>3.9.0</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@@ -41,10 +41,11 @@
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bspfsystems</groupId>
|
||||
<artifactId>yamlconfiguration</artifactId>
|
||||
<version>1.3.3</version>
|
||||
<version>2.0.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>3.8.0</version>
|
||||
<version>3.9.0</version>
|
||||
<modules>
|
||||
<module>core</module>
|
||||
<module>demo</module>
|
||||
@@ -110,7 +110,7 @@
|
||||
<dependency>
|
||||
<groupId>org.jetbrains</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
<version>24.0.1</version>
|
||||
<version>24.1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.1.2</version>
|
||||
<version>3.2.3</version>
|
||||
<configuration>
|
||||
<useSystemClassLoader>false</useSystemClassLoader>
|
||||
</configuration>
|
||||
@@ -167,7 +167,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.5.0</version>
|
||||
<version>3.6.3</version>
|
||||
<configuration>
|
||||
<classifier>javadoc</classifier>
|
||||
<detectJavaApiLink>false</detectJavaApiLink>
|
||||
@@ -194,7 +194,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.11.0</version>
|
||||
<version>3.12.0</version>
|
||||
<configuration>
|
||||
<source>${project.jdk.version}</source>
|
||||
<target>${project.jdk.version}</target>
|
||||
@@ -226,7 +226,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.5.0</version>
|
||||
<version>3.5.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
|
||||
Reference in New Issue
Block a user