mirror of
https://github.com/CarmJos/EasyConfiguration.git
synced 2026-06-04 18:48:20 +08:00
Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 727c26a2fb | |||
| 9c95a16d90 | |||
| 92c05f1a59 | |||
| 739ed41885 | |||
| a66da01996 | |||
| 6dc0447502 | |||
| c49d904665 | |||
| b756074ddc | |||
| 9e3dff3e95 | |||
| fd01d9b7ef | |||
| 0f8383bbf3 | |||
| 1232c7c4da | |||
| 7ac39da4e9 | |||
| bf89f583db | |||
| 03c69ba3a2 | |||
| d9cbd1a283 | |||
| 96e90dd71b | |||
| a9f3d829bd | |||
| 8eefba5159 | |||
| 01e20df559 | |||
| 35398ab741 | |||
| 6f97166192 | |||
| ccd239ad6b | |||
| 69b27476bc | |||
| 0651cac6b0 | |||
| 1a1efad283 | |||
| 3c1ba61b61 | |||
| 1a3e84a787 | |||
| 00228db2c4 | |||
| 0fddfe28af | |||
| 4a17089da0 | |||
| 8faa7b1c24 | |||
| 5e525428fe | |||
| bc0dfd5698 | |||
| dc28d743db | |||
| f61294c5f3 | |||
| 6883a464db | |||
| bcdf0d9bd1 | |||
| 5f89ff4db7 | |||
| d6f4970277 | |||
| c045ca1489 | |||
| ceea900b08 |
@@ -30,7 +30,7 @@
|
||||
|
||||
### 示例代码
|
||||
|
||||
您可以 [点击这里](impl/yaml/src/test/java/config/source/DemoConfiguration.java) 查看部分代码演示,更多演示详见 [开发介绍](.documentation/README.md) 。
|
||||
您可以 [点击这里](demo/src/main/java/cc/carm/lib/configuration/demo/DatabaseConfiguration.java) 查看部分代码演示,更多演示详见 [开发介绍](.documentation/README.md) 。
|
||||
|
||||
### 依赖方式
|
||||
|
||||
|
||||
+3
-1
@@ -5,12 +5,14 @@
|
||||
<parent>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.5.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<properties>
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
||||
</properties>
|
||||
|
||||
<artifactId>easyconfiguration-core</artifactId>
|
||||
|
||||
@@ -46,7 +46,7 @@ public class ConfigInitializer<T extends ConfigurationProvider<?>> {
|
||||
*/
|
||||
public void initialize(@NotNull Class<? extends ConfigurationRoot> clazz,
|
||||
boolean saveDefaults, boolean loadSubClasses) {
|
||||
initializeClass(
|
||||
initializeStaticClass(
|
||||
clazz, null, null,
|
||||
null, null, null,
|
||||
saveDefaults, loadSubClasses
|
||||
@@ -60,12 +60,61 @@ public class ConfigInitializer<T extends ConfigurationProvider<?>> {
|
||||
}
|
||||
}
|
||||
|
||||
protected void initializeClass(@NotNull Class<?> clazz,
|
||||
/**
|
||||
* 初始化指定实例的所有 {@link ConfigValue} 与内部 {@link ConfigurationRoot} 对象。
|
||||
*
|
||||
* @param config 配置文件实例类,须实现 {@link ConfigurationRoot} 。
|
||||
*/
|
||||
public void initialize(@NotNull ConfigurationRoot config) {
|
||||
initialize(config, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化指定实例的所有 {@link ConfigValue} 与内部 {@link ConfigurationRoot} 对象。
|
||||
*
|
||||
* @param config 配置文件实例类,须实现 {@link ConfigurationRoot} 。
|
||||
* @param saveDefaults 是否写入默认值(默认为 true)。
|
||||
*/
|
||||
public void initialize(@NotNull ConfigurationRoot config, boolean saveDefaults) {
|
||||
initializeInstance(
|
||||
config, null, null,
|
||||
null, null, null,
|
||||
saveDefaults
|
||||
);
|
||||
if (saveDefaults) {
|
||||
try {
|
||||
provider.save();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 针对实例类的初始化方法
|
||||
private void initializeInstance(@NotNull ConfigurationRoot root,
|
||||
@Nullable String parentPath, @Nullable String fieldName,
|
||||
@Nullable ConfigPath fieldPath,
|
||||
@Nullable HeaderComment fieldHeaderComments,
|
||||
@Nullable InlineComment fieldInlineComments,
|
||||
boolean saveDefaults) {
|
||||
String path = getClassPath(root.getClass(), parentPath, fieldName, fieldPath);
|
||||
this.provider.setHeaderComment(path, getClassHeaderComments(root.getClass(), fieldHeaderComments));
|
||||
if (path != null) this.provider.setInlineComment(path, readInlineComments(fieldInlineComments));
|
||||
|
||||
for (Field field : root.getClass().getDeclaredFields()) {
|
||||
initializeField(root, field, path, saveDefaults, false);
|
||||
}
|
||||
}
|
||||
|
||||
// 针对静态类的初始化方法
|
||||
private void initializeStaticClass(@NotNull Class<?> clazz,
|
||||
@Nullable String parentPath, @Nullable String fieldName,
|
||||
@Nullable ConfigPath fieldPath,
|
||||
@Nullable HeaderComment fieldHeaderComments,
|
||||
@Nullable InlineComment fieldInlineComments,
|
||||
boolean saveDefaults, boolean loadSubClasses) {
|
||||
if (!ConfigurationRoot.class.isAssignableFrom(clazz)) return; // 只解析继承了 ConfigurationRoot 的类
|
||||
String path = getClassPath(clazz, parentPath, fieldName, fieldPath);
|
||||
this.provider.setHeaderComment(path, getClassHeaderComments(clazz, fieldHeaderComments));
|
||||
if (path != null) this.provider.setInlineComment(path, readInlineComments(fieldInlineComments));
|
||||
@@ -77,7 +126,7 @@ public class ConfigInitializer<T extends ConfigurationProvider<?>> {
|
||||
if (!loadSubClasses) return;
|
||||
Class<?>[] classes = clazz.getDeclaredClasses();
|
||||
for (int i = classes.length - 1; i >= 0; i--) { // 逆向加载,保持顺序。
|
||||
initializeClass(
|
||||
initializeStaticClass(
|
||||
classes[i], path, classes[i].getSimpleName(),
|
||||
null, null, null,
|
||||
saveDefaults, true
|
||||
@@ -85,11 +134,12 @@ public class ConfigInitializer<T extends ConfigurationProvider<?>> {
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeField(@NotNull Class<?> source, @NotNull Field field, @Nullable String parent,
|
||||
boolean saveDefaults, boolean loadSubClasses) {
|
||||
private void initializeField(@NotNull Object source, @NotNull Field field,
|
||||
@Nullable String parent, boolean saveDefaults, boolean loadSubClasses) {
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
Object object = field.get(source);
|
||||
|
||||
if (object instanceof ConfigValue<?>) {
|
||||
initializeValue(
|
||||
(ConfigValue<?>) object, getFieldPath(field, parent),
|
||||
@@ -97,8 +147,18 @@ public class ConfigInitializer<T extends ConfigurationProvider<?>> {
|
||||
field.getAnnotation(InlineComment.class),
|
||||
saveDefaults
|
||||
);
|
||||
} else if (object instanceof Class<?>) {
|
||||
initializeClass(
|
||||
} else if (source instanceof ConfigurationRoot && object instanceof ConfigurationRoot) {
|
||||
// 当且仅当 源字段与字段 均为ConfigurationRoot实例时,才对目标字段进行下一步初始化加载。
|
||||
initializeInstance(
|
||||
(ConfigurationRoot) object, parent, field.getName(),
|
||||
field.getAnnotation(ConfigPath.class),
|
||||
field.getAnnotation(HeaderComment.class),
|
||||
field.getAnnotation(InlineComment.class),
|
||||
saveDefaults
|
||||
);
|
||||
} else if (source instanceof Class<?> && object instanceof Class<?>) {
|
||||
// 当且仅当 源字段与字段 均为静态类时,才对目标字段进行下一步初始化加载。
|
||||
initializeStaticClass(
|
||||
(Class<?>) object, parent, field.getName(),
|
||||
field.getAnnotation(ConfigPath.class),
|
||||
field.getAnnotation(HeaderComment.class),
|
||||
@@ -106,6 +166,11 @@ public class ConfigInitializer<T extends ConfigurationProvider<?>> {
|
||||
saveDefaults, loadSubClasses
|
||||
);
|
||||
}
|
||||
|
||||
// 以上判断实现以下规范:
|
||||
// - 实例类中仅加载 ConfigValue实例 与 ConfigurationRoot实例
|
||||
// - 静态类中仅加载 静态ConfigValue实例 与 静态ConfigurationRoot类
|
||||
|
||||
} catch (IllegalAccessException ignored) {
|
||||
}
|
||||
}
|
||||
@@ -142,7 +207,7 @@ public class ConfigInitializer<T extends ConfigurationProvider<?>> {
|
||||
return value.length() > 0 ? value : null;
|
||||
}
|
||||
|
||||
protected static @Nullable String getClassPath(@NotNull Class<?> clazz,
|
||||
protected static @Nullable String getClassPath(@Nullable Class<?> clazz,
|
||||
@Nullable String parentPath,
|
||||
@Nullable String filedName,
|
||||
@Nullable ConfigPath fieldAnnotation) {
|
||||
@@ -150,6 +215,7 @@ public class ConfigInitializer<T extends ConfigurationProvider<?>> {
|
||||
boolean fromRoot = false;
|
||||
|
||||
// 先获取 Class 对应的路径注解 其优先度最高。
|
||||
if (clazz != null) {
|
||||
ConfigPath clazzAnnotation = clazz.getAnnotation(ConfigPath.class);
|
||||
if (clazzAnnotation != null) {
|
||||
fromRoot = clazzAnnotation.root();
|
||||
@@ -157,6 +223,7 @@ public class ConfigInitializer<T extends ConfigurationProvider<?>> {
|
||||
return (fromRoot ? "" : parent) + clazzAnnotation.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fieldAnnotation != null) {
|
||||
fromRoot = fromRoot || fieldAnnotation.root();
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package cc.carm.lib.configuration.core.builder;
|
||||
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
||||
import cc.carm.lib.configuration.core.value.ValueManifest;
|
||||
import cc.carm.lib.configuration.core.value.ConfigValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public abstract class AbstractConfigBuilder<T, B extends AbstractConfigBuilder<T, B, P>, P extends ConfigurationProvider<?>> {
|
||||
|
||||
@@ -61,4 +63,15 @@ public abstract class AbstractConfigBuilder<T, B extends AbstractConfigBuilder<T
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public @NotNull B defaults(@NotNull Supplier<@Nullable T> defaultValueSupplier) {
|
||||
return defaults(defaultValueSupplier.get());
|
||||
}
|
||||
|
||||
protected @NotNull ValueManifest<T> buildManifest() {
|
||||
return ValueManifest.of(
|
||||
this.provider, this.path,
|
||||
this.headerComments, this.inlineComment, this.defaultValue
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-3
@@ -65,9 +65,7 @@ public class SourceListBuilder<S, V> extends CommonConfigBuilder<List<V>, Source
|
||||
@Override
|
||||
public @NotNull ConfiguredList<V> build() {
|
||||
return new ConfiguredList<>(
|
||||
this.provider, this.path,
|
||||
this.headerComments, this.inlineComment,
|
||||
this.valueClass, this.defaultValue,
|
||||
buildManifest(), this.valueClass,
|
||||
this.sourceParser.andThen(this.valueParser),
|
||||
this.valueSerializer.andThen(sourceSerializer)
|
||||
);
|
||||
|
||||
+10
-4
@@ -2,10 +2,12 @@ package cc.carm.lib.configuration.core.builder.map;
|
||||
|
||||
import cc.carm.lib.configuration.core.builder.CommonConfigBuilder;
|
||||
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
|
||||
import cc.carm.lib.configuration.core.value.ValueManifest;
|
||||
import cc.carm.lib.configuration.core.value.type.ConfiguredMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class SourceMapBuilder<M extends Map<K, V>, S, K, V> extends CommonConfigBuilder<M, SourceMapBuilder<M, S, K, V>> {
|
||||
@@ -51,6 +53,12 @@ public class SourceMapBuilder<M extends Map<K, V>, S, K, V> extends CommonConfig
|
||||
);
|
||||
}
|
||||
|
||||
public @NotNull SourceMapBuilder<M, S, K, V> defaults(@NotNull Consumer<M> factory) {
|
||||
M map = supplier.get();
|
||||
factory.accept(map);
|
||||
return defaults(map);
|
||||
}
|
||||
|
||||
public @NotNull SourceMapBuilder<M, S, K, V> parseKey(@NotNull ConfigDataFunction<String, K> parser) {
|
||||
this.keyParser = parser;
|
||||
return this;
|
||||
@@ -89,10 +97,8 @@ public class SourceMapBuilder<M extends Map<K, V>, S, K, V> extends CommonConfig
|
||||
@Override
|
||||
public @NotNull ConfiguredMap<K, V> build() {
|
||||
return new ConfiguredMap<>(
|
||||
this.provider, this.path,
|
||||
this.headerComments, this.inlineComment,
|
||||
this.defaultValue, this.supplier,
|
||||
this.keyClass, this.keyParser,
|
||||
new ValueManifest<>(provider, path, headerComments, inlineComment, defaultValue),
|
||||
this.supplier, this.keyClass, this.keyParser,
|
||||
this.valueClass, this.sourceParser.andThen(this.valueParser),
|
||||
this.keySerializer, this.valueSerializer.andThen(this.sourceSerializer)
|
||||
);
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ public class ConfigValueBuilder<V> {
|
||||
return fromSection(ConfigValueParser.required(), ConfigDataFunction.required());
|
||||
}
|
||||
|
||||
public @NotNull SectionValueBuilder<V> fromSection(@NotNull ConfigValueParser<ConfigurationWrapper, V> valueParser,
|
||||
public @NotNull SectionValueBuilder<V> fromSection(@NotNull ConfigValueParser<ConfigurationWrapper<?>, V> valueParser,
|
||||
@NotNull ConfigDataFunction<V, ? extends Map<String, Object>> valueSerializer) {
|
||||
return new SectionValueBuilder<>(this.valueClass, valueParser, valueSerializer);
|
||||
}
|
||||
|
||||
+4
-9
@@ -15,11 +15,11 @@ public class SectionValueBuilder<V>
|
||||
|
||||
protected final @NotNull Class<V> valueClass;
|
||||
|
||||
protected @NotNull ConfigValueParser<ConfigurationWrapper, V> parser;
|
||||
protected @NotNull ConfigValueParser<ConfigurationWrapper<?>, V> parser;
|
||||
protected @NotNull ConfigDataFunction<V, ? extends Map<String, Object>> serializer;
|
||||
|
||||
public SectionValueBuilder(@NotNull Class<V> valueClass,
|
||||
@NotNull ConfigValueParser<ConfigurationWrapper, V> parser,
|
||||
@NotNull ConfigValueParser<ConfigurationWrapper<?>, V> parser,
|
||||
@NotNull ConfigDataFunction<V, ? extends Map<String, Object>> serializer) {
|
||||
this.valueClass = valueClass;
|
||||
this.parser = parser;
|
||||
@@ -32,7 +32,7 @@ public class SectionValueBuilder<V>
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NotNull SectionValueBuilder<V> parseValue(ConfigValueParser<ConfigurationWrapper, V> valueParser) {
|
||||
public @NotNull SectionValueBuilder<V> parseValue(ConfigValueParser<ConfigurationWrapper<?>, V> valueParser) {
|
||||
this.parser = valueParser;
|
||||
return this;
|
||||
}
|
||||
@@ -44,12 +44,7 @@ public class SectionValueBuilder<V>
|
||||
|
||||
@Override
|
||||
public @NotNull ConfiguredSection<V> build() {
|
||||
return new ConfiguredSection<>(
|
||||
this.provider, this.path,
|
||||
this.headerComments, this.inlineComment,
|
||||
this.valueClass, this.defaultValue,
|
||||
this.parser, this.serializer
|
||||
);
|
||||
return new ConfiguredSection<>(buildManifest(), this.valueClass, this.parser, this.serializer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-3
@@ -57,9 +57,7 @@ public class SourceValueBuilder<S, V> extends CommonConfigBuilder<V, SourceValue
|
||||
@Override
|
||||
public @NotNull ConfiguredValue<V> build() {
|
||||
return new ConfiguredValue<>(
|
||||
this.provider, this.path,
|
||||
this.headerComments, this.inlineComment,
|
||||
this.valueClass, this.defaultValue,
|
||||
buildManifest(), this.valueClass,
|
||||
this.valueParser.compose(this.sourceParser),
|
||||
this.valueSerializer.andThen(sourceSerializer)
|
||||
);
|
||||
|
||||
@@ -62,6 +62,94 @@ public interface ConfigDataFunction<T, R> {
|
||||
};
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
static <V> @NotNull ConfigDataFunction<String, V> parseString(Class<V> valueClass) {
|
||||
return (input) -> {
|
||||
if (valueClass.isInstance(input)) return valueClass.cast(input);
|
||||
else throw new IllegalArgumentException("Cannot cast string to " + valueClass.getName());
|
||||
};
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
static @NotNull ConfigDataFunction<Object, Integer> intValue() {
|
||||
return (input) -> {
|
||||
if (input instanceof Integer) {
|
||||
return (Integer) input;
|
||||
} else if (input instanceof Number) {
|
||||
return ((Number) input).intValue();
|
||||
} else throw new IllegalArgumentException("Cannot cast value to " + Integer.class.getName());
|
||||
};
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
static @NotNull ConfigDataFunction<Object, Short> shortValue() {
|
||||
return (input) -> {
|
||||
if (input instanceof Short) {
|
||||
return (Short) input;
|
||||
} else if (input instanceof Number) {
|
||||
return ((Number) input).shortValue();
|
||||
} else throw new IllegalArgumentException("Cannot cast value to " + Short.class.getName());
|
||||
};
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
static @NotNull ConfigDataFunction<Object, Double> doubleValue() {
|
||||
return (input) -> {
|
||||
if (input instanceof Double) {
|
||||
return (Double) input;
|
||||
} else if (input instanceof Number) {
|
||||
return ((Number) input).doubleValue();
|
||||
} else throw new IllegalArgumentException("Cannot cast value to " + Double.class.getName());
|
||||
};
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
static @NotNull ConfigDataFunction<Object, Byte> byteValue() {
|
||||
return (input) -> {
|
||||
if (input instanceof Byte) {
|
||||
return (Byte) input;
|
||||
} else if (input instanceof Number) {
|
||||
return ((Number) input).byteValue();
|
||||
} else throw new IllegalArgumentException("Cannot cast value to " + Byte.class.getName());
|
||||
};
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
static @NotNull ConfigDataFunction<Object, Float> floatValue() {
|
||||
return (input) -> {
|
||||
if (input instanceof Float) {
|
||||
return (Float) input;
|
||||
} else if (input instanceof Number) {
|
||||
return ((Number) input).floatValue();
|
||||
} else throw new IllegalArgumentException("Cannot cast value to " + Float.class.getName());
|
||||
};
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
static @NotNull ConfigDataFunction<Object, Long> longValue() {
|
||||
return (input) -> {
|
||||
if (input instanceof Long) {
|
||||
return (Long) input;
|
||||
} else if (input instanceof Number) {
|
||||
return ((Number) input).longValue();
|
||||
} else throw new IllegalArgumentException("Cannot cast value to " + Long.class.getName());
|
||||
};
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
static @NotNull ConfigDataFunction<Object, Boolean> booleanValue() {
|
||||
return (input) -> {
|
||||
if (input instanceof Boolean) {
|
||||
return (Boolean) input;
|
||||
} else if (input instanceof String) {
|
||||
String s = (String) input;
|
||||
return Boolean.parseBoolean(s) || "yes".equalsIgnoreCase(s);
|
||||
} else if (input instanceof Integer) {
|
||||
return ((Integer) input) == 1;
|
||||
} else throw new IllegalArgumentException("Cannot cast value to " + Boolean.class.getName());
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,25 @@ 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)) {
|
||||
input = longValue().parse(input, (Long) defaultValue);
|
||||
} else if (Integer.class.isAssignableFrom(valueClass)) {
|
||||
input = intValue().parse(input, (Integer) defaultValue);
|
||||
} else if (Float.class.isAssignableFrom(valueClass)) {
|
||||
input = floatValue().parse(input, (Float) defaultValue);
|
||||
} else if (Double.class.isAssignableFrom(valueClass)) {
|
||||
input = doubleValue().parse(input, (Double) defaultValue);
|
||||
} else if (Byte.class.isAssignableFrom(valueClass)) {
|
||||
input = byteValue().parse(input, (Byte) defaultValue);
|
||||
} else if (Short.class.isAssignableFrom(valueClass)) {
|
||||
input = shortValue().parse(input, (Short) defaultValue);
|
||||
}
|
||||
} else if (Boolean.class.isAssignableFrom(valueClass)) {
|
||||
input = booleanValue().parse(input, (Boolean) defaultValue);
|
||||
}
|
||||
|
||||
if (valueClass.isInstance(input)) return valueClass.cast(input);
|
||||
else throw new IllegalArgumentException("Cannot cast value to " + valueClass.getName());
|
||||
};
|
||||
@@ -71,92 +90,39 @@ public interface ConfigValueParser<T, R> {
|
||||
};
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
static @NotNull <T> ConfigValueParser<T, String> castToString(Class<T> clazz) {
|
||||
return (input, defaultValue) -> {
|
||||
if (input instanceof String) return (String) input;
|
||||
else return input.toString();
|
||||
};
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
static @NotNull ConfigValueParser<Object, Integer> intValue() {
|
||||
return (input, defaultValue) -> {
|
||||
if (input instanceof Integer) {
|
||||
return (Integer) input;
|
||||
} else if (input instanceof Number) {
|
||||
return ((Number) input).intValue();
|
||||
} else throw new IllegalArgumentException("Cannot cast value to " + Integer.class.getName());
|
||||
};
|
||||
return (input, defaultValue) -> ConfigDataFunction.intValue().parse(input);
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
static @NotNull ConfigValueParser<Object, Short> shortValue() {
|
||||
return (input, defaultValue) -> {
|
||||
if (input instanceof Short) {
|
||||
return (Short) input;
|
||||
} else if (input instanceof Number) {
|
||||
return ((Number) input).shortValue();
|
||||
} else throw new IllegalArgumentException("Cannot cast value to " + Short.class.getName());
|
||||
};
|
||||
return (input, defaultValue) -> ConfigDataFunction.shortValue().parse(input);
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
static @NotNull ConfigValueParser<Object, Double> doubleValue() {
|
||||
return (input, defaultValue) -> {
|
||||
if (input instanceof Double) {
|
||||
return (Double) input;
|
||||
} else if (input instanceof Number) {
|
||||
return ((Number) input).doubleValue();
|
||||
} else throw new IllegalArgumentException("Cannot cast value to " + Double.class.getName());
|
||||
};
|
||||
return (input, defaultValue) -> ConfigDataFunction.doubleValue().parse(input);
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
static @NotNull ConfigValueParser<Object, Byte> byteValue() {
|
||||
return (input, defaultValue) -> {
|
||||
if (input instanceof Byte) {
|
||||
return (Byte) input;
|
||||
} else if (input instanceof Number) {
|
||||
return ((Number) input).byteValue();
|
||||
} else throw new IllegalArgumentException("Cannot cast value to " + Byte.class.getName());
|
||||
};
|
||||
return (input, defaultValue) -> ConfigDataFunction.byteValue().parse(input);
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
static @NotNull ConfigValueParser<Object, Float> floatValue() {
|
||||
return (input, defaultValue) -> {
|
||||
if (input instanceof Float) {
|
||||
return (Float) input;
|
||||
} else if (input instanceof Number) {
|
||||
return ((Number) input).floatValue();
|
||||
} else throw new IllegalArgumentException("Cannot cast value to " + Float.class.getName());
|
||||
};
|
||||
return (input, defaultValue) -> ConfigDataFunction.floatValue().parse(input);
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
static @NotNull ConfigValueParser<Object, Long> longValue() {
|
||||
return (input, defaultValue) -> {
|
||||
if (input instanceof Long) {
|
||||
return (Long) input;
|
||||
} else if (input instanceof Number) {
|
||||
return ((Number) input).longValue();
|
||||
} else throw new IllegalArgumentException("Cannot cast value to " + Long.class.getName());
|
||||
};
|
||||
return (input, defaultValue) -> ConfigDataFunction.longValue().parse(input);
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
static @NotNull ConfigValueParser<Object, Boolean> booleanValue() {
|
||||
return (input, defaultValue) -> {
|
||||
if (input instanceof Boolean) {
|
||||
return (Boolean) input;
|
||||
} else if (input instanceof String) {
|
||||
String s = (String) input;
|
||||
return Boolean.parseBoolean(s) || "yes".equalsIgnoreCase(s);
|
||||
} else if (input instanceof Integer) {
|
||||
return ((Integer) input) == 1;
|
||||
} else throw new IllegalArgumentException("Cannot cast value to " + Boolean.class.getName());
|
||||
};
|
||||
return (input, defaultValue) -> ConfigDataFunction.booleanValue().parse(input);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package cc.carm.lib.configuration.core.source;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public abstract class ConfigurationComments {
|
||||
|
||||
protected final @NotNull Map<String, List<String>> headerComments = new HashMap<>();
|
||||
protected final @NotNull Map<String, String> inlineComments = new HashMap<>();
|
||||
|
||||
protected @NotNull Map<String, List<String>> getHeaderComments() {
|
||||
return headerComments;
|
||||
}
|
||||
|
||||
protected @NotNull Map<String, String> getInlineComments() {
|
||||
return inlineComments;
|
||||
}
|
||||
|
||||
public void setHeaderComments(@Nullable String path, @Nullable List<String> comments) {
|
||||
|
||||
if (comments == null) {
|
||||
getHeaderComments().remove(path);
|
||||
} else {
|
||||
getHeaderComments().put(path, comments);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setInlineComment(@NotNull String path, @Nullable String comment) {
|
||||
if (comment == null) {
|
||||
getInlineComments().remove(path);
|
||||
} else {
|
||||
getInlineComments().put(path, comment);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Unmodifiable
|
||||
public List<String> getHeaderComment(@Nullable String path) {
|
||||
return Optional.ofNullable(getHeaderComments().get(path)).map(Collections::unmodifiableList).orElse(null);
|
||||
}
|
||||
|
||||
public @Nullable String getInlineComment(@NotNull String path) {
|
||||
return getInlineComments().get(path);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+97
-9
@@ -2,13 +2,16 @@ 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.value.ConfigValue;
|
||||
import cc.carm.lib.configuration.core.value.impl.CachedConfigValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public abstract class ConfigurationProvider<W extends ConfigurationWrapper> {
|
||||
public abstract class ConfigurationProvider<W extends ConfigurationWrapper<?>> {
|
||||
|
||||
protected long updateTime;
|
||||
|
||||
@@ -16,42 +19,127 @@ public abstract class ConfigurationProvider<W extends ConfigurationWrapper> {
|
||||
this.updateTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到配置文件的更新(最后加载)时间。
|
||||
*
|
||||
* @return 更新时间
|
||||
*/
|
||||
public long getUpdateTime() {
|
||||
return updateTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于 {@link CachedConfigValue} 判断缓存值是否过期(即缓存的时间早于配置文件的最后加载时间)。
|
||||
*
|
||||
* @param time 缓存值时的时间戳
|
||||
* @return 缓存值是否过期
|
||||
*/
|
||||
public boolean isExpired(long time) {
|
||||
return this.updateTime > time;
|
||||
return getUpdateTime() > time;
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到配置文件的原生功能类。
|
||||
*
|
||||
* @return 原生类
|
||||
*/
|
||||
public abstract @NotNull W getConfiguration();
|
||||
|
||||
public abstract void reload() throws Exception;
|
||||
/**
|
||||
* 重载当前配置文件。(将不会保存已修改的内容)
|
||||
*
|
||||
* @throws Exception 当重载出现错误时抛出
|
||||
*/
|
||||
public void reload() throws Exception {
|
||||
onReload(); // 调用重写的Reload方法
|
||||
this.updateTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将当前对配置文件的更改进行保存。
|
||||
*
|
||||
* @throws Exception 当保存出现错误时抛出
|
||||
*/
|
||||
public abstract void save() throws Exception;
|
||||
|
||||
public abstract void setHeaderComment(@Nullable String path, @Nullable List<String> comments);
|
||||
/**
|
||||
* 针对于不同配置文件类型所执行的重载操作。
|
||||
*
|
||||
* @throws Exception 当操作出现错误时抛出。
|
||||
*/
|
||||
protected abstract void onReload() throws Exception;
|
||||
|
||||
public abstract void setInlineComment(@NotNull String path, @Nullable String comment);
|
||||
public abstract @Nullable ConfigurationComments getComments();
|
||||
|
||||
public void setHeaderComment(@Nullable String path, @Nullable List<String> comments) {
|
||||
if (getComments() == null) return;
|
||||
getComments().setHeaderComments(path, comments);
|
||||
}
|
||||
|
||||
public void setInlineComment(@NotNull String path, @Nullable String comment) {
|
||||
if (getComments() == null) return;
|
||||
getComments().setInlineComment(path, comment);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Unmodifiable
|
||||
public abstract List<String> getHeaderComment(@Nullable String path);
|
||||
public List<String> getHeaderComment(@Nullable String path) {
|
||||
return Optional.ofNullable(getComments()).map(c -> c.getHeaderComment(path)).orElse(null);
|
||||
}
|
||||
|
||||
public abstract @Nullable String getInlineComment(@NotNull String path);
|
||||
public @Nullable String getInlineComment(@NotNull String path) {
|
||||
return Optional.ofNullable(getComments()).map(c -> c.getInlineComment(path)).orElse(null);
|
||||
}
|
||||
|
||||
public abstract @NotNull ConfigInitializer<? extends ConfigurationProvider<W>> getInitializer();
|
||||
|
||||
/**
|
||||
* 初始化指定类以及其子类的所有 {@link ConfigValue} 对象。
|
||||
*
|
||||
* @param configClazz 配置文件类,须继承于 {@link ConfigurationRoot} 。
|
||||
*/
|
||||
public void initialize(Class<? extends ConfigurationRoot> configClazz) {
|
||||
initialize(configClazz, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化指定类以及其子类的所有 {@link ConfigValue} 对象。
|
||||
*
|
||||
* @param configClazz 配置文件类,须继承于 {@link ConfigurationRoot} 。
|
||||
* @param saveDefaults 是否写入默认值(默认为 true)。
|
||||
*/
|
||||
public void initialize(Class<? extends ConfigurationRoot> configClazz, boolean saveDefaults) {
|
||||
getInitializer().initialize(configClazz, saveDefaults);
|
||||
this.getInitializer().initialize(configClazz, saveDefaults);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化指定类的所有 {@link ConfigValue} 对象。
|
||||
*
|
||||
* @param configClazz 配置文件类,须继承于 {@link ConfigurationRoot} 。
|
||||
* @param saveDefaults 是否写入默认值(默认为 true)。
|
||||
* @param loadSubClasses 是否加载内部子类(默认为 true)。
|
||||
*/
|
||||
public void initialize(Class<? extends ConfigurationRoot> configClazz, boolean saveDefaults, boolean loadSubClasses) {
|
||||
getInitializer().initialize(configClazz, saveDefaults, loadSubClasses);
|
||||
this.getInitializer().initialize(configClazz, saveDefaults, loadSubClasses);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化指定实例的所有 {@link ConfigValue} 与内部 {@link ConfigurationRoot} 对象。
|
||||
*
|
||||
* @param config 配置文件实例类,须实现 {@link ConfigurationRoot} 。
|
||||
*/
|
||||
public void initialize(@NotNull ConfigurationRoot config) {
|
||||
this.getInitializer().initialize(config, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化指定实例的所有 {@link ConfigValue} 与内部 {@link ConfigurationRoot} 对象。
|
||||
*
|
||||
* @param config 配置文件实例类,须实现 {@link ConfigurationRoot} 。
|
||||
* @param saveDefaults 是否写入默认值(默认为 true)。
|
||||
*/
|
||||
public void initialize(@NotNull ConfigurationRoot config, boolean saveDefaults) {
|
||||
this.getInitializer().initialize(config, saveDefaults);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import java.util.List;
|
||||
|
||||
interface ConfigurationReader {
|
||||
|
||||
ConfigurationWrapper getWrapper();
|
||||
ConfigurationWrapper<?> getWrapper();
|
||||
|
||||
default boolean isBoolean(@NotNull String path) {
|
||||
return getWrapper().isType(path, Boolean.class);
|
||||
|
||||
@@ -9,13 +9,15 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public interface ConfigurationWrapper extends ConfigurationReader {
|
||||
public interface ConfigurationWrapper<S> extends ConfigurationReader {
|
||||
|
||||
@Override
|
||||
default ConfigurationWrapper getWrapper() {
|
||||
default ConfigurationWrapper<S> getWrapper() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull S getSource();
|
||||
|
||||
@NotNull
|
||||
Set<String> getKeys(boolean deep);
|
||||
|
||||
@@ -66,6 +68,6 @@ public interface ConfigurationWrapper extends ConfigurationReader {
|
||||
boolean isConfigurationSection(@NotNull String path);
|
||||
|
||||
@Nullable
|
||||
ConfigurationWrapper getConfigurationSection(@NotNull String path);
|
||||
ConfigurationWrapper<S> getConfigurationSection(@NotNull String path);
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Objects;
|
||||
|
||||
public abstract class FileConfigProvider<W extends ConfigurationWrapper> extends ConfigurationProvider<W> {
|
||||
public abstract class FileConfigProvider<W extends ConfigurationWrapper<?>> extends ConfigurationProvider<W> {
|
||||
|
||||
protected final @NotNull File file;
|
||||
|
||||
|
||||
@@ -2,62 +2,34 @@ package cc.carm.lib.configuration.core.value;
|
||||
|
||||
import cc.carm.lib.configuration.core.builder.ConfigBuilder;
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
public abstract class ConfigValue<T> {
|
||||
public abstract class ConfigValue<T> extends ValueManifest<T> {
|
||||
|
||||
public static @NotNull ConfigBuilder builder() {
|
||||
return new ConfigBuilder();
|
||||
}
|
||||
|
||||
protected @Nullable ConfigurationProvider<?> provider;
|
||||
protected @Nullable String configPath;
|
||||
|
||||
protected @Nullable List<String> headerComments;
|
||||
protected @Nullable String inlineComments;
|
||||
|
||||
protected @Nullable T defaultValue;
|
||||
public ConfigValue(@NotNull ValueManifest<T> manifest) {
|
||||
super(manifest.provider, manifest.configPath, manifest.headerComments, manifest.inlineComment, manifest.defaultValue);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public ConfigValue(@Nullable ConfigurationProvider<?> provider, @Nullable String configPath,
|
||||
@Nullable List<String> headerComments, @Nullable String inlineComments,
|
||||
@Nullable T defaultValue) {
|
||||
this.provider = provider;
|
||||
this.configPath = configPath;
|
||||
this.headerComments = headerComments;
|
||||
this.inlineComments = inlineComments;
|
||||
this.defaultValue = defaultValue;
|
||||
super(provider, configPath, headerComments, inlineComments, defaultValue);
|
||||
}
|
||||
|
||||
public void initialize(@NotNull ConfigurationProvider<?> provider, boolean saveDefault, @NotNull String configPath,
|
||||
@Nullable List<String> headerComments, @Nullable String inlineComments) {
|
||||
if (this.provider == null) this.provider = provider;
|
||||
if (this.configPath == null) this.configPath = configPath;
|
||||
if (this.headerComments == null) this.headerComments = headerComments;
|
||||
if (this.inlineComments == null) this.inlineComments = inlineComments;
|
||||
this.initialize(provider, configPath, headerComments, inlineComments);
|
||||
if (saveDefault) setDefault();
|
||||
|
||||
if (getHeaderComments() != null) {
|
||||
this.provider.setHeaderComment(getConfigPath(), getHeaderComments());
|
||||
}
|
||||
if (getInlineComments() != null) {
|
||||
this.provider.setInlineComment(getConfigPath(), getInlineComments());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public @Nullable T getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public void setDefaultValue(@Nullable T defaultValue) {
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,39 +103,4 @@ public abstract class ConfigValue<T> {
|
||||
else return false;
|
||||
}
|
||||
|
||||
public @NotNull ConfigurationProvider<?> getProvider() {
|
||||
return Optional.ofNullable(this.provider)
|
||||
.orElseThrow(() -> new IllegalStateException("Value(" + configPath + ") does not have a provider."));
|
||||
}
|
||||
|
||||
public final @NotNull ConfigurationWrapper getConfiguration() {
|
||||
try {
|
||||
return getProvider().getConfiguration();
|
||||
} catch (Exception ex) {
|
||||
throw new IllegalStateException("Value(" + configPath + ") has not been initialized", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public @NotNull String getConfigPath() {
|
||||
return Optional.ofNullable(this.configPath)
|
||||
.orElseThrow(() -> new IllegalStateException("No section path provided."));
|
||||
}
|
||||
|
||||
protected Object getValue() {
|
||||
return getConfiguration().get(getConfigPath());
|
||||
}
|
||||
|
||||
protected void setValue(@Nullable Object value) {
|
||||
getConfiguration().set(getConfigPath(), value);
|
||||
}
|
||||
|
||||
public @Nullable String getInlineComments() {
|
||||
return inlineComments;
|
||||
}
|
||||
|
||||
@Unmodifiable
|
||||
public @Nullable List<String> getHeaderComments() {
|
||||
return headerComments;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
package cc.carm.lib.configuration.core.value;
|
||||
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ValueManifest<T> {
|
||||
|
||||
public static <V> ValueManifest<V> of(@Nullable ConfigurationProvider<?> provider, @Nullable String configPath,
|
||||
@Nullable List<String> headerComments, @Nullable String inlineComments) {
|
||||
return new ValueManifest<>(provider, configPath, headerComments, inlineComments, null);
|
||||
}
|
||||
|
||||
public static <V> ValueManifest<V> of(@Nullable ConfigurationProvider<?> provider, @Nullable String configPath,
|
||||
@Nullable List<String> headerComments, @Nullable String inlineComments,
|
||||
@Nullable V defaultValue) {
|
||||
return new ValueManifest<>(provider, configPath, headerComments, inlineComments, defaultValue);
|
||||
}
|
||||
|
||||
protected @Nullable ConfigurationProvider<?> provider;
|
||||
protected @Nullable String configPath;
|
||||
|
||||
protected @Nullable List<String> headerComments;
|
||||
protected @Nullable String inlineComment;
|
||||
|
||||
protected @Nullable T defaultValue;
|
||||
|
||||
public ValueManifest(@Nullable ConfigurationProvider<?> provider, @Nullable String configPath,
|
||||
@Nullable List<String> headerComments, @Nullable String inlineComment,
|
||||
@Nullable T defaultValue) {
|
||||
this.provider = provider;
|
||||
this.configPath = configPath;
|
||||
this.headerComments = headerComments;
|
||||
this.inlineComment = inlineComment;
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
protected void initialize(@NotNull ConfigurationProvider<?> provider, @NotNull String configPath,
|
||||
@Nullable List<String> headerComments, @Nullable String inlineComments) {
|
||||
if (this.provider == null) this.provider = provider;
|
||||
if (this.configPath == null) this.configPath = configPath;
|
||||
if (this.headerComments == null) this.headerComments = headerComments;
|
||||
if (this.inlineComment == null) this.inlineComment = inlineComments;
|
||||
|
||||
if (getHeaderComments() != null) {
|
||||
this.provider.setHeaderComment(getConfigPath(), getHeaderComments());
|
||||
}
|
||||
if (getInlineComment() != null) {
|
||||
this.provider.setInlineComment(getConfigPath(), getInlineComment());
|
||||
}
|
||||
}
|
||||
|
||||
public @Nullable T getDefaultValue() {
|
||||
return this.defaultValue;
|
||||
}
|
||||
|
||||
public void setDefaultValue(@Nullable T defaultValue) {
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
public @NotNull ConfigurationProvider<?> getProvider() {
|
||||
return Optional.ofNullable(this.provider)
|
||||
.orElseThrow(() -> new IllegalStateException("Value(" + configPath + ") does not have a provider."));
|
||||
}
|
||||
|
||||
public final @NotNull ConfigurationWrapper<?> getConfiguration() {
|
||||
try {
|
||||
return getProvider().getConfiguration();
|
||||
} catch (Exception ex) {
|
||||
throw new IllegalStateException("Value(" + configPath + ") has not been initialized", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public @NotNull String getConfigPath() {
|
||||
return Optional.ofNullable(this.configPath)
|
||||
.orElseThrow(() -> new IllegalStateException("No section path provided."));
|
||||
}
|
||||
|
||||
protected Object getValue() {
|
||||
String path = getConfigPath(); // 当未指定路径时,优先抛出异常
|
||||
return getConfiguration().get(path);
|
||||
}
|
||||
|
||||
protected void setValue(@Nullable Object value) {
|
||||
getConfiguration().set(getConfigPath(), value);
|
||||
}
|
||||
|
||||
public @Nullable String getInlineComment() {
|
||||
return inlineComment;
|
||||
}
|
||||
|
||||
@Unmodifiable
|
||||
public @Nullable List<String> getHeaderComments() {
|
||||
return headerComments;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,21 +1,18 @@
|
||||
package cc.carm.lib.configuration.core.value.impl;
|
||||
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
||||
import cc.carm.lib.configuration.core.value.ConfigValue;
|
||||
import cc.carm.lib.configuration.core.value.ValueManifest;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class CachedConfigValue<T> extends ConfigValue<T> {
|
||||
|
||||
|
||||
protected @Nullable T cachedValue;
|
||||
protected long parsedTime = -1;
|
||||
|
||||
public CachedConfigValue(@Nullable ConfigurationProvider<?> provider, @Nullable String sectionPath,
|
||||
@Nullable List<String> headerComments, @Nullable String inlineComments,
|
||||
@Nullable T defaultValue) {
|
||||
super(provider, sectionPath, headerComments, inlineComments, defaultValue);
|
||||
public CachedConfigValue(@NotNull ValueManifest<T> manifest) {
|
||||
super(manifest);
|
||||
}
|
||||
|
||||
protected T updateCache(T value) {
|
||||
|
||||
@@ -1,34 +1,31 @@
|
||||
package cc.carm.lib.configuration.core.value.type;
|
||||
|
||||
import cc.carm.lib.configuration.core.annotation.HeaderComment;
|
||||
import cc.carm.lib.configuration.core.builder.list.ConfigListBuilder;
|
||||
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
||||
import cc.carm.lib.configuration.core.value.ValueManifest;
|
||||
import cc.carm.lib.configuration.core.value.impl.CachedConfigValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ConfiguredList<V> extends CachedConfigValue<List<V>> {
|
||||
public class ConfiguredList<V> extends CachedConfigValue<List<V>> implements List<V> {
|
||||
|
||||
public static <V> @NotNull ConfigListBuilder<V> builder(@NotNull Class<V> valueClass) {
|
||||
return builder().asList(valueClass);
|
||||
}
|
||||
|
||||
@HeaderComment
|
||||
protected final @NotNull Class<V> valueClass;
|
||||
|
||||
protected final @NotNull ConfigDataFunction<Object, V> parser;
|
||||
protected final @NotNull ConfigDataFunction<V, Object> serializer;
|
||||
|
||||
public ConfiguredList(@Nullable ConfigurationProvider<?> provider, @Nullable String sectionPath,
|
||||
@Nullable List<String> headerComments, @Nullable String inlineComments,
|
||||
@NotNull Class<V> valueClass, @Nullable List<V> defaultValue,
|
||||
public ConfiguredList(@NotNull ValueManifest<List<V>> manifest, @NotNull Class<V> valueClass,
|
||||
@NotNull ConfigDataFunction<Object, V> parser,
|
||||
@NotNull ConfigDataFunction<V, Object> serializer) {
|
||||
super(provider, sectionPath, headerComments, inlineComments, defaultValue);
|
||||
super(manifest);
|
||||
this.valueClass = valueClass;
|
||||
this.parser = parser;
|
||||
this.serializer = serializer;
|
||||
@@ -38,8 +35,9 @@ public class ConfiguredList<V> extends CachedConfigValue<List<V>> {
|
||||
public @NotNull List<V> get() {
|
||||
if (isExpired()) { // 已过时的数据,需要重新解析一次。
|
||||
List<V> list = new ArrayList<>();
|
||||
List<?> data = getConfiguration().getList(getConfigPath());
|
||||
if (data == null || data.isEmpty()) return useOrDefault(list);
|
||||
List<?> data = getConfiguration().contains(getConfigPath()) ?
|
||||
getConfiguration().getList(getConfigPath()) : null;
|
||||
if (data == null) return useOrDefault(list);
|
||||
for (Object dataVal : data) {
|
||||
if (dataVal == null) continue;
|
||||
try {
|
||||
@@ -54,6 +52,25 @@ public class ConfiguredList<V> extends CachedConfigValue<List<V>> {
|
||||
else return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get(int index) {
|
||||
return get().get(index);
|
||||
}
|
||||
|
||||
public <T> @NotNull T modifyValue(Function<List<V>, T> function) {
|
||||
List<V> list = get();
|
||||
T result = function.apply(list);
|
||||
set(list);
|
||||
return result;
|
||||
}
|
||||
|
||||
public @NotNull List<V> modifyList(Consumer<List<V>> consumer) {
|
||||
List<V> list = get();
|
||||
consumer.accept(list);
|
||||
set(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(@Nullable List<V> value) {
|
||||
updateCache(value);
|
||||
@@ -72,5 +89,121 @@ public class ConfiguredList<V> extends CachedConfigValue<List<V>> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public V set(int index, V element) {
|
||||
return modifyValue(list -> list.set(index, element));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return get().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return get().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return get().contains(o);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterator<V> iterator() {
|
||||
return get().iterator();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Object @NotNull [] toArray() {
|
||||
return get().toArray();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public <T> T @NotNull [] toArray(@NotNull T[] a) {
|
||||
return get().toArray(a);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(@NotNull Collection<?> c) {
|
||||
return new HashSet<>(get()).containsAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(V v) {
|
||||
modifyValue(list -> list.add(v));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int index, V element) {
|
||||
modifyList(list -> list.add(index, element));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(@NotNull Collection<? extends V> c) {
|
||||
return modifyValue(list -> list.addAll(c));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(int index, @NotNull Collection<? extends V> c) {
|
||||
return modifyValue(list -> list.addAll(index, c));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
return modifyValue(list -> list.remove(o));
|
||||
}
|
||||
|
||||
@Override
|
||||
public V remove(int index) {
|
||||
return modifyValue(list -> list.remove(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(@NotNull Collection<?> c) {
|
||||
return modifyValue(list -> list.removeAll(c));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(@NotNull Collection<?> c) {
|
||||
return modifyValue(list -> list.retainAll(c));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
modifyList(List::clear);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int indexOf(Object o) {
|
||||
return get().indexOf(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int lastIndexOf(Object o) {
|
||||
return get().lastIndexOf(o);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ListIterator<V> listIterator() {
|
||||
return get().listIterator();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ListIterator<V> listIterator(int index) {
|
||||
return get().listIterator(index);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<V> subList(int fromIndex, int toIndex) {
|
||||
return get().subList(fromIndex, toIndex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,19 +2,22 @@ package cc.carm.lib.configuration.core.value.type;
|
||||
|
||||
import cc.carm.lib.configuration.core.builder.map.ConfigMapBuilder;
|
||||
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
||||
import cc.carm.lib.configuration.core.value.ValueManifest;
|
||||
import cc.carm.lib.configuration.core.value.impl.CachedConfigValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> {
|
||||
public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> implements Map<K, V> {
|
||||
|
||||
public static <K, V> @NotNull ConfigMapBuilder<LinkedHashMap<K, V>, K, V> builder(@NotNull Class<K> keyClass,
|
||||
@NotNull Class<V> valueClass) {
|
||||
@@ -32,15 +35,17 @@ public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> {
|
||||
protected final @NotNull ConfigDataFunction<K, String> keySerializer;
|
||||
protected final @NotNull ConfigDataFunction<V, Object> valueSerializer;
|
||||
|
||||
public ConfiguredMap(@Nullable ConfigurationProvider<?> provider, @Nullable String sectionPath,
|
||||
@Nullable List<String> headerComments, @Nullable String inlineComments,
|
||||
@Nullable Map<K, V> defaultValue, @NotNull Supplier<? extends Map<K, V>> supplier,
|
||||
|
||||
public ConfiguredMap(@NotNull ValueManifest<Map<K, V>> manifest
|
||||
,
|
||||
@NotNull Supplier<? extends Map<K, V>> mapObjSupplier,
|
||||
@NotNull Class<K> keyClass, @NotNull ConfigDataFunction<String, K> keyParser,
|
||||
@NotNull Class<V> valueClass, @NotNull ConfigDataFunction<Object, V> valueParser,
|
||||
@NotNull ConfigDataFunction<K, String> keySerializer,
|
||||
@NotNull ConfigDataFunction<V, Object> valueSerializer) {
|
||||
super(provider, sectionPath, headerComments, inlineComments, defaultValue);
|
||||
this.supplier = supplier;
|
||||
super(manifest
|
||||
);
|
||||
this.supplier = mapObjSupplier;
|
||||
this.keyClass = keyClass;
|
||||
this.valueClass = valueClass;
|
||||
this.keyParser = keyParser;
|
||||
@@ -78,7 +83,7 @@ public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> {
|
||||
if (isExpired()) { // 已过时的数据,需要重新解析一次。
|
||||
Map<K, V> map = supplier.get();
|
||||
|
||||
ConfigurationWrapper section = getConfiguration().getConfigurationSection(getConfigPath());
|
||||
ConfigurationWrapper<?> section = getConfiguration().getConfigurationSection(getConfigPath());
|
||||
if (section == null) return useOrDefault(map);
|
||||
|
||||
Set<String> keys = section.getKeys(false);
|
||||
@@ -103,7 +108,12 @@ public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(Map<K, V> value) {
|
||||
public V get(Object key) {
|
||||
return get().get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(@Nullable Map<K, V> value) {
|
||||
updateCache(value);
|
||||
if (value == null) setValue(null);
|
||||
else {
|
||||
@@ -122,5 +132,78 @@ public class ConfiguredMap<K, V> extends CachedConfigValue<Map<K, V>> {
|
||||
}
|
||||
}
|
||||
|
||||
public <T> @NotNull T modifyValue(Function<Map<K, V>, T> function) {
|
||||
Map<K, V> m = get();
|
||||
T result = function.apply(m);
|
||||
set(m);
|
||||
return result;
|
||||
}
|
||||
|
||||
public @NotNull Map<K, V> modifyMap(Consumer<Map<K, V>> consumer) {
|
||||
Map<K, V> m = get();
|
||||
consumer.accept(m);
|
||||
set(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return get().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return get().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(Object key) {
|
||||
return get().containsKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(Object value) {
|
||||
return get().containsValue(value);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public V put(K key, V value) {
|
||||
return modifyValue(m -> m.put(key, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public V remove(Object key) {
|
||||
return modifyValue(m -> m.remove(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll(@NotNull Map<? extends K, ? extends V> m) {
|
||||
modifyMap(map -> map.putAll(m));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
modifyMap(Map::clear);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<K> keySet() {
|
||||
return get().keySet();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<V> values() {
|
||||
return get().values();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
@Unmodifiable
|
||||
public Set<Entry<K, V>> entrySet() {
|
||||
return get().entrySet();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+8
-10
@@ -3,33 +3,31 @@ package cc.carm.lib.configuration.core.value.type;
|
||||
import cc.carm.lib.configuration.core.builder.value.SectionValueBuilder;
|
||||
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
|
||||
import cc.carm.lib.configuration.core.function.ConfigValueParser;
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
||||
import cc.carm.lib.configuration.core.value.ValueManifest;
|
||||
import cc.carm.lib.configuration.core.value.impl.CachedConfigValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ConfiguredSection<V> extends CachedConfigValue<V> {
|
||||
|
||||
|
||||
public static <V> @NotNull SectionValueBuilder<V> builder(@NotNull Class<V> valueClass) {
|
||||
return builder().asValue(valueClass).fromSection();
|
||||
}
|
||||
|
||||
protected final @NotNull Class<V> valueClass;
|
||||
|
||||
protected final @NotNull ConfigValueParser<ConfigurationWrapper, V> parser;
|
||||
protected final @NotNull ConfigValueParser<ConfigurationWrapper<?>, V> parser;
|
||||
protected final @NotNull ConfigDataFunction<V, ? extends Map<String, Object>> serializer;
|
||||
|
||||
public ConfiguredSection(@Nullable ConfigurationProvider<?> provider, @Nullable String sectionPath,
|
||||
@Nullable List<String> headerComments, @Nullable String inlineComments,
|
||||
@NotNull Class<V> valueClass, @Nullable V defaultValue,
|
||||
@NotNull ConfigValueParser<ConfigurationWrapper, V> parser,
|
||||
public ConfiguredSection(@NotNull ValueManifest<V> manifest, @NotNull Class<V> valueClass,
|
||||
@NotNull ConfigValueParser<ConfigurationWrapper<?>, V> parser,
|
||||
@NotNull ConfigDataFunction<V, ? extends Map<String, Object>> serializer) {
|
||||
super(provider, sectionPath, headerComments, inlineComments, defaultValue);
|
||||
super(manifest);
|
||||
this.valueClass = valueClass;
|
||||
this.parser = parser;
|
||||
this.serializer = serializer;
|
||||
@@ -39,7 +37,7 @@ public class ConfiguredSection<V> extends CachedConfigValue<V> {
|
||||
return valueClass;
|
||||
}
|
||||
|
||||
public @NotNull ConfigValueParser<ConfigurationWrapper, V> getParser() {
|
||||
public @NotNull ConfigValueParser<ConfigurationWrapper<?>, V> getParser() {
|
||||
return parser;
|
||||
}
|
||||
|
||||
@@ -50,7 +48,7 @@ public class ConfiguredSection<V> extends CachedConfigValue<V> {
|
||||
@Override
|
||||
public @Nullable V get() {
|
||||
if (isExpired()) { // 已过时的数据,需要重新解析一次。
|
||||
ConfigurationWrapper section = getConfiguration().getConfigurationSection(getConfigPath());
|
||||
ConfigurationWrapper<?> section = getConfiguration().getConfigurationSection(getConfigPath());
|
||||
if (section == null) return useDefault();
|
||||
try {
|
||||
// 若未出现错误,则直接更新缓存并返回。
|
||||
|
||||
@@ -3,12 +3,11 @@ package cc.carm.lib.configuration.core.value.type;
|
||||
import cc.carm.lib.configuration.core.builder.value.ConfigValueBuilder;
|
||||
import cc.carm.lib.configuration.core.function.ConfigDataFunction;
|
||||
import cc.carm.lib.configuration.core.function.ConfigValueParser;
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
||||
import cc.carm.lib.configuration.core.value.ValueManifest;
|
||||
import cc.carm.lib.configuration.core.value.impl.CachedConfigValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ConfiguredValue<V> extends CachedConfigValue<V> {
|
||||
@@ -30,13 +29,10 @@ public class ConfiguredValue<V> extends CachedConfigValue<V> {
|
||||
protected final @NotNull ConfigValueParser<Object, V> parser;
|
||||
protected final @NotNull ConfigDataFunction<V, Object> serializer;
|
||||
|
||||
public ConfiguredValue(@Nullable ConfigurationProvider<?> provider, @Nullable String sectionPath,
|
||||
@Nullable List<String> headerComments, @Nullable String inlineComments,
|
||||
@NotNull Class<V> valueClass, @Nullable V defaultValue,
|
||||
public ConfiguredValue(@NotNull ValueManifest<V> manifest, @NotNull Class<V> valueClass,
|
||||
@NotNull ConfigValueParser<Object, V> parser,
|
||||
@NotNull ConfigDataFunction<V, Object> serializer) {
|
||||
|
||||
super(provider, sectionPath, headerComments, inlineComments, defaultValue);
|
||||
super(manifest);
|
||||
this.valueClass = valueClass;
|
||||
this.parser = parser;
|
||||
this.serializer = serializer;
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package config.offset;
|
||||
package cc.carm.test.config.offset;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
//package config.offset;
|
||||
//
|
||||
//
|
||||
//import sun.misc.Unsafe;
|
||||
//
|
||||
//import java.lang.reflect.Field;
|
||||
//import java.lang.reflect.Modifier;
|
||||
//import java.util.Collections;
|
||||
//import java.util.LinkedList;
|
||||
//import java.util.List;
|
||||
//
|
||||
///**
|
||||
// * @author Chris2018998
|
||||
// */
|
||||
//public class OffsetUtil {
|
||||
// private static Unsafe unsafe;
|
||||
//
|
||||
// static {
|
||||
// try {
|
||||
// // 获取 Unsafe 内部的私有的实例化单例对象
|
||||
// Field field = Unsafe.class.getDeclaredField("theUnsafe");
|
||||
// // 无视权限
|
||||
// field.setAccessible(true);
|
||||
// unsafe = (Unsafe) field.get(null);
|
||||
// } catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
//// try {
|
||||
//// unsafe = AccessController.doPrivileged((PrivilegedExceptionAction<Unsafe>) () -> {
|
||||
//// Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
|
||||
//// theUnsafe.setAccessible(true);
|
||||
//// return (Unsafe) theUnsafe.get(null);
|
||||
//// });
|
||||
//// } catch (Throwable e) {
|
||||
//// System.err.println("Unable to load unsafe");
|
||||
//// }
|
||||
// }
|
||||
//
|
||||
// public static List<FieldOffset> getClassMemberOffset(Class<?> beanClass) {
|
||||
// List<FieldOffset> offsetsList = new LinkedList<>();
|
||||
// for (Field field : beanClass.getDeclaredFields()) {
|
||||
// FieldOffset fieldOffset = new FieldOffset(field);
|
||||
// offsetsList.add(fieldOffset);
|
||||
// if (Modifier.isStatic(field.getModifiers()))
|
||||
// fieldOffset.setOffsetValue(unsafe.staticFieldOffset(field));
|
||||
// else
|
||||
// fieldOffset.setOffsetValue(unsafe.objectFieldOffset(field));
|
||||
// Class<?> fieldType = field.getType();
|
||||
// if (!fieldType.getName().startsWith("java")) {
|
||||
// Field[] subfields = fieldType.getDeclaredFields();
|
||||
// if (subfields.length > 0) {
|
||||
// fieldOffset.setSubFieldOffsetList(getClassMemberOffset(fieldType));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Collections.sort(offsetsList);
|
||||
// return offsetsList;
|
||||
// }
|
||||
//
|
||||
//
|
||||
//}
|
||||
//
|
||||
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<version>3.5.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<properties>
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
||||
</properties>
|
||||
<artifactId>easyconfiguration-demo</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>${project.parent.groupId}</groupId>
|
||||
<artifactId>easyconfiguration-core</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
+3
-2
@@ -1,4 +1,4 @@
|
||||
package config.source;
|
||||
package cc.carm.lib.configuration.demo;
|
||||
|
||||
import cc.carm.lib.configuration.core.ConfigurationRoot;
|
||||
import cc.carm.lib.configuration.core.annotation.ConfigPath;
|
||||
@@ -12,7 +12,8 @@ public class DatabaseConfiguration extends ConfigurationRoot {
|
||||
@ConfigPath("driver")
|
||||
@HeaderComment({
|
||||
"数据库驱动配置,请根据数据库类型设置。",
|
||||
"- MySQL: com.mysql.cj.jdbc.Driver",
|
||||
"- MySQL(旧): com.mysql.jdbc.Driver",
|
||||
"- MySQL(新): com.mysql.cj.jdbc.Driver",
|
||||
"- MariaDB(推荐): org.mariadb.jdbc.Driver",
|
||||
})
|
||||
protected static final ConfigValue<String> DRIVER_NAME = ConfiguredValue.of(
|
||||
@@ -0,0 +1,89 @@
|
||||
package cc.carm.lib.configuration.demo.tests;
|
||||
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
||||
import cc.carm.lib.configuration.demo.tests.conf.DemoConfiguration;
|
||||
import cc.carm.lib.configuration.demo.tests.conf.TestConfiguration;
|
||||
import cc.carm.lib.configuration.demo.tests.model.TestModel;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class ConfigurationTest {
|
||||
|
||||
@TestOnly
|
||||
public static void testDemo(ConfigurationProvider<?> provider) {
|
||||
provider.initialize(DemoConfiguration.class);
|
||||
|
||||
System.out.println("----------------------------------------------------");
|
||||
|
||||
System.out.println("Test Number: ");
|
||||
|
||||
System.out.println("before: " + DemoConfiguration.TEST_NUMBER.get());
|
||||
DemoConfiguration.TEST_NUMBER.set((long) (Long.MAX_VALUE * Math.random()));
|
||||
System.out.println("after: " + DemoConfiguration.TEST_NUMBER.get());
|
||||
|
||||
System.out.println("> Test Value:");
|
||||
System.out.println("before: " + DemoConfiguration.Sub.UUID_CONFIG_VALUE.get());
|
||||
DemoConfiguration.Sub.UUID_CONFIG_VALUE.set(UUID.randomUUID());
|
||||
System.out.println("after: " + DemoConfiguration.Sub.UUID_CONFIG_VALUE.get());
|
||||
|
||||
System.out.println("> Test List:");
|
||||
|
||||
System.out.println(" Before:");
|
||||
DemoConfiguration.Sub.That.OPERATORS.forEach(System.out::println);
|
||||
List<UUID> operators = IntStream.range(0, 5).mapToObj(i -> UUID.randomUUID()).collect(Collectors.toList());
|
||||
DemoConfiguration.Sub.That.OPERATORS.set(operators);
|
||||
System.out.println(" After:");
|
||||
DemoConfiguration.Sub.That.OPERATORS.forEach(System.out::println);
|
||||
|
||||
System.out.println("> Clear List:");
|
||||
System.out.println(" Before: size :" + DemoConfiguration.Sub.That.OPERATORS.size());
|
||||
DemoConfiguration.Sub.That.OPERATORS.modifyList(List::clear);
|
||||
System.out.println(" After size :" + DemoConfiguration.Sub.That.OPERATORS.size());
|
||||
|
||||
System.out.println("> Test Section:");
|
||||
System.out.println(DemoConfiguration.MODEL_TEST.get());
|
||||
DemoConfiguration.MODEL_TEST.set(TestModel.random());
|
||||
|
||||
System.out.println("> Test Maps:");
|
||||
DemoConfiguration.USERS.forEach((k, v) -> System.out.println(k + ": " + v));
|
||||
LinkedHashMap<Integer, UUID> data = new LinkedHashMap<>();
|
||||
for (int i = 1; i <= 5; i++) {
|
||||
data.put(i, UUID.randomUUID());
|
||||
}
|
||||
DemoConfiguration.USERS.set(data);
|
||||
System.out.println("----------------------------------------------------");
|
||||
}
|
||||
|
||||
public static void testInner(ConfigurationProvider<?> provider) {
|
||||
|
||||
TestConfiguration TEST = new TestConfiguration();
|
||||
|
||||
provider.initialize(TEST, true);
|
||||
|
||||
System.out.println("> Test Inner value before:");
|
||||
System.out.println(TEST.INNER.INNER_VALUE.getNotNull());
|
||||
|
||||
double after = Math.random() * 200D;
|
||||
System.out.println("> Test Inner value -> " + after);
|
||||
TEST.INNER.INNER_VALUE.set(after);
|
||||
|
||||
System.out.println("> Test Inner value after:");
|
||||
System.out.println(TEST.INNER.INNER_VALUE.getNotNull());
|
||||
|
||||
}
|
||||
|
||||
public static void save(ConfigurationProvider<?> provider) {
|
||||
try {
|
||||
provider.save();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+9
-13
@@ -1,4 +1,4 @@
|
||||
package config.source;
|
||||
package cc.carm.lib.configuration.demo.tests.conf;
|
||||
|
||||
import cc.carm.lib.configuration.core.ConfigInitializer;
|
||||
import cc.carm.lib.configuration.core.ConfigurationRoot;
|
||||
@@ -10,10 +10,8 @@ import cc.carm.lib.configuration.core.value.type.ConfiguredList;
|
||||
import cc.carm.lib.configuration.core.value.type.ConfiguredMap;
|
||||
import cc.carm.lib.configuration.core.value.type.ConfiguredSection;
|
||||
import cc.carm.lib.configuration.core.value.type.ConfiguredValue;
|
||||
import config.model.TestModel;
|
||||
import cc.carm.lib.configuration.demo.tests.model.TestModel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -27,16 +25,15 @@ public class DemoConfiguration extends ConfigurationRoot {
|
||||
@ConfigPath(root = true)
|
||||
protected static final ConfigValue<Double> VERSION = ConfiguredValue.of(Double.class, 1.0D);
|
||||
|
||||
@ConfigPath(root = true)
|
||||
public static final ConfigValue<Long> TEST_NUMBER = ConfiguredValue.of(Long.class, 1000000L);
|
||||
|
||||
// 支持通过 Class<?> 变量标注子配置,一并注册。
|
||||
// 注意: 若对应类也有注解,则优先使用类的注解。
|
||||
@ConfigPath("impl-test") //支持通过注解修改子配置的主路径,若不修改则以变量名自动生成。
|
||||
@ConfigPath("other-class-config") //支持通过注解修改子配置的主路径,若不修改则以变量名自动生成。
|
||||
@HeaderComment({"", "Something..."}) // 支持给子路径直接打注释
|
||||
@InlineComment("InlineComments for class path")
|
||||
public static final Class<?> IMPL = ImplConfiguration.class;
|
||||
|
||||
// 子配置文件
|
||||
@ConfigPath("database")
|
||||
public static final Class<?> DB_CONFIG = DatabaseConfiguration.class;
|
||||
public static final Class<?> OTHER = OtherConfiguration.class;
|
||||
|
||||
@ConfigPath("user") // 通过注解规定配置文件中的路径,若不进行注解则以变量名自动生成。
|
||||
@HeaderComment({"", "Section类型数据测试"}) // 通过注解给配置添加注释。
|
||||
@@ -48,7 +45,7 @@ public class DemoConfiguration extends ConfigurationRoot {
|
||||
.serializeValue(TestModel::serialize).build();
|
||||
|
||||
@HeaderComment({"", "[ID - UUID]对照表", "", "用于测试Map类型的解析与序列化保存"})
|
||||
public static final ConfigValue<Map<Integer, UUID>> USERS = ConfiguredMap
|
||||
public static final ConfiguredMap<Integer, UUID> USERS = ConfiguredMap
|
||||
.builder(Integer.class, UUID.class).fromString()
|
||||
.parseKey(Integer::parseInt)
|
||||
.parseValue(v -> Objects.requireNonNull(UUID.fromString(v)))
|
||||
@@ -70,13 +67,12 @@ public class DemoConfiguration extends ConfigurationRoot {
|
||||
|
||||
public static class That extends ConfigurationRoot {
|
||||
|
||||
public static final ConfigValue<List<UUID>> OPERATORS = ConfiguredList
|
||||
public static final ConfiguredList<UUID> OPERATORS = ConfiguredList
|
||||
.builder(UUID.class).fromString()
|
||||
.parseValue(s -> Objects.requireNonNull(UUID.fromString(s)))
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
package cc.carm.lib.configuration.demo.tests.conf;
|
||||
|
||||
public class OtherConfiguration {
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package cc.carm.lib.configuration.demo.tests.conf;
|
||||
|
||||
import cc.carm.lib.configuration.core.ConfigurationRoot;
|
||||
import cc.carm.lib.configuration.core.annotation.ConfigPath;
|
||||
import cc.carm.lib.configuration.core.annotation.HeaderComment;
|
||||
import cc.carm.lib.configuration.core.annotation.InlineComment;
|
||||
import cc.carm.lib.configuration.core.value.ConfigValue;
|
||||
import cc.carm.lib.configuration.core.value.type.ConfiguredSection;
|
||||
import cc.carm.lib.configuration.core.value.type.ConfiguredValue;
|
||||
import cc.carm.lib.configuration.demo.tests.model.TestModel;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class TestConfiguration extends ConfigurationRoot {
|
||||
|
||||
public final TestInnerConfiguration INNER = new TestInnerConfiguration();
|
||||
|
||||
public final ConfigValue<Double> CLASS_VALUE = ConfiguredValue.of(Double.class, 1.0D);
|
||||
|
||||
@ConfigPath("test.user") // 通过注解规定配置文件中的路径,若不进行注解则以变量名自动生成。
|
||||
@HeaderComment({"", "Section类型数据测试"}) // 通过注解给配置添加注释。
|
||||
@InlineComment("Section数据也支持InlineComment注释")
|
||||
public final ConfigValue<TestModel> TEST_MODEL = ConfiguredSection
|
||||
.builder(TestModel.class)
|
||||
.defaults(new TestModel("Carm", UUID.randomUUID()))
|
||||
.parseValue((section, defaultValue) -> TestModel.deserialize(section))
|
||||
.serializeValue(TestModel::serialize).build();
|
||||
|
||||
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package cc.carm.lib.configuration.demo.tests.conf;
|
||||
|
||||
import cc.carm.lib.configuration.core.ConfigurationRoot;
|
||||
import cc.carm.lib.configuration.core.annotation.HeaderComment;
|
||||
import cc.carm.lib.configuration.core.value.ConfigValue;
|
||||
import cc.carm.lib.configuration.core.value.type.ConfiguredValue;
|
||||
|
||||
@HeaderComment("Inner Test")
|
||||
public class TestInnerConfiguration extends ConfigurationRoot {
|
||||
|
||||
public final ConfigValue<Double> INNER_VALUE = ConfiguredValue.of(Double.class, 1.0D);
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package config.model;
|
||||
package cc.carm.lib.configuration.demo.tests.model;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
package config.model;
|
||||
package cc.carm.lib.configuration.demo.tests.model;
|
||||
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -33,7 +33,7 @@ public class TestModel extends AbstractModel {
|
||||
return map;
|
||||
}
|
||||
|
||||
public static TestModel deserialize(ConfigurationWrapper section) {
|
||||
public static TestModel deserialize(ConfigurationWrapper<?> section) {
|
||||
String name = section.getString("name");
|
||||
if (name == null) throw new NullPointerException("name is null");
|
||||
String uuidString = section.getString("info.uuid");
|
||||
+11
-2
@@ -5,13 +5,15 @@
|
||||
<parent>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.5.0</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<properties>
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
||||
</properties>
|
||||
<artifactId>easyconfiguration-json</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
@@ -25,10 +27,17 @@
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>${project.parent.groupId}</groupId>
|
||||
<artifactId>easyconfiguration-demo</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.9.0</version>
|
||||
<version>2.10.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cc.carm.lib.configuration.json;
|
||||
|
||||
import cc.carm.lib.configuration.core.ConfigInitializer;
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationComments;
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
||||
import cc.carm.lib.configuration.core.source.impl.FileConfigProvider;
|
||||
import com.google.gson.Gson;
|
||||
@@ -8,12 +9,10 @@ import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonSerializer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Some code comes from BungeeCord's implementation of the JsonConfiguration.
|
||||
@@ -49,7 +48,6 @@ public class JSONConfigProvider extends FileConfigProvider<JSONConfigWrapper> {
|
||||
if (map == null) map = new LinkedHashMap<>();
|
||||
|
||||
this.configuration = new JSONConfigWrapper(map);
|
||||
this.initializer = new ConfigInitializer<>(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -58,10 +56,16 @@ public class JSONConfigProvider extends FileConfigProvider<JSONConfigWrapper> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
protected void onReload() throws Exception {
|
||||
super.reload();
|
||||
initializeConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ConfigurationComments getComments() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() throws Exception {
|
||||
try (Writer writer = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)) {
|
||||
@@ -69,26 +73,6 @@ public class JSONConfigProvider extends FileConfigProvider<JSONConfigWrapper> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeaderComment(@Nullable String path, @Nullable List<String> comments) {
|
||||
// JSON doesn't support comments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInlineComment(@NotNull String path, @Nullable String comment) {
|
||||
// JSON doesn't support comments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable @Unmodifiable List<String> getHeaderComment(@Nullable String path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getInlineComment(@NotNull String path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ConfigInitializer<? extends ConfigurationProvider<JSONConfigWrapper>> getInitializer() {
|
||||
return this.initializer;
|
||||
|
||||
@@ -14,7 +14,7 @@ import java.util.Set;
|
||||
*
|
||||
* @author md_5, CarmJos
|
||||
*/
|
||||
public class JSONConfigWrapper implements ConfigurationWrapper {
|
||||
public class JSONConfigWrapper implements ConfigurationWrapper<Map<String, Object>> {
|
||||
|
||||
private static final char SEPARATOR = '.';
|
||||
protected final Map<String, Object> data;
|
||||
@@ -33,6 +33,10 @@ public class JSONConfigWrapper implements ConfigurationWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Map<String, Object> getSource() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<String> getKeys(boolean deep) {
|
||||
@@ -94,7 +98,7 @@ public class JSONConfigWrapper implements ConfigurationWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ConfigurationWrapper getConfigurationSection(@NotNull String path) {
|
||||
public @Nullable JSONConfigWrapper getConfigurationSection(@NotNull String path) {
|
||||
Object val = get(path);
|
||||
return (val instanceof JSONConfigWrapper) ? (JSONConfigWrapper) val : null;
|
||||
}
|
||||
|
||||
@@ -1,67 +1,28 @@
|
||||
package config;
|
||||
|
||||
import cc.carm.lib.configuration.EasyConfiguration;
|
||||
import cc.carm.lib.configuration.demo.tests.ConfigurationTest;
|
||||
import cc.carm.lib.configuration.json.JSONConfigProvider;
|
||||
import config.model.TestModel;
|
||||
import config.source.DemoConfiguration;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class JSONConfigTest {
|
||||
|
||||
protected final JSONConfigProvider provider = EasyConfiguration.from("target/config.yml", "config.yml");
|
||||
protected final JSONConfigProvider provider = EasyConfiguration.from("target/config.json", "config.json");
|
||||
|
||||
|
||||
@Test
|
||||
public void onTest() {
|
||||
|
||||
provider.initialize(DemoConfiguration.class);
|
||||
ConfigurationTest.testDemo(this.provider);
|
||||
ConfigurationTest.testInner(this.provider);
|
||||
|
||||
testDemo();
|
||||
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("----------------------------------------------------");
|
||||
|
||||
try {
|
||||
provider.save();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void testDemo() {
|
||||
System.out.println("----------------------------------------------------");
|
||||
|
||||
System.out.println("> Test Value:");
|
||||
System.out.println("before: " + DemoConfiguration.Sub.UUID_CONFIG_VALUE.get());
|
||||
DemoConfiguration.Sub.UUID_CONFIG_VALUE.set(UUID.randomUUID());
|
||||
System.out.println("after: " + DemoConfiguration.Sub.UUID_CONFIG_VALUE.get());
|
||||
|
||||
System.out.println("> Test List:");
|
||||
DemoConfiguration.Sub.That.OPERATORS.getNotNull().forEach(System.out::println);
|
||||
List<UUID> operators = IntStream.range(0, 5).mapToObj(i -> UUID.randomUUID()).collect(Collectors.toList());
|
||||
DemoConfiguration.Sub.That.OPERATORS.set(operators);
|
||||
|
||||
System.out.println("> Test Section:");
|
||||
System.out.println(DemoConfiguration.MODEL_TEST.get());
|
||||
DemoConfiguration.MODEL_TEST.set(TestModel.random());
|
||||
|
||||
System.out.println("> Test Maps:");
|
||||
DemoConfiguration.USERS.getNotNull().forEach((k, v) -> System.out.println(k + ": " + v));
|
||||
LinkedHashMap<Integer, UUID> data = new LinkedHashMap<>();
|
||||
for (int i = 1; i <= 5; i++) {
|
||||
data.put(i, UUID.randomUUID());
|
||||
}
|
||||
DemoConfiguration.USERS.set(data);
|
||||
System.out.println("----------------------------------------------------");
|
||||
ConfigurationTest.save(this.provider);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
package config.model;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class SomeModel extends AbstractModel {
|
||||
|
||||
int num;
|
||||
|
||||
public SomeModel(@NotNull String name, int num) {
|
||||
super(name);
|
||||
this.num = num;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SomeModel{" +
|
||||
"name='" + name + '\'' +
|
||||
", num=" + num +
|
||||
'}';
|
||||
}
|
||||
|
||||
public @NotNull Map<String, Object> serialize() {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("name", name);
|
||||
map.put("num", num);
|
||||
return map;
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
public static SomeModel deserialize(Map<String, ?> args) {
|
||||
return new SomeModel((String) args.get("name"), (Integer) args.get("num"));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package config.source;
|
||||
|
||||
import cc.carm.lib.configuration.core.ConfigurationRoot;
|
||||
import cc.carm.lib.configuration.core.annotation.HeaderComment;
|
||||
import cc.carm.lib.configuration.core.annotation.ConfigPath;
|
||||
import cc.carm.lib.configuration.core.value.ConfigValue;
|
||||
import cc.carm.lib.configuration.core.value.type.ConfiguredValue;
|
||||
|
||||
@HeaderComment({"数据库配置", " 用于提供数据库连接,进行数据库操作。"})
|
||||
public class DatabaseConfiguration extends ConfigurationRoot {
|
||||
|
||||
@ConfigPath("driver")
|
||||
protected static final ConfigValue<String> DRIVER_NAME = ConfiguredValue.of(
|
||||
String.class, "com.mysql.cj.jdbc.Driver"
|
||||
);
|
||||
|
||||
protected static final ConfigValue<String> HOST = ConfiguredValue.of(String.class, "127.0.0.1");
|
||||
protected static final ConfigValue<Integer> PORT = ConfiguredValue.of(Integer.class, 3306);
|
||||
|
||||
protected static final ConfigValue<String> DATABASE = ConfiguredValue.of(String.class, "minecraft");
|
||||
protected static final ConfigValue<String> USERNAME = ConfiguredValue.of(String.class, "root");
|
||||
protected static final ConfigValue<String> PASSWORD = ConfiguredValue.of(String.class, "password");
|
||||
|
||||
protected static final ConfigValue<String> EXTRA = ConfiguredValue.of(String.class, "?useSSL=false");
|
||||
|
||||
protected static String buildJDBC() {
|
||||
return String.format("jdbc:mysql://%s:%s/%s%s", HOST.get(), PORT.get(), DATABASE.get(), EXTRA.get());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
package config.source;
|
||||
|
||||
import cc.carm.lib.configuration.core.ConfigurationRoot;
|
||||
import cc.carm.lib.configuration.core.annotation.ConfigPath;
|
||||
import cc.carm.lib.configuration.core.value.ConfigValue;
|
||||
import cc.carm.lib.configuration.core.value.type.ConfiguredList;
|
||||
import cc.carm.lib.configuration.core.value.type.ConfiguredMap;
|
||||
import cc.carm.lib.configuration.core.value.type.ConfiguredSection;
|
||||
import cc.carm.lib.configuration.core.value.type.ConfiguredValue;
|
||||
import config.model.TestModel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public class DemoConfiguration extends ConfigurationRoot {
|
||||
|
||||
@ConfigPath(root = true)
|
||||
protected static final ConfigValue<Double> VERSION = ConfiguredValue.of(Double.class, 1.0D);
|
||||
|
||||
// 可以直接写静态内部类,并通过 Class<?> 声明。
|
||||
public static final Class<?> SUB_TEST = Sub.class;
|
||||
|
||||
@ConfigPath("user") // 通过注解规定配置文件中的路径,若不进行注解则以变量名自动生成。
|
||||
public static final ConfigValue<TestModel> MODEL_TEST = ConfiguredSection
|
||||
.builder(TestModel.class)
|
||||
.defaults(new TestModel("Carm", UUID.randomUUID()))
|
||||
.parseValue((section, defaultValue) -> TestModel.deserialize(section))
|
||||
.serializeValue(TestModel::serialize).build();
|
||||
|
||||
// 子配置文件
|
||||
@ConfigPath("database")
|
||||
public static final Class<?> DB_CONFIG = DatabaseConfiguration.class;
|
||||
|
||||
public static final ConfigValue<Map<Integer, UUID>> USERS = ConfiguredMap
|
||||
.builder(Integer.class, UUID.class).fromString()
|
||||
.parseKey(Integer::parseInt)
|
||||
.parseValue(v -> Objects.requireNonNull(UUID.fromString(v)))
|
||||
.build();
|
||||
|
||||
|
||||
public static class Sub extends ConfigurationRoot {
|
||||
|
||||
@ConfigPath(value = "uuid-value", root = true)
|
||||
public static final ConfigValue<UUID> UUID_CONFIG_VALUE = ConfiguredValue
|
||||
.builder(UUID.class).fromString()
|
||||
.parseValue((data, defaultValue) -> UUID.fromString(data))
|
||||
.build();
|
||||
|
||||
public static final Class<?> NOTHING = That.class;
|
||||
|
||||
public static class That extends ConfigurationRoot {
|
||||
|
||||
public static final ConfigValue<List<UUID>> OPERATORS = ConfiguredList
|
||||
.builder(UUID.class).fromString()
|
||||
.parseValue(s -> Objects.requireNonNull(UUID.fromString(s)))
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<version>3.5.0</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<properties>
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
||||
|
||||
<maven.deploy.skip>true</maven.deploy.skip>
|
||||
</properties>
|
||||
<artifactId>easyconfiguration-sql</artifactId>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>${project.parent.groupId}</groupId>
|
||||
<artifactId>easyconfiguration-core</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,6 @@
|
||||
package cc.carm.lib.configuration;
|
||||
|
||||
public class EasyConfiguration {
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package cc.carm.lib.configuration.sql;
|
||||
|
||||
import cc.carm.lib.configuration.core.ConfigInitializer;
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationComments;
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class SQLConfigProvider extends ConfigurationProvider<SQLSectionWrapper> {
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull SQLSectionWrapper getConfiguration() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onReload() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ConfigurationComments getComments() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ConfigInitializer<? extends ConfigurationProvider<SQLSectionWrapper>> getInitializer() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package cc.carm.lib.configuration.sql;
|
||||
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class SQLSectionWrapper implements ConfigurationWrapper<Map<String, Object>> {
|
||||
|
||||
@Override
|
||||
public @NotNull Map<String, Object> getSource() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<String> getKeys(boolean deep) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Map<String, Object> getValues(boolean deep) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(@NotNull String path, @Nullable Object value) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(@NotNull String path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Object get(@NotNull String path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isList(@NotNull String path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable List<?> getList(@NotNull String path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConfigurationSection(@NotNull String path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable SQLSectionWrapper getConfigurationSection(@NotNull String path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package cc.carm.lib.configuration.sql;
|
||||
|
||||
public class SQLValueParser {
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
CREATE TABLE IF NOT EXISTS conf
|
||||
(
|
||||
`namespace` VARCHAR(255) NOT NULL, # 命名空间
|
||||
`section` VARCHAR(255) NOT NULL, # 配置路径 (ConfigPath)
|
||||
`type` VARCHAR(255) NOT NULL, # 数据类型 (Integer/Byte/List/Map/...)
|
||||
`value` MEDIUMTEXT, # 配置项的值 (可能为JSON格式)
|
||||
`inline_comments` TINYTEXT, # 行内注释
|
||||
`header_comments` TEXT, # 顶部注释
|
||||
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`namespace`, `section`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4;
|
||||
|
||||
+11
-2
@@ -5,13 +5,15 @@
|
||||
<parent>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.5.0</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<properties>
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
||||
</properties>
|
||||
|
||||
<artifactId>easyconfiguration-yaml</artifactId>
|
||||
@@ -26,10 +28,17 @@
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>${project.parent.groupId}</groupId>
|
||||
<artifactId>easyconfiguration-demo</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bspfsystems</groupId>
|
||||
<artifactId>yamlconfiguration</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.3.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -1,60 +1,23 @@
|
||||
package cc.carm.lib.configuration.yaml;
|
||||
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationComments;
|
||||
import org.bspfsystems.yamlconfiguration.configuration.ConfigurationSection;
|
||||
import org.bspfsystems.yamlconfiguration.file.FileConfiguration;
|
||||
import org.bspfsystems.yamlconfiguration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static cc.carm.lib.configuration.yaml.YAMLConfigProvider.SEPARATOR;
|
||||
|
||||
public class YAMLComments {
|
||||
|
||||
protected final @NotNull Map<String, List<String>> headerComments = new HashMap<>();
|
||||
protected final @NotNull Map<String, String> inlineComments = new HashMap<>();
|
||||
|
||||
protected @NotNull Map<String, List<String>> getHeaderComments() {
|
||||
return headerComments;
|
||||
}
|
||||
|
||||
protected @NotNull Map<String, String> getInlineComments() {
|
||||
return inlineComments;
|
||||
}
|
||||
|
||||
public void setHeaderComments(@Nullable String path, @Nullable List<String> comments) {
|
||||
|
||||
if (comments == null) {
|
||||
getHeaderComments().remove(path);
|
||||
} else {
|
||||
getHeaderComments().put(path, comments);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setInlineComment(@NotNull String path, @Nullable String comment) {
|
||||
if (comment == null) {
|
||||
getInlineComments().remove(path);
|
||||
} else {
|
||||
getInlineComments().put(path, comment);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Unmodifiable
|
||||
public List<String> getHeaderComment(@Nullable String path) {
|
||||
return Optional.ofNullable(getHeaderComments().get(path)).map(Collections::unmodifiableList).orElse(null);
|
||||
}
|
||||
|
||||
public @Nullable String getInlineComment(@NotNull String path) {
|
||||
return getInlineComments().get(path);
|
||||
}
|
||||
@SuppressWarnings("SpellCheckingInspection")
|
||||
public class YAMLComments extends ConfigurationComments {
|
||||
|
||||
public @Nullable String buildHeaderComments(@Nullable String path, @NotNull String indents) {
|
||||
List<String> comments = getHeaderComment(path);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package cc.carm.lib.configuration.yaml;
|
||||
|
||||
import cc.carm.lib.configuration.core.ConfigInitializer;
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationComments;
|
||||
import cc.carm.lib.configuration.core.source.impl.FileConfigProvider;
|
||||
import org.bspfsystems.yamlconfiguration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
@@ -13,7 +13,6 @@ import java.io.StringWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
public class YAMLConfigProvider extends FileConfigProvider<YAMLSectionWrapper> {
|
||||
|
||||
@@ -38,11 +37,17 @@ public class YAMLConfigProvider extends FileConfigProvider<YAMLSectionWrapper> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() throws Exception {
|
||||
protected void onReload() throws Exception {
|
||||
configuration.load(getFile());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ConfigurationComments getComments() {
|
||||
return this.comments;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("SpellCheckingInspection")
|
||||
public void save() throws Exception {
|
||||
configuration.save(getFile());
|
||||
|
||||
@@ -60,28 +65,6 @@ public class YAMLConfigProvider extends FileConfigProvider<YAMLSectionWrapper> {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeaderComment(@Nullable String path, @Nullable List<String> comments) {
|
||||
this.comments.setHeaderComments(path, comments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInlineComment(@NotNull String path, @Nullable String comment) {
|
||||
this.comments.setInlineComment(path, comment);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
@Unmodifiable
|
||||
public List<String> getHeaderComment(@Nullable String path) {
|
||||
return this.comments.getHeaderComment(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getInlineComment(@NotNull String path) {
|
||||
return this.comments.getInlineComment(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ConfigInitializer<YAMLConfigProvider> getInitializer() {
|
||||
return this.initializer;
|
||||
|
||||
@@ -12,7 +12,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class YAMLSectionWrapper implements ConfigurationWrapper {
|
||||
public class YAMLSectionWrapper implements ConfigurationWrapper<ConfigurationSection> {
|
||||
|
||||
private final ConfigurationSection section;
|
||||
|
||||
@@ -25,6 +25,11 @@ public class YAMLSectionWrapper implements ConfigurationWrapper {
|
||||
return section == null ? null : new YAMLSectionWrapper(section);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ConfigurationSection getSource() {
|
||||
return this.section;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<String> getKeys(boolean deep) {
|
||||
return new LinkedHashSet<>(section.getKeys(deep));
|
||||
@@ -66,7 +71,7 @@ public class YAMLSectionWrapper implements ConfigurationWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ConfigurationWrapper getConfigurationSection(@NotNull String path) {
|
||||
public @Nullable YAMLSectionWrapper getConfigurationSection(@NotNull String path) {
|
||||
return of(this.section.getConfigurationSection(path));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
package cc.carm.lib.configuration.yaml;
|
||||
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
||||
import cc.carm.lib.configuration.core.value.ValueManifest;
|
||||
import cc.carm.lib.configuration.core.value.impl.CachedConfigValue;
|
||||
import cc.carm.lib.configuration.yaml.builder.YAMLConfigBuilder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class YAMLValue<T> extends CachedConfigValue<T> {
|
||||
|
||||
@@ -14,10 +12,8 @@ public abstract class YAMLValue<T> extends CachedConfigValue<T> {
|
||||
return new YAMLConfigBuilder();
|
||||
}
|
||||
|
||||
public YAMLValue(@Nullable YAMLConfigProvider provider, @Nullable String configPath,
|
||||
@Nullable List<String> headerComments, @Nullable String inlineComments,
|
||||
@Nullable T defaultValue) {
|
||||
super(provider, configPath, headerComments, inlineComments, defaultValue);
|
||||
public YAMLValue(@NotNull ValueManifest<T> manifest) {
|
||||
super(manifest);
|
||||
}
|
||||
|
||||
public YAMLConfigProvider getYAMLProvider() {
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ public class SerializableBuilder<T extends ConfigurationSerializable>
|
||||
|
||||
@Override
|
||||
public @NotNull ConfiguredSerializable<T> build() {
|
||||
return new ConfiguredSerializable<>(this.provider, this.path, this.headerComments, this.inlineComment, this.valueClass, this.defaultValue);
|
||||
return new ConfiguredSerializable<>(buildManifest(), this.valueClass);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+3
-6
@@ -1,12 +1,11 @@
|
||||
package cc.carm.lib.configuration.yaml.value;
|
||||
|
||||
import cc.carm.lib.configuration.yaml.YAMLConfigProvider;
|
||||
import cc.carm.lib.configuration.core.value.ValueManifest;
|
||||
import cc.carm.lib.configuration.yaml.YAMLValue;
|
||||
import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerializable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ConfiguredSerializable<T extends ConfigurationSerializable> extends YAMLValue<T> {
|
||||
@@ -22,10 +21,8 @@ public class ConfiguredSerializable<T extends ConfigurationSerializable> extends
|
||||
|
||||
protected final @NotNull Class<T> valueClass;
|
||||
|
||||
public ConfiguredSerializable(@Nullable YAMLConfigProvider provider, @Nullable String configPath,
|
||||
@Nullable List<String> headerComments, @Nullable String inlineComments,
|
||||
@NotNull Class<T> valueClass, @Nullable T defaultValue) {
|
||||
super(provider, configPath, headerComments, inlineComments, defaultValue);
|
||||
public ConfiguredSerializable(@NotNull ValueManifest<T> manifest, @NotNull Class<T> valueClass) {
|
||||
super(manifest);
|
||||
this.valueClass = valueClass;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
package config;
|
||||
|
||||
import cc.carm.lib.configuration.EasyConfiguration;
|
||||
import cc.carm.lib.configuration.yaml.YAMLConfigProvider;
|
||||
import config.model.AbstractModel;
|
||||
import config.model.SomeModel;
|
||||
import config.model.TestModel;
|
||||
import config.source.DemoConfiguration;
|
||||
import config.source.ImplConfiguration;
|
||||
import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerialization;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class ConfigTester {
|
||||
|
||||
static {
|
||||
ConfigurationSerialization.registerClass(TestModel.class);
|
||||
ConfigurationSerialization.registerClass(SomeModel.class);
|
||||
}
|
||||
|
||||
protected final YAMLConfigProvider provider = EasyConfiguration.from("target/config.yml", "config.yml");
|
||||
|
||||
@Test
|
||||
public void onTest() {
|
||||
provider.initialize(DemoConfiguration.class);
|
||||
|
||||
testDemo();
|
||||
testSerialization();
|
||||
|
||||
try {
|
||||
provider.save();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void testDemo() {
|
||||
System.out.println("----------------------------------------------------");
|
||||
|
||||
System.out.println("> Test Value:");
|
||||
System.out.println("before: " + DemoConfiguration.Sub.UUID_CONFIG_VALUE.get());
|
||||
DemoConfiguration.Sub.UUID_CONFIG_VALUE.set(UUID.randomUUID());
|
||||
System.out.println("after: " + DemoConfiguration.Sub.UUID_CONFIG_VALUE.get());
|
||||
|
||||
System.out.println("> Test List:");
|
||||
DemoConfiguration.Sub.That.OPERATORS.getNotNull().forEach(System.out::println);
|
||||
List<UUID> operators = IntStream.range(0, 5).mapToObj(i -> UUID.randomUUID()).collect(Collectors.toList());
|
||||
DemoConfiguration.Sub.That.OPERATORS.set(operators);
|
||||
|
||||
System.out.println("> Test Section:");
|
||||
System.out.println(DemoConfiguration.MODEL_TEST.get());
|
||||
DemoConfiguration.MODEL_TEST.set(TestModel.random());
|
||||
|
||||
System.out.println("> Test Maps:");
|
||||
DemoConfiguration.USERS.getNotNull().forEach((k, v) -> System.out.println(k + ": " + v));
|
||||
LinkedHashMap<Integer, UUID> data = new LinkedHashMap<>();
|
||||
for (int i = 1; i <= 5; i++) {
|
||||
data.put(i, UUID.randomUUID());
|
||||
}
|
||||
DemoConfiguration.USERS.set(data);
|
||||
System.out.println("----------------------------------------------------");
|
||||
}
|
||||
|
||||
public static void testSerialization() {
|
||||
System.out.println("----------------------------------------------------");
|
||||
AbstractModel model = ImplConfiguration.TEST.get();
|
||||
if (model != null) {
|
||||
System.out.println(model.getName());
|
||||
}
|
||||
System.out.println("----------------------------------------------------");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package config;
|
||||
|
||||
import cc.carm.lib.configuration.EasyConfiguration;
|
||||
import cc.carm.lib.configuration.demo.tests.ConfigurationTest;
|
||||
import cc.carm.lib.configuration.demo.tests.model.AbstractModel;
|
||||
import cc.carm.lib.configuration.yaml.YAMLConfigProvider;
|
||||
import config.model.AnyModel;
|
||||
import config.model.SomeModel;
|
||||
import config.source.ModelConfiguration;
|
||||
import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerialization;
|
||||
import org.junit.Test;
|
||||
|
||||
public class DemoConfigTest {
|
||||
|
||||
static {
|
||||
ConfigurationSerialization.registerClass(SomeModel.class);
|
||||
ConfigurationSerialization.registerClass(AnyModel.class);
|
||||
}
|
||||
|
||||
protected final YAMLConfigProvider provider = EasyConfiguration.from("target/config.yml", "config.yml");
|
||||
|
||||
@Test
|
||||
public void onTest() {
|
||||
ConfigurationTest.testDemo(this.provider);
|
||||
ConfigurationTest.testInner(this.provider);
|
||||
|
||||
testSerialization(this.provider);
|
||||
|
||||
ConfigurationTest.save(this.provider);
|
||||
}
|
||||
|
||||
|
||||
public static void testSerialization(YAMLConfigProvider provider) {
|
||||
provider.initialize(ModelConfiguration.class);
|
||||
System.out.println("----------------------------------------------------");
|
||||
|
||||
AbstractModel someModel = ModelConfiguration.SOME_MODEL.get();
|
||||
if (someModel != null) System.out.println(someModel.getName());
|
||||
|
||||
AbstractModel anyModel = ModelConfiguration.ANY_MODEL.get();
|
||||
if (anyModel != null) System.out.println(anyModel.getName());
|
||||
|
||||
System.out.println("----------------------------------------------------");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package config;
|
||||
|
||||
import config.offset.FieldOffset;
|
||||
import config.offset.OffsetUtil;
|
||||
import config.source.DemoConfiguration;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class OffsetTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
//
|
||||
// output(OffsetUtil.getClassMemberOffset(DemoConfiguration.class));
|
||||
// output(OffsetUtil.getClassMemberOffset(DemoConfiguration.Sub.class));
|
||||
|
||||
}
|
||||
|
||||
protected static void output(List<FieldOffset> fieldOffsets) {
|
||||
for (FieldOffset fieldOffset : fieldOffsets) {
|
||||
System.out.println(fieldOffset.getOffsetValue() + " -> " + fieldOffset);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package config.model;
|
||||
|
||||
import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerializable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public abstract class AbstractModel implements ConfigurationSerializable {
|
||||
|
||||
protected final @NotNull String name;
|
||||
|
||||
public AbstractModel(@NotNull String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public @NotNull String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package config.model;
|
||||
|
||||
import cc.carm.lib.configuration.demo.tests.model.AbstractModel;
|
||||
import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerializable;
|
||||
import org.bspfsystems.yamlconfiguration.serialization.SerializableAs;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@SerializableAs("AnyModel")
|
||||
public class AnyModel extends AbstractModel implements ConfigurationSerializable {
|
||||
|
||||
public final boolean bool;
|
||||
|
||||
public AnyModel(@NotNull String name, boolean bool) {
|
||||
super(name);
|
||||
this.bool = bool;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AnyModel{" +
|
||||
"name='" + name + '\'' +
|
||||
", bool=" + bool +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Map<String, Object> serialize() {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("name", name);
|
||||
map.put("state", bool);
|
||||
return map;
|
||||
}
|
||||
|
||||
public static AnyModel random() {
|
||||
return new AnyModel(UUID.randomUUID().toString().substring(0, 5), Math.random() > 0.5);
|
||||
}
|
||||
|
||||
|
||||
@TestOnly
|
||||
public static AnyModel deserialize(Map<String, ?> args) {
|
||||
return new AnyModel((String) args.get("name"), (Boolean) args.get("state"));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package config.model;
|
||||
|
||||
import cc.carm.lib.configuration.demo.tests.model.AbstractModel;
|
||||
import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerializable;
|
||||
import org.bspfsystems.yamlconfiguration.serialization.SerializableAs;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -7,11 +8,12 @@ import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@SerializableAs("SomeModel")
|
||||
public class SomeModel extends AbstractModel implements ConfigurationSerializable {
|
||||
|
||||
int num;
|
||||
public final int num;
|
||||
|
||||
public SomeModel(@NotNull String name, int num) {
|
||||
super(name);
|
||||
@@ -34,6 +36,11 @@ public class SomeModel extends AbstractModel implements ConfigurationSerializabl
|
||||
return map;
|
||||
}
|
||||
|
||||
public static SomeModel random() {
|
||||
return new SomeModel(UUID.randomUUID().toString().substring(0, 5), (int) (Math.random() * 1000));
|
||||
}
|
||||
|
||||
|
||||
@TestOnly
|
||||
public static SomeModel deserialize(Map<String, ?> args) {
|
||||
return new SomeModel((String) args.get("name"), (Integer) args.get("num"));
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
package config.model;
|
||||
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
||||
import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerializable;
|
||||
import org.bspfsystems.yamlconfiguration.serialization.SerializableAs;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@SerializableAs("TestModel")
|
||||
public class TestModel extends AbstractModel implements ConfigurationSerializable {
|
||||
|
||||
public UUID uuid;
|
||||
|
||||
public TestModel(String name, UUID uuid) {
|
||||
super(name);
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public void setUuid(UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Map<String, Object> serialize() {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("name", name);
|
||||
Map<String, Object> map2 = new HashMap<>();
|
||||
map2.put("uuid", uuid.toString());
|
||||
map.put("info", map2);
|
||||
return map;
|
||||
}
|
||||
|
||||
public static TestModel deserialize(ConfigurationWrapper section) {
|
||||
String name = section.getString("name");
|
||||
if (name == null) throw new NullPointerException("name is null");
|
||||
String uuidString = section.getString("info.uuid");
|
||||
if (uuidString == null) throw new NullPointerException("uuid is null");
|
||||
return new TestModel(name, UUID.fromString(uuidString));
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
@SuppressWarnings("unchecked")
|
||||
public static TestModel deserialize(Map<String, ?> args) {
|
||||
String name = (String) args.get("name");
|
||||
if (name == null) throw new NullPointerException("name is null");
|
||||
Map<String, ?> map = (Map<String, ?>) args.get("info");
|
||||
String uuidString = (String) map.get("uuid");
|
||||
if (uuidString == null) throw new NullPointerException("uuid is null");
|
||||
return new TestModel(name, UUID.fromString(uuidString));
|
||||
}
|
||||
|
||||
public static TestModel random() {
|
||||
return new TestModel(UUID.randomUUID().toString().substring(0, 5), UUID.randomUUID());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TestUser{" +
|
||||
"name='" + name + '\'' +
|
||||
", uuid=" + uuid +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package config.offset;
|
||||
|
||||
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Chris2018998
|
||||
*/
|
||||
public class OffsetUtil {
|
||||
private static Unsafe unsafe;
|
||||
|
||||
static {
|
||||
try {
|
||||
// 获取 Unsafe 内部的私有的实例化单例对象
|
||||
Field field = Unsafe.class.getDeclaredField("theUnsafe");
|
||||
// 无视权限
|
||||
field.setAccessible(true);
|
||||
unsafe = (Unsafe) field.get(null);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// try {
|
||||
// unsafe = AccessController.doPrivileged((PrivilegedExceptionAction<Unsafe>) () -> {
|
||||
// Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
|
||||
// theUnsafe.setAccessible(true);
|
||||
// return (Unsafe) theUnsafe.get(null);
|
||||
// });
|
||||
// } catch (Throwable e) {
|
||||
// System.err.println("Unable to load unsafe");
|
||||
// }
|
||||
}
|
||||
|
||||
public static List<FieldOffset> getClassMemberOffset(Class<?> beanClass) {
|
||||
List<FieldOffset> offsetsList = new LinkedList<>();
|
||||
for (Field field : beanClass.getDeclaredFields()) {
|
||||
FieldOffset fieldOffset = new FieldOffset(field);
|
||||
offsetsList.add(fieldOffset);
|
||||
if (Modifier.isStatic(field.getModifiers()))
|
||||
fieldOffset.setOffsetValue(unsafe.staticFieldOffset(field));
|
||||
else
|
||||
fieldOffset.setOffsetValue(unsafe.objectFieldOffset(field));
|
||||
Class<?> fieldType = field.getType();
|
||||
if (!fieldType.getName().startsWith("java")) {
|
||||
Field[] subfields = fieldType.getDeclaredFields();
|
||||
if (subfields.length > 0) {
|
||||
fieldOffset.setSubFieldOffsetList(getClassMemberOffset(fieldType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Collections.sort(offsetsList);
|
||||
return offsetsList;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
package config.source;
|
||||
|
||||
import cc.carm.lib.configuration.core.ConfigurationRoot;
|
||||
import cc.carm.lib.configuration.core.annotation.ConfigPath;
|
||||
import cc.carm.lib.configuration.core.value.ConfigValue;
|
||||
import cc.carm.lib.configuration.yaml.value.ConfiguredSerializable;
|
||||
import config.model.AbstractModel;
|
||||
import config.model.TestModel;
|
||||
|
||||
@ConfigPath(root = true)
|
||||
public class ImplConfiguration extends ConfigurationRoot {
|
||||
|
||||
public static final ConfigValue<? extends AbstractModel> TEST = ConfiguredSerializable.of(
|
||||
TestModel.class, TestModel.random()
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package config.source;
|
||||
|
||||
import cc.carm.lib.configuration.core.ConfigurationRoot;
|
||||
import cc.carm.lib.configuration.core.annotation.ConfigPath;
|
||||
import cc.carm.lib.configuration.core.value.ConfigValue;
|
||||
import cc.carm.lib.configuration.demo.tests.model.AbstractModel;
|
||||
import cc.carm.lib.configuration.yaml.value.ConfiguredSerializable;
|
||||
import config.model.AnyModel;
|
||||
import config.model.SomeModel;
|
||||
|
||||
@ConfigPath("model-test")
|
||||
public class ModelConfiguration extends ConfigurationRoot {
|
||||
|
||||
public static final ConfigValue<? extends AbstractModel> SOME_MODEL = ConfiguredSerializable.of(
|
||||
SomeModel.class, SomeModel.random()
|
||||
);
|
||||
|
||||
public static final ConfigValue<? extends AbstractModel> ANY_MODEL = ConfiguredSerializable.of(
|
||||
AnyModel.class, AnyModel.random()
|
||||
);
|
||||
|
||||
}
|
||||
@@ -15,11 +15,13 @@
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>3.0.0</version>
|
||||
<version>3.5.0</version>
|
||||
<modules>
|
||||
<module>core</module>
|
||||
<module>demo</module>
|
||||
<module>impl/yaml</module>
|
||||
<module>impl/json</module>
|
||||
<module>impl/sql</module>
|
||||
</modules>
|
||||
|
||||
<name>EasyConfiguration</name>
|
||||
@@ -90,7 +92,7 @@
|
||||
<downloadUrl>https://github.com/CarmJos/EasyConfiguration/releases</downloadUrl>
|
||||
<site>
|
||||
<id>javadoc</id>
|
||||
<name>EasyConfiguration JavaDoc (on Github Pages)</name>
|
||||
<name>EasyConfiguration JavaDoc (on GitHub Pages)</name>
|
||||
<url>https://CarmJos.github.io/EasyConfiguration</url>
|
||||
</site>
|
||||
</distributionManagement>
|
||||
@@ -107,7 +109,7 @@
|
||||
<dependency>
|
||||
<groupId>org.jetbrains</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
<version>23.0.0</version>
|
||||
<version>24.0.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -120,7 +122,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.2</version>
|
||||
<version>3.0.0</version>
|
||||
<configuration>
|
||||
<useSystemClassLoader>false</useSystemClassLoader>
|
||||
</configuration>
|
||||
@@ -164,7 +166,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.4.0</version>
|
||||
<version>3.5.0</version>
|
||||
<configuration>
|
||||
<classifier>javadoc</classifier>
|
||||
<detectJavaApiLink>false</detectJavaApiLink>
|
||||
@@ -191,7 +193,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.10.1</version>
|
||||
<version>3.11.0</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
@@ -203,7 +205,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.2.2</version>
|
||||
<version>3.3.0</version>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
@@ -223,7 +225,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<version>3.4.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
|
||||
Reference in New Issue
Block a user