mirror of
https://github.com/CarmJos/EasyConfiguration.git
synced 2026-06-04 10:38:19 +08:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1c27c2f881 | |||
| 476cb79e2f | |||
| bf716b06ae | |||
| 00170e6d77 | |||
| 1bac201427 | |||
| cd77639df5 |
@@ -49,41 +49,58 @@ Check out all code demonstrations [HERE](demo/src/main/java/cc/carm/lib/configur
|
||||
For more examples, see the [Development Guide](.doc/README.md).
|
||||
|
||||
```java
|
||||
@HeaderComment("Configurations for sample")
|
||||
interface SampleConfig extends Configuration {
|
||||
@ConfigPath(root = true)
|
||||
@HeaderComments("Configurations for sample")
|
||||
public interface SampleConfig extends Configuration {
|
||||
|
||||
@InlineComment("Enabled?") // Inline comment
|
||||
ConfiguredValue<Boolean> ENABLED = ConfiguredValue.of(true);
|
||||
@InlineComment("Enabled?") // Inline comment
|
||||
ConfiguredValue<Boolean> ENABLED = ConfiguredValue.of(true);
|
||||
|
||||
ConfiguredList<UUID> UUIDS = ConfiguredList.builderOf(UUID.class).fromString()
|
||||
.parseValue(UUID::fromString).serializeValue(UUID::toString)
|
||||
.defaults(
|
||||
UUID.fromString("00000000-0000-0000-0000-000000000000"),
|
||||
UUID.fromString("00000000-0000-0000-0000-000000000001")
|
||||
).build();
|
||||
@HeaderComments("Server configurations") // Header comment
|
||||
ConfiguredValue<Integer> PORT = ConfiguredValue.of(Integer.class);
|
||||
|
||||
interface INFO extends Configuration {
|
||||
|
||||
@HeaderComment("Configure your name!") // Header comment
|
||||
ConfiguredValue<String> NAME = ConfiguredValue.of("Joker");
|
||||
@HeaderComments({"[ UUID >-----------------------------------", "A lot of UUIDs"})
|
||||
@FooterComments("[ UUID >-----------------------------------")
|
||||
ConfiguredList<UUID> UUIDS = ConfiguredList.builderOf(UUID.class).fromString()
|
||||
.parse(UUID::fromString).serialize(UUID::toString)
|
||||
.defaults(
|
||||
UUID.fromString("00000000-0000-0000-0000-000000000000"),
|
||||
UUID.fromString("00000000-0000-0000-0000-000000000001")
|
||||
).build();
|
||||
|
||||
@ConfigPath("info") // Custom path
|
||||
interface INFO extends Configuration {
|
||||
|
||||
@HeaderComments("Configure your name!") // Header comment
|
||||
ConfiguredValue<String> NAME = ConfiguredValue.of("Joker");
|
||||
|
||||
@ConfigPath("how-old-are-you") // Custom path
|
||||
ConfiguredValue<Integer> AGE = ConfiguredValue.of(24);
|
||||
|
||||
}
|
||||
|
||||
@ConfigPath("year") // Custom path
|
||||
ConfiguredValue<Integer> AGE = ConfiguredValue.of(24);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
```java
|
||||
public class Sample {
|
||||
public static void main(String[] args) {
|
||||
// 1. Make a configuration provider from a file.
|
||||
ConfigurationProvider<?> provider = EasyConfiguration.from("config.yml");
|
||||
ConfigurationHolder<?> holder = YAMLConfigFactory.from("target/config.yml")
|
||||
.resourcePath("configs/sample.yml")
|
||||
.indent(4) // Optional: Set the indentation of the configuration file.
|
||||
.build();
|
||||
|
||||
// 2. Initialize the configuration classes or instances.
|
||||
provider.initialize(SampleConfig.class);
|
||||
holder.initialize(SampleConfig.class);
|
||||
// 3. Enjoy using the configuration!
|
||||
System.out.println("Enabled? -> " + SampleConfig.ENABLED.resolve());
|
||||
SampleConfig.ENABLED.set(false);
|
||||
System.out.println("Your name is " + SampleConfig.INFO.NAME.getNotNull() + " !");
|
||||
System.out.println("And now? -> " + SampleConfig.ENABLED.resolve());
|
||||
// p.s. Changes not save so enable value will still be true in the next run.
|
||||
|
||||
System.out.println("Your name is " + SampleConfig.INFO.NAME.resolve() + " (age=" + SampleConfig.INFO.AGE.resolve() + ")!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,16 +109,22 @@ public class Sample {
|
||||
```yaml
|
||||
# Configurations for sample
|
||||
|
||||
enabled: true # Enabled?
|
||||
enabled: true #Enabled?
|
||||
|
||||
# Server configurations
|
||||
port:
|
||||
|
||||
# [ UUID >-----------------------------------
|
||||
# A lot of UUIDs
|
||||
uuids:
|
||||
- 00000000-0000-0000-0000-000000000000
|
||||
- 00000000-0000-0000-0000-000000000001
|
||||
# [ UUID >-----------------------------------
|
||||
|
||||
info:
|
||||
# Configure your name!
|
||||
name: Joker
|
||||
year: 24
|
||||
how-old-are-you: 24
|
||||
```
|
||||
|
||||
### Dependencies
|
||||
@@ -159,10 +182,10 @@ info:
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- JSON file-based implementation, compatible with all Java environments. Note: JSON does not support file comments. -->
|
||||
<!-- JSON file-based implementation, compatible with all Java environments. -->
|
||||
<dependency>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easyconfiguration-json</artifactId>
|
||||
<artifactId>easyconfiguration-gson</artifactId>
|
||||
<version>[LATEST RELEASE]</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
@@ -205,8 +228,8 @@ dependencies {
|
||||
// YAML file-based implementation, compatible with all Java environments.
|
||||
api "cc.carm.lib:easyconfiguration-yaml:[LATEST RELEASE]"
|
||||
|
||||
// JSON file-based implementation, compatible with all Java environments. Note: JSON does not support file comments.
|
||||
api "cc.carm.lib:easyconfiguration-json:[LATEST RELEASE]"
|
||||
// JSON file-based implementation, compatible with all Java environments.
|
||||
api "cc.carm.lib:easyconfiguration-gson:[LATEST RELEASE]"
|
||||
|
||||
}
|
||||
```
|
||||
@@ -220,7 +243,8 @@ dependencies {
|
||||
EasyConfiguration for MineCraft!
|
||||
Easily manage configurations on MineCraft-related server platforms.
|
||||
|
||||
Currently supports BungeeCord, Bukkit (Spigot) servers, with more platforms to be supported soon.
|
||||
Currently, it supports BungeeCord, Velocity, Bukkit (Spigot) servers,
|
||||
with more platforms to be supported soon.
|
||||
|
||||
## Support and Donation
|
||||
|
||||
|
||||
+48
-27
@@ -43,42 +43,57 @@ README LANGUAGES [ [English](README.md) | [**中文**](README_CN.md) ]
|
||||
您可以 [点击这里](demo/src/main/java/cc/carm/lib/configuration/demo) 直接查看现有的代码演示,更多复杂情况演示详见 [开发介绍](.doc/README.md) 。
|
||||
|
||||
|
||||
|
||||
```java
|
||||
@HeaderComment("Configurations for sample")
|
||||
interface SampleConfig extends Configuration {
|
||||
@ConfigPath(root = true)
|
||||
@HeaderComments("Configurations for sample")
|
||||
public interface SampleConfig extends Configuration {
|
||||
|
||||
@InlineComment("Enabled?") // 行内注释
|
||||
ConfiguredValue<Boolean> ENABLED = ConfiguredValue.of(true);
|
||||
@InlineComment("Enabled?") // 行后注释
|
||||
ConfiguredValue<Boolean> ENABLED = ConfiguredValue.of(true);
|
||||
|
||||
ConfiguredList<UUID> UUIDS = ConfiguredList.builderOf(UUID.class).fromString()
|
||||
.parseValue(UUID::fromString).serializeValue(UUID::toString)
|
||||
.defaults(
|
||||
UUID.fromString("00000000-0000-0000-0000-000000000000"),
|
||||
UUID.fromString("00000000-0000-0000-0000-000000000001")
|
||||
).build();
|
||||
@HeaderComments("Server configurations") // 头部注释
|
||||
ConfiguredValue<Integer> PORT = ConfiguredValue.of(Integer.class);
|
||||
|
||||
interface INFO extends Configuration {
|
||||
|
||||
@HeaderComment("Configure your name!") // 头部注释
|
||||
ConfiguredValue<String> NAME = ConfiguredValue.of("Joker");
|
||||
@HeaderComments({"[ UUID >-----------------------------------", "A lot of UUIDs"})
|
||||
@FooterComments("[ UUID >-----------------------------------")
|
||||
ConfiguredList<UUID> UUIDS = ConfiguredList.builderOf(UUID.class).fromString()
|
||||
.parse(UUID::fromString).serialize(UUID::toString)
|
||||
.defaults(
|
||||
UUID.fromString("00000000-0000-0000-0000-000000000000"),
|
||||
UUID.fromString("00000000-0000-0000-0000-000000000001")
|
||||
).build();
|
||||
|
||||
interface INFO extends Configuration {
|
||||
|
||||
@HeaderComments("Configure your name!") // Header comment
|
||||
ConfiguredValue<String> NAME = ConfiguredValue.of("Joker");
|
||||
|
||||
@ConfigPath("how-old-are-you") // 自定义路径
|
||||
ConfiguredValue<Integer> AGE = ConfiguredValue.of(24);
|
||||
|
||||
}
|
||||
|
||||
@ConfigPath("year") // 自定义配置路径,若不定义,则按照默认规则生成
|
||||
ConfiguredValue<Integer> AGE = ConfiguredValue.of(24);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
```java
|
||||
public class Sample {
|
||||
public static void main(String[] args) {
|
||||
// 1. 生成一个 “Provider” 用于给配置类提供源配置的文件。
|
||||
ConfigurationProvider<?> provider = EasyConfiguration.from("config.yml");
|
||||
// 2. 通过 “Provider” 初始化配置类或配置实例。
|
||||
provider.initialize(SampleConfig.class);
|
||||
// 1. 生成一个 “holder” 用于给配置类提供源配置的文件。
|
||||
ConfigurationHolder<?> holder = YAMLConfigFactory.from("target/config.yml")
|
||||
.resourcePath("configs/sample.yml")
|
||||
.indent(4) // Optional: Set the indentation of the configuration file.
|
||||
.build();
|
||||
|
||||
// 2. 通过 “holder” 初始化配置类或配置实例。
|
||||
holder.initialize(SampleConfig.class);
|
||||
// 3. 现在可以享受快捷方便的配置文件使用方式了~
|
||||
System.out.println("Enabled? -> " + SampleConfig.ENABLED.resolve());
|
||||
SampleConfig.ENABLED.set(false);
|
||||
System.out.println("Your name is " + SampleConfig.INFO.NAME.getNotNull() + " !");
|
||||
System.out.println("And now? -> " + SampleConfig.ENABLED.resolve());
|
||||
// p.s. 在本示例里的更改未保存,因此启用值在下次运行中仍将为 true。
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -86,16 +101,22 @@ public class Sample {
|
||||
```yaml
|
||||
# Configurations for sample
|
||||
|
||||
enabled: true # Enabled?
|
||||
enabled: true #Enabled?
|
||||
|
||||
# Server configurations
|
||||
port:
|
||||
|
||||
# [ UUID >-----------------------------------
|
||||
# A lot of UUIDs
|
||||
uuids:
|
||||
- 00000000-0000-0000-0000-000000000000
|
||||
- 00000000-0000-0000-0000-000000000001
|
||||
# [ UUID >-----------------------------------
|
||||
|
||||
info:
|
||||
# Configure your name!
|
||||
name: Joker
|
||||
year: 24
|
||||
how-old-are-you: 24
|
||||
```
|
||||
|
||||
### 依赖方式
|
||||
@@ -164,7 +185,7 @@ info:
|
||||
<!--需要注意的是,JSON不支持文件注释。-->
|
||||
<dependency>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easyconfiguration-json</artifactId>
|
||||
<artifactId>easyconfiguration-gson</artifactId>
|
||||
<version>[LATEST RELEASE]</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
@@ -225,7 +246,7 @@ dependencies {
|
||||
|
||||
//基于JSON文件的实现版本,可用于全部Java环境。
|
||||
//需要注意的是,JSON不支持文件注释。
|
||||
api "cc.carm.lib:easyconfiguration-json:[LATEST RELEASE]"
|
||||
api "cc.carm.lib:easyconfiguration-gson:[LATEST RELEASE]"
|
||||
|
||||
api "cc.carm.lib:easyconfiguration-hocon:[LATEST RELEASE]"
|
||||
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<version>4.0.1</version>
|
||||
<version>4.0.2</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<properties>
|
||||
|
||||
@@ -20,6 +20,13 @@ import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* ConfigurationFactory, used to create configuration holder.
|
||||
*
|
||||
* @param <SOURCE> The {@link ConfigureSource} type
|
||||
* @param <HOLDER> The {@link ConfigurationHolder} type.
|
||||
* @param <SELF> Self builder, for further implement support.
|
||||
*/
|
||||
public abstract class ConfigurationFactory<
|
||||
SOURCE extends ConfigureSource<?, ?, SOURCE>,
|
||||
HOLDER extends ConfigurationHolder<SOURCE>,
|
||||
@@ -139,18 +146,39 @@ public abstract class ConfigurationFactory<
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Supply the base path generator for this configuration holder
|
||||
*
|
||||
* @param generator {@link PathGenerator}
|
||||
* @return this
|
||||
*/
|
||||
public SELF pathGenerator(PathGenerator generator) {
|
||||
return initializer(loader -> {
|
||||
loader.pathGenerator(generator);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new annotation for metadata to the configuration loader
|
||||
*
|
||||
* @param annotation The {@link Annotation}
|
||||
* @param metadata The {@link ConfigurationMetadata} type
|
||||
* @param extractor The {@link Function} to extract the metadata from the annotation
|
||||
* @param <M> The metadata type
|
||||
* @param <A> The annotation type
|
||||
* @return this
|
||||
*/
|
||||
public <M, A extends Annotation> SELF metaAnnotation(@NotNull Class<A> annotation,
|
||||
@NotNull ConfigurationMetadata<M> metadata,
|
||||
@NotNull Function<A, M> extractor) {
|
||||
return initializer(loader -> loader.registerAnnotation(annotation, metadata, extractor));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the configuration holder.
|
||||
*
|
||||
* @return The configuration holder
|
||||
*/
|
||||
public abstract @NotNull HOLDER build();
|
||||
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import cc.carm.lib.configuration.adapter.ValueType;
|
||||
import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
|
||||
import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder;
|
||||
import cc.carm.lib.configuration.source.meta.ConfigurationMetadata;
|
||||
import cc.carm.lib.configuration.source.option.ConfigurationOption;
|
||||
import cc.carm.lib.configuration.source.option.ConfigurationOptionHolder;
|
||||
import cc.carm.lib.configuration.source.section.ConfigureSource;
|
||||
import cc.carm.lib.configuration.value.ValueManifest;
|
||||
@@ -50,6 +51,10 @@ public abstract class ConfigurationHolder<SOURCE extends ConfigureSource<?, ?, S
|
||||
return options;
|
||||
}
|
||||
|
||||
public <O> O option(@NotNull ConfigurationOption<O> option) {
|
||||
return options().get(option);
|
||||
}
|
||||
|
||||
public @NotNull Map<String, ConfigurationMetaHolder> metadata() {
|
||||
return this.metadata;
|
||||
}
|
||||
|
||||
+8
-5
@@ -108,13 +108,13 @@ public class ConfigurationInitializer {
|
||||
public void initialize(@NotNull ConfigurationHolder<?> holder,
|
||||
@NotNull Configuration config) throws Exception {
|
||||
initializeInstance(holder, config, null, null);
|
||||
if (holder.options().get(StandardOptions.SET_DEFAULTS)) holder.save();
|
||||
if (holder.option(StandardOptions.SET_DEFAULTS)) holder.save();
|
||||
}
|
||||
|
||||
public void initialize(@NotNull ConfigurationHolder<?> holder,
|
||||
@NotNull Class<? extends Configuration> clazz) throws Exception {
|
||||
initializeStaticClass(holder, clazz, null, null);
|
||||
if (holder.options().get(StandardOptions.SET_DEFAULTS)) holder.save();
|
||||
if (holder.option(StandardOptions.SET_DEFAULTS)) holder.save();
|
||||
}
|
||||
|
||||
|
||||
@@ -149,7 +149,7 @@ public class ConfigurationInitializer {
|
||||
initializeField(holder, clazz, field, path);
|
||||
}
|
||||
|
||||
if (holder.options().get(StandardOptions.LOAD_SUB_CLASSES)) {
|
||||
if (holder.option(StandardOptions.LOAD_SUB_CLASSES)) {
|
||||
Class<?>[] classes = clazz.getDeclaredClasses();
|
||||
for (int i = classes.length - 1; i >= 0; i--) { // 逆向加载,保持顺序。
|
||||
initializeStaticClass(holder, classes[i], path, null);
|
||||
@@ -175,8 +175,11 @@ public class ConfigurationInitializer {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (holder.options().get(StandardOptions.SET_DEFAULTS)) {
|
||||
value.setDefault();
|
||||
if (holder.option(StandardOptions.SET_DEFAULTS)) {
|
||||
value.setDefault(); // Set default value.
|
||||
}
|
||||
if (holder.option(StandardOptions.PRELOAD)) {
|
||||
value.get(); // Preload the value by calling #get method.
|
||||
}
|
||||
} else if (source instanceof Configuration && object instanceof Configuration) {
|
||||
// 当且仅当 源字段与字段 均为Configuration实例时,才对目标字段进行下一步初始化加载。
|
||||
|
||||
@@ -9,6 +9,12 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
/**
|
||||
* Path generator for configuration.
|
||||
* <p>
|
||||
* Path generator is a utility class that helps to generate the path of the configuration.
|
||||
* It can be used to generate the path of the field or class.
|
||||
*/
|
||||
public class PathGenerator {
|
||||
|
||||
public static PathGenerator of() {
|
||||
@@ -80,7 +86,7 @@ public class PathGenerator {
|
||||
}
|
||||
|
||||
public static char pathSeparator(ConfigurationHolder<?> holder) {
|
||||
return holder.options().get(StandardOptions.PATH_SEPARATOR);
|
||||
return holder.option(StandardOptions.PATH_SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+2
-14
@@ -6,32 +6,20 @@ import java.util.function.Supplier;
|
||||
|
||||
public class ConfigurationOption<V> {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> ConfigurationOption<T> of(@NotNull T defaultValue) {
|
||||
return of((Class<T>) defaultValue.getClass(), defaultValue);
|
||||
}
|
||||
|
||||
public static <T> ConfigurationOption<T> of(@NotNull Class<T> valueClazz, @NotNull T defaultValue) {
|
||||
return new ConfigurationOption<>(valueClazz, defaultValue);
|
||||
return new ConfigurationOption<>(defaultValue);
|
||||
}
|
||||
|
||||
public static <T> ConfigurationOption<T> of(@NotNull Supplier<T> defaultValue) {
|
||||
return of(defaultValue.get());
|
||||
}
|
||||
|
||||
private final @NotNull Class<V> valueClazz;
|
||||
private @NotNull V defaultValue;
|
||||
|
||||
public ConfigurationOption(@NotNull Class<V> valueClazz, @NotNull V defaultValue) {
|
||||
this.valueClazz = valueClazz;
|
||||
public ConfigurationOption(@NotNull V defaultValue) {
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Class<V> valueClass() {
|
||||
return this.valueClazz;
|
||||
}
|
||||
|
||||
public @NotNull V defaults() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
+343
-18
@@ -1,7 +1,6 @@
|
||||
package cc.carm.lib.configuration.source.section;
|
||||
|
||||
import cc.carm.lib.configuration.function.DataFunction;
|
||||
import cc.carm.lib.configuration.source.option.StandardOptions;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -12,62 +11,199 @@ import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Represents a section of a configuration.
|
||||
*
|
||||
* @author Carm
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public interface ConfigureSection {
|
||||
|
||||
@NotNull ConfigureSource<?, ?, ?> source();
|
||||
|
||||
/**
|
||||
* Gets the parent section of this section.
|
||||
* <p>
|
||||
* For root sections, this will return null.
|
||||
*
|
||||
* @return Parent section, or null if this is a root section.
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
@Nullable ConfigureSection parent();
|
||||
|
||||
default char separator() {
|
||||
return source().holder().options().get(StandardOptions.PATH_SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a set containing all keys in this section.
|
||||
* <p>
|
||||
* If deep is set to true, then this will contain all the keys within any
|
||||
* child {@link ConfigureSection}s (and their children paths).
|
||||
* <p>
|
||||
* If deep is set to false, then this will contain only the keys of any
|
||||
* direct children, and not their own children.
|
||||
*
|
||||
* @param deep Whether to get a deep list.
|
||||
* @return Set of keys contained within this Section.
|
||||
*/
|
||||
@NotNull
|
||||
@UnmodifiableView
|
||||
default Set<String> getKeys(boolean deep) {
|
||||
return getValues(deep).keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a set containing all values in this section.
|
||||
* <p>
|
||||
* If deep is set to true, then this will contain all the keys within any
|
||||
* child {@link ConfigureSection}s (and their children paths).
|
||||
* <p>
|
||||
* If deep is set to false, then this will contain only the keys of any
|
||||
* direct children, and not their own children.
|
||||
*
|
||||
* @param deep Whether to get a deep list.
|
||||
* @return Map of data values contained within this Section.
|
||||
*/
|
||||
@NotNull
|
||||
@UnmodifiableView
|
||||
Map<String, Object> getValues(boolean deep);
|
||||
|
||||
/**
|
||||
* Sets the value at the given path.
|
||||
* <p>
|
||||
* Null values will be kept, if you want to remove a value use {@link #remove(String)}
|
||||
* Path separator depends on holder's
|
||||
* {@link cc.carm.lib.configuration.source.option.StandardOptions#PATH_SEPARATOR}
|
||||
*
|
||||
* @param path The path to set the value at.
|
||||
* @param value The value to set.
|
||||
*/
|
||||
void set(@NotNull String path, @Nullable Object value);
|
||||
|
||||
/**
|
||||
* Removes the value at the given path.
|
||||
* <p>
|
||||
* Path separator depends on holder's
|
||||
* {@link cc.carm.lib.configuration.source.option.StandardOptions#PATH_SEPARATOR}
|
||||
*
|
||||
* @param path The path to remove the value at.
|
||||
*/
|
||||
void remove(@NotNull String path);
|
||||
|
||||
/**
|
||||
* Check if the value of given path is present.
|
||||
* <p>
|
||||
* Path separator depends on holder's
|
||||
* {@link cc.carm.lib.configuration.source.option.StandardOptions#PATH_SEPARATOR}
|
||||
*
|
||||
* @param path The path to check.
|
||||
* @return True if the value is present, false otherwise.
|
||||
*/
|
||||
boolean contains(@NotNull String path);
|
||||
|
||||
/**
|
||||
* Predicate the value of given path is specific type.
|
||||
*
|
||||
* @param path The path to check.
|
||||
* @param typeClass The type's class
|
||||
* @param <T> The type to check.
|
||||
* @return True if the value is present and is the correct type, false otherwise.
|
||||
*/
|
||||
default <T> boolean isType(@NotNull String path, @NotNull Class<T> typeClass) {
|
||||
return typeClass.isInstance(get(path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Predicate the value of given path is a {@link List}.
|
||||
*
|
||||
* @param path The path to check.
|
||||
* @return True if the value is present and is a list, false otherwise.
|
||||
*/
|
||||
default boolean isList(@NotNull String path) {
|
||||
return isType(path, List.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value as a {@link List} from the specified path.
|
||||
*
|
||||
* @param path The path to get the {@link List}.
|
||||
* @return The list if the path exists and is a list, otherwise null.
|
||||
*/
|
||||
@Nullable List<?> getList(@NotNull String path);
|
||||
|
||||
/**
|
||||
* Predicate the value of given path is a {@link ConfigureSection}.
|
||||
*
|
||||
* @param path The path to check.
|
||||
* @return True if the value is present and is a section, false otherwise.
|
||||
*/
|
||||
default boolean isSection(@NotNull String path) {
|
||||
return isType(path, ConfigureSection.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value as a {@link ConfigureSection} from the specified path.
|
||||
*
|
||||
* @param path The path to get the section.
|
||||
* @return The section if the path exists and is a section, otherwise null.
|
||||
*/
|
||||
@Nullable
|
||||
ConfigureSection getSection(@NotNull String path);
|
||||
|
||||
/**
|
||||
* Get the origin value of the path.
|
||||
*
|
||||
* @param path The path to get the value from.
|
||||
* @return The value at the path, or null if not found.
|
||||
*/
|
||||
@Nullable Object get(@NotNull String path);
|
||||
|
||||
default @Nullable <T> T get(@NotNull String path, @NotNull Class<T> clazz) {
|
||||
return get(path, null, clazz);
|
||||
/**
|
||||
* Get the value of the path for specific type,
|
||||
* if the path does not exist, return null.
|
||||
*
|
||||
* @param path The path to get the value from.
|
||||
* @param type The type class of the value
|
||||
* @param <T> The type of the value
|
||||
* @return The value at the path, or the default value if not found.
|
||||
*/
|
||||
default @Nullable <T> T get(@NotNull String path, @NotNull Class<T> type) {
|
||||
return get(path, null, type);
|
||||
}
|
||||
|
||||
default @Nullable <T> T get(@NotNull String path, @NotNull DataFunction<Object, T> parser) {
|
||||
/**
|
||||
* Get the value of the path using a parser function,
|
||||
* if the path does not exist, return NULL.
|
||||
*
|
||||
* @param path The path to get the value from.
|
||||
* @param parser The function to parse the value
|
||||
* @param <T> The type of the value
|
||||
* @return The value at the path, or null if not found.
|
||||
*/
|
||||
default @Nullable <T> T get(@NotNull String path, @NotNull DataFunction<@Nullable Object, T> parser) {
|
||||
return get(path, null, parser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the path for specific type,
|
||||
* if the path does not exist, return the default value.
|
||||
*
|
||||
* @param path The path to get the value from.
|
||||
* @param defaults The default value to return if the path does not exist.
|
||||
* @param clazz The type class of the value
|
||||
* @param <T> The type of the value
|
||||
* @return The value at the path, or the default value if not found.
|
||||
*/
|
||||
@Contract("_,!null,_->!null")
|
||||
default @Nullable <T> T get(@NotNull String path, @Nullable T defaultValue, @NotNull Class<T> clazz) {
|
||||
return get(path, defaultValue, DataFunction.castObject(clazz));
|
||||
default @Nullable <T> T get(@NotNull String path, @Nullable T defaults, @NotNull Class<T> clazz) {
|
||||
return get(path, defaults, DataFunction.castObject(clazz));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the path using a parser function,
|
||||
* if the path does not exist, return the default value.
|
||||
*
|
||||
* @param path The path to get the value from.
|
||||
* @param defaultValue The default value to return if the path does not exist.
|
||||
* @param parser The function to parse the value
|
||||
* @param <T> The type of the value
|
||||
* @return The value at the path, or the default value if not found.
|
||||
*/
|
||||
@Contract("_,!null,_->!null")
|
||||
default @Nullable <T> T get(@NotNull String path, @Nullable T defaultValue,
|
||||
@NotNull DataFunction<Object, T> parser) {
|
||||
@@ -82,125 +218,290 @@ public interface ConfigureSection {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Predicate the value of given path is a {@link Boolean}.
|
||||
*
|
||||
* @param path The path to check.
|
||||
* @return True if the value is present and is a boolean, false otherwise.
|
||||
*/
|
||||
default boolean isBoolean(@NotNull String path) {
|
||||
return isType(path, Boolean.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value as a {@link Boolean} from the specified path.
|
||||
*
|
||||
* @param path The path to get the boolean.
|
||||
* @return The boolean if the path exists and is a boolean, otherwise false.
|
||||
*/
|
||||
default boolean getBoolean(@NotNull String path) {
|
||||
return getBoolean(path, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value as a {@link Boolean} from the specified path.
|
||||
*
|
||||
* @param path The path to get the boolean.
|
||||
* @param def The default value to return if the path does not exist.
|
||||
* @return The boolean if the path exists and is a boolean, otherwise the default value.
|
||||
*/
|
||||
@Contract("_, !null -> !null")
|
||||
default @Nullable Boolean getBoolean(@NotNull String path, @Nullable Boolean def) {
|
||||
return get(path, def, DataFunction.booleanValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Predicate the value of given path is a {@link Byte}.
|
||||
*
|
||||
* @param path The path to check.
|
||||
* @return True if the value is present and is a byte, false otherwise.
|
||||
*/
|
||||
default @Nullable Boolean isByte(@NotNull String path) {
|
||||
return isType(path, Byte.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value as a {@link Byte} from the specified path.
|
||||
*
|
||||
* @param path The path to get the byte.
|
||||
* @return The byte if the path exists and is a byte, otherwise 0.
|
||||
*/
|
||||
default @Nullable Byte getByte(@NotNull String path) {
|
||||
return getByte(path, (byte) 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value as a {@link Byte} from the specified path.
|
||||
*
|
||||
* @param path The path to get the byte.
|
||||
* @param def The default value to return if the path does not exist.
|
||||
* @return The byte if the path exists and is a byte, otherwise the default value.
|
||||
*/
|
||||
@Contract("_, !null -> !null")
|
||||
default @Nullable Byte getByte(@NotNull String path, @Nullable Byte def) {
|
||||
return get(path, def, DataFunction.byteValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Predicate the value of given path is a {@link Short}.
|
||||
*
|
||||
* @param path The path to check.
|
||||
* @return True if the value is present and is a short, false otherwise.
|
||||
*/
|
||||
default boolean isShort(@NotNull String path) {
|
||||
return isType(path, Short.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value as a {@link Short} from the specified path.
|
||||
*
|
||||
* @param path The path to get the short.
|
||||
* @return The short if the path exists and is a short, otherwise 0.
|
||||
*/
|
||||
default @Nullable Short getShort(@NotNull String path) {
|
||||
return getShort(path, (short) 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value as a {@link Short} from the specified path.
|
||||
*
|
||||
* @param path The path to get the short.
|
||||
* @param def The default value to return if the path does not exist.
|
||||
* @return The short if the path exists and is a short, otherwise the default value.
|
||||
*/
|
||||
@Contract("_, !null -> !null")
|
||||
default @Nullable Short getShort(@NotNull String path, @Nullable Short def) {
|
||||
return get(path, def, DataFunction.shortValue());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Predicate the value of given path is a {@link Integer}.
|
||||
*
|
||||
* @param path The path to check.
|
||||
* @return True if the value is present and is a int, false otherwise.
|
||||
*/
|
||||
default boolean isInt(@NotNull String path) {
|
||||
return isType(path, Integer.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value as a {@link Integer} from the specified path.
|
||||
*
|
||||
* @param path The path to get the int.
|
||||
* @return The int if the path exists and is a int, otherwise 0.
|
||||
*/
|
||||
default @Nullable Integer getInt(@NotNull String path) {
|
||||
return getInt(path, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value as a {@link Integer} from the specified path.
|
||||
*
|
||||
* @param path The path to get the int.
|
||||
* @param def The default value to return if the path does not exist.
|
||||
* @return The int if the path exists and is a int, otherwise the default value.
|
||||
*/
|
||||
@Contract("_, !null -> !null")
|
||||
default @Nullable Integer getInt(@NotNull String path, @Nullable Integer def) {
|
||||
return get(path, def, DataFunction.intValue());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Predicate the value of given path is a {@link Long}.F
|
||||
*
|
||||
* @param path The path to check.
|
||||
* @return True if the value is present and is a long, false otherwise.
|
||||
*/
|
||||
default boolean isLong(@NotNull String path) {
|
||||
return isType(path, Long.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value as a {@link Long} from the specified path.
|
||||
*
|
||||
* @param path The path to get the long.
|
||||
* @return The long if the path exists and is a long, otherwise 0.
|
||||
*/
|
||||
default @Nullable Long getLong(@NotNull String path) {
|
||||
return getLong(path, 0L);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value as a {@link Long} from the specified path.
|
||||
*
|
||||
* @param path The path to get the long.
|
||||
* @param def The default value to return if the path does not exist.
|
||||
* @return The long if the path exists and is a long, otherwise the default value.
|
||||
*/
|
||||
@Contract("_, !null -> !null")
|
||||
default @Nullable Long getLong(@NotNull String path, @Nullable Long def) {
|
||||
return get(path, def, DataFunction.longValue());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Predicate the value of given path is a {@link Float}.
|
||||
*
|
||||
* @param path The path to check.
|
||||
* @return True if the value is present and is a float, false otherwise.
|
||||
*/
|
||||
default boolean isFloat(@NotNull String path) {
|
||||
return isType(path, Float.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value as a {@link Float} from the specified path.
|
||||
*
|
||||
* @param path The path to get the float.
|
||||
* @return The float if the path exists and is a float, otherwise 0.
|
||||
*/
|
||||
default @Nullable Float getFloat(@NotNull String path) {
|
||||
return getFloat(path, 0.0F);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value as a {@link Float} from the specified path.
|
||||
*
|
||||
* @param path The path to get the float.
|
||||
* @param def The default value to return if the path does not exist.
|
||||
* @return The float if the path exists and is a float, otherwise the default value.
|
||||
*/
|
||||
@Contract("_, !null -> !null")
|
||||
default @Nullable Float getFloat(@NotNull String path, @Nullable Float def) {
|
||||
return get(path, def, DataFunction.floatValue());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Predicate the value of given path is a {@link Double}.
|
||||
*
|
||||
* @param path The path to check.
|
||||
* @return True if the value is present and is a double, false otherwise.
|
||||
*/
|
||||
default boolean isDouble(@NotNull String path) {
|
||||
return isType(path, Double.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value as a {@link Double} from the specified path.
|
||||
*
|
||||
* @param path The path to get the double.
|
||||
* @return The double if the path exists and is a double, otherwise 0.
|
||||
*/
|
||||
default @Nullable Double getDouble(@NotNull String path) {
|
||||
return getDouble(path, 0.0D);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value as a {@link Double} from the specified path.
|
||||
*
|
||||
* @param path The path to get the double.
|
||||
* @param def The default value to return if the path does not exist.
|
||||
* @return The double if the path exists and is a double, otherwise the default value.
|
||||
*/
|
||||
@Contract("_, !null -> !null")
|
||||
default @Nullable Double getDouble(@NotNull String path, @Nullable Double def) {
|
||||
return get(path, def, DataFunction.doubleValue());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Predicate the value of given path is a {@link Character}.
|
||||
*
|
||||
* @param path The path to check.
|
||||
* @return True if the value is present and is a char, false otherwise.
|
||||
*/
|
||||
default boolean isChar(@NotNull String path) {
|
||||
return isType(path, Boolean.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value as a {@link Character} from the specified path.
|
||||
*
|
||||
* @param path The path to get the char.
|
||||
* @return The char if the path exists and is a char, otherwise null.
|
||||
*/
|
||||
default @Nullable Character getChar(@NotNull String path) {
|
||||
return getChar(path, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value as a {@link Character} from the specified path.
|
||||
*
|
||||
* @param path The path to get the char.
|
||||
* @param def The default value to return if the path does not exist.
|
||||
* @return The char if the path exists and is a char, otherwise the default value.
|
||||
*/
|
||||
@Contract("_, !null -> !null")
|
||||
default @Nullable Character getChar(@NotNull String path, @Nullable Character def) {
|
||||
return get(path, def, Character.class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Predicate the value of given path is a {@link String}.
|
||||
*
|
||||
* @param path The path to check.
|
||||
* @return True if the value is present and is a string, false otherwise.
|
||||
*/
|
||||
default boolean isString(@NotNull String path) {
|
||||
return isType(path, String.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value as a {@link String} from the specified path.
|
||||
*
|
||||
* @param path The path to get the string.
|
||||
* @return The string if the path exists and is a string, otherwise null.
|
||||
*/
|
||||
default @Nullable String getString(@NotNull String path) {
|
||||
return getString(path, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value as a {@link String} from the specified path.
|
||||
*
|
||||
* @param path The path to get the string.
|
||||
* @param def The default value to return if the path does not exist.
|
||||
* @return The string if the path exists and is a string, otherwise the default value.
|
||||
*/
|
||||
@Contract("_, !null -> !null")
|
||||
default @Nullable String getString(@NotNull String path, @Nullable String def) {
|
||||
return get(path, def, String.class);
|
||||
@@ -298,17 +599,41 @@ public interface ConfigureSection {
|
||||
return getList(path, DataFunction.castObject(Character.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specific type of collection from the section.
|
||||
*
|
||||
* @param path The path to get the collection from
|
||||
* @param constructor The constructor of the collection
|
||||
* @param parser The function to parse the values
|
||||
* @param <T> The type of the values
|
||||
* @param <C> The type of the collection
|
||||
* @return The collection of values
|
||||
*/
|
||||
default <T, C extends Collection<T>> @NotNull C getCollection(@NotNull String path,
|
||||
@NotNull Supplier<C> constructor,
|
||||
@NotNull DataFunction<Object, T> parser) {
|
||||
return parseCollection(getList(path), constructor, parser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specific type of steam from the section.
|
||||
*
|
||||
* @param path The path to get the stream from
|
||||
* @return The stream of values
|
||||
*/
|
||||
default @NotNull Stream<?> stream(@NotNull String path) {
|
||||
List<?> values = getList(path);
|
||||
return values == null ? Stream.empty() : values.stream();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specific type of steam from the section.
|
||||
*
|
||||
* @param path The path to get the stream from
|
||||
* @param parser The function to parse the values
|
||||
* @param <T> The type of the values
|
||||
* @return The stream of values
|
||||
*/
|
||||
default <T> @NotNull Stream<T> stream(@NotNull String path, @NotNull Function<Object, T> parser) {
|
||||
return stream(path).map(parser);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,23 @@
|
||||
package cc.carm.lib.configuration.source.section;
|
||||
|
||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||
import cc.carm.lib.configuration.source.option.StandardOptions;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* ConfigureSource represents the source of configuration,
|
||||
* which can be a file, a database, or any other source.
|
||||
*
|
||||
* @param <SECTION> The type of the root section.
|
||||
* @param <ORIGINAL> The original configuration object.
|
||||
* @param <SELF> The type of the source itself, for further implement support.
|
||||
*/
|
||||
public abstract class ConfigureSource<
|
||||
SECTION extends ConfigureSection, ORIGINAL,
|
||||
SELF extends ConfigureSource<SECTION, ORIGINAL, SELF>>
|
||||
@@ -24,28 +35,46 @@ public abstract class ConfigureSource<
|
||||
return holder;
|
||||
}
|
||||
|
||||
|
||||
public void reload() throws Exception {
|
||||
onReload(); // 调用重写的Reload方法
|
||||
this.lastUpdateMillis = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
protected abstract SELF self();
|
||||
@Contract(pure = true)
|
||||
@ApiStatus.Internal
|
||||
protected abstract @NotNull SELF self();
|
||||
|
||||
/**
|
||||
* @return Original configuration object
|
||||
* @return The original configuration object.
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
public abstract @NotNull ORIGINAL original();
|
||||
|
||||
/**
|
||||
* @return The root {@link ConfigureSection}
|
||||
* @return The root {@link ConfigureSection}, which represents the entire configuration.
|
||||
*/
|
||||
public abstract @NotNull SECTION section();
|
||||
|
||||
/**
|
||||
* Save the whole configuration.
|
||||
*
|
||||
* @throws Exception If any error occurs while saving.
|
||||
*/
|
||||
public abstract void save() throws Exception;
|
||||
|
||||
/**
|
||||
* Reload the configuration.
|
||||
* <br>This used for implementation, for external usage, use {@link #reload()}
|
||||
*
|
||||
* @throws Exception If any error occurs while reloading.
|
||||
*/
|
||||
@ApiStatus.OverrideOnly
|
||||
protected abstract void onReload() throws Exception;
|
||||
|
||||
public char pathSeparator() {
|
||||
return holder().options().get(StandardOptions.PATH_SEPARATOR);
|
||||
}
|
||||
|
||||
public long getLastUpdateMillis() {
|
||||
return this.lastUpdateMillis;
|
||||
}
|
||||
@@ -54,14 +83,15 @@ public abstract class ConfigureSource<
|
||||
return getLastUpdateMillis() > parsedTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Source also represents the root section, so it has no parent
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
@Override
|
||||
@Contract(pure = true, value = "->null")
|
||||
public @Nullable ConfigureSection parent() {
|
||||
return null; // Source also represents the root section, so it has no parent
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ConfigureSource<?, ?, ?> source() {
|
||||
return self();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -80,8 +110,8 @@ public abstract class ConfigureSource<
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isList(@NotNull String path) {
|
||||
return section().isList(path);
|
||||
public void remove(@NotNull String path) {
|
||||
section().remove(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -89,11 +119,6 @@ public abstract class ConfigureSource<
|
||||
return section().getList(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSection(@NotNull String path) {
|
||||
return section().isSection(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ConfigureSection getSection(@NotNull String path) {
|
||||
return section().getSection(path);
|
||||
|
||||
@@ -113,7 +113,7 @@ public abstract class ConfigValue<T> extends ValueManifest<T> {
|
||||
* @param override Whether to overwrite existing configured value
|
||||
*/
|
||||
public void setDefault(boolean override) {
|
||||
if (!override && config().contains(path())) return;
|
||||
if (config().contains(path()) && !override) return; // Skip if the value is already set
|
||||
set(defaults()); // Set the default value
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<version>4.0.1</version>
|
||||
<version>4.0.2</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<properties>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<version>4.0.1</version>
|
||||
<version>4.0.2</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<properties>
|
||||
|
||||
+3
@@ -44,6 +44,9 @@ public @interface InlineComment {
|
||||
* bar: "foobar" # Comment Contents
|
||||
* </pre></blockquote>
|
||||
*
|
||||
* <p><i>Some implements may not support this feature
|
||||
* in list values or other complex structures.</i>
|
||||
*
|
||||
* @return The path regexes of this comment
|
||||
*/
|
||||
@NotNull
|
||||
|
||||
+6
-1
@@ -9,7 +9,12 @@ import java.lang.annotation.Target;
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface InlineComments {
|
||||
|
||||
|
||||
/**
|
||||
* Multiple inline comments support.
|
||||
*
|
||||
* @return inline comment contents.
|
||||
* @see InlineComment
|
||||
*/
|
||||
InlineComment[] value();
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ public class Commentable {
|
||||
String comment = getInlineComment(holder, path, null);
|
||||
if (comment != null) return comment;
|
||||
|
||||
String sep = String.valueOf(holder.options().get(StandardOptions.PATH_SEPARATOR));
|
||||
String sep = String.valueOf(holder.option(StandardOptions.PATH_SEPARATOR));
|
||||
|
||||
// If the comment is not found, try to get the comment from the parent section
|
||||
String[] keys = path.split(Pattern.quote(sep));
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<version>4.0.1</version>
|
||||
<version>4.0.2</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<properties>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<version>4.0.1</version>
|
||||
<version>4.0.2</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<properties>
|
||||
|
||||
+17
-4
@@ -53,7 +53,6 @@ public class MemorySection implements ConfigureSection {
|
||||
return createChild(new LinkedHashMap<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ConfigureSource<? extends MemorySection, ?, ?> source() {
|
||||
return this.source;
|
||||
}
|
||||
@@ -66,6 +65,10 @@ public class MemorySection implements ConfigureSection {
|
||||
return this.parent;
|
||||
}
|
||||
|
||||
public char pathSeparator() {
|
||||
return source.pathSeparator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Map<String, Object> getValues(boolean deep) {
|
||||
return Collections.unmodifiableMap(deep ? mapChildrenValues(this, null, true) : data());
|
||||
@@ -85,6 +88,16 @@ public class MemorySection implements ConfigureSection {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(@NotNull String path) {
|
||||
MemorySection section = getSectionFor(path);
|
||||
if (section != this) {
|
||||
section.remove(childPath(path));
|
||||
} else {
|
||||
this.data.remove(path);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(@NotNull String path) {
|
||||
return get(path) != null;
|
||||
@@ -109,7 +122,7 @@ public class MemorySection implements ConfigureSection {
|
||||
}
|
||||
|
||||
private MemorySection getSectionFor(String path) {
|
||||
int index = path.indexOf(separator());
|
||||
int index = path.indexOf(pathSeparator());
|
||||
if (index == -1) return this;
|
||||
|
||||
String root = path.substring(0, index);
|
||||
@@ -123,7 +136,7 @@ public class MemorySection implements ConfigureSection {
|
||||
}
|
||||
|
||||
private String childPath(String path) {
|
||||
int index = path.indexOf(separator());
|
||||
int index = path.indexOf(pathSeparator());
|
||||
return (index == -1) ? path : path.substring(index + 1);
|
||||
}
|
||||
|
||||
@@ -138,7 +151,7 @@ public class MemorySection implements ConfigureSection {
|
||||
@Nullable String parent, boolean deep) {
|
||||
Map<String, Object> output = new LinkedHashMap<>();
|
||||
for (Map.Entry<String, Object> entry : section.data().entrySet()) {
|
||||
String path = (parent == null ? "" : parent + separator()) + entry.getKey();
|
||||
String path = (parent == null ? "" : parent + pathSeparator()) + entry.getKey();
|
||||
output.remove(path);
|
||||
output.put(path, entry.getValue());
|
||||
if (deep && entry.getValue() instanceof MemorySection) {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<version>4.0.1</version>
|
||||
<version>4.0.2</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<properties>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<version>4.0.1</version>
|
||||
<version>4.0.2</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<properties>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>4.0.1</version>
|
||||
<version>4.0.2</version>
|
||||
<modules>
|
||||
<module>core</module>
|
||||
<module>features/section</module>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<version>4.0.1</version>
|
||||
<version>4.0.2</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -48,7 +48,7 @@ public class JSONSource extends FileConfigSource<MemorySection, Map<String, Obje
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSONSource self() {
|
||||
protected @NotNull JSONSource self() {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<version>4.0.1</version>
|
||||
<version>4.0.2</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<properties>
|
||||
|
||||
@@ -4,7 +4,6 @@ import cc.carm.lib.configuration.commentable.Commentable;
|
||||
import cc.carm.lib.configuration.commentable.CommentableOptions;
|
||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||
import cc.carm.lib.configuration.source.file.FileConfigSource;
|
||||
import cc.carm.lib.configuration.source.option.StandardOptions;
|
||||
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
||||
import cc.carm.lib.configuration.source.section.MemorySection;
|
||||
import cc.carm.lib.yamlcommentupdater.CommentedSection;
|
||||
@@ -56,7 +55,7 @@ public class YAMLSource
|
||||
}
|
||||
|
||||
@Override
|
||||
protected YAMLSource self() {
|
||||
protected @NotNull YAMLSource self() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -70,11 +69,6 @@ public class YAMLSource
|
||||
return Objects.requireNonNull(this.rootSection, "Root section is not initialized.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public char separator() {
|
||||
return holder().options().get(StandardOptions.PATH_SEPARATOR);
|
||||
}
|
||||
|
||||
public @NotNull LoaderOptions loaderOptions() {
|
||||
return holder().options().get(YAMLOptions.LOADER);
|
||||
}
|
||||
@@ -115,9 +109,9 @@ public class YAMLSource
|
||||
@Override
|
||||
public void save() throws Exception {
|
||||
CommentedYAMLWriter writer = new CommentedYAMLWriter(
|
||||
String.valueOf(this.separator()),
|
||||
String.valueOf(this.pathSeparator()),
|
||||
dumperOptions().getIndent(),
|
||||
holder.options().get(CommentableOptions.COMMENT_EMPTY_VALUE)
|
||||
holder.option(CommentableOptions.COMMENT_EMPTY_VALUE)
|
||||
);
|
||||
try {
|
||||
fileWriter(w -> w.write(writer.saveToString(this)));
|
||||
|
||||
@@ -2,6 +2,7 @@ package sample;
|
||||
|
||||
import cc.carm.lib.configuration.Configuration;
|
||||
import cc.carm.lib.configuration.annotation.ConfigPath;
|
||||
import cc.carm.lib.configuration.annotation.FooterComments;
|
||||
import cc.carm.lib.configuration.annotation.HeaderComments;
|
||||
import cc.carm.lib.configuration.annotation.InlineComment;
|
||||
import cc.carm.lib.configuration.value.standard.ConfiguredList;
|
||||
@@ -19,6 +20,8 @@ public interface SampleConfig extends Configuration {
|
||||
@HeaderComments("Server configurations") // Header comment
|
||||
ConfiguredValue<Integer> PORT = ConfiguredValue.of(Integer.class);
|
||||
|
||||
@HeaderComments({"[ UUID >-----------------------------------", "A lot of UUIDs"})
|
||||
@FooterComments("[ UUID >-----------------------------------")
|
||||
ConfiguredList<UUID> UUIDS = ConfiguredList.builderOf(UUID.class).fromString()
|
||||
.parse(UUID::fromString).serialize(UUID::toString)
|
||||
.defaults(
|
||||
|
||||
@@ -11,7 +11,7 @@ public class SampleTest {
|
||||
// 1. Make a configuration provider from a file.
|
||||
ConfigurationHolder<?> holder = YAMLConfigFactory.from("target/config.yml")
|
||||
.resourcePath("configs/sample.yml")
|
||||
.indent(4) // Optional: Set the indentation of the configuration file.
|
||||
.indent(2) // Optional: Set the indentation of the configuration file.
|
||||
.build();
|
||||
|
||||
// 2. Initialize the configuration classes or instances.
|
||||
|
||||
Reference in New Issue
Block a user