1
mirror of https://github.com/CarmJos/EasyConfiguration.git synced 2024-09-19 20:25:51 +00:00

完成新Initializer,以支持配置文件内容的顺序加载。

This commit is contained in:
Carm Jos 2022-04-21 06:40:32 +08:00
parent 132ca81635
commit 4b7a7aeae7
13 changed files with 242 additions and 212 deletions

View File

@ -8,8 +8,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Optional;
public class ConfigInitializer<T extends ConfigurationProvider<?>> {
@ -19,94 +17,116 @@ public class ConfigInitializer<T extends ConfigurationProvider<?>> {
this.provider = provider;
}
public void initialize(Class<? extends ConfigurationRoot> rootClazz) {
initialize(rootClazz, true);
public void initialize(@NotNull Class<? extends ConfigurationRoot> clazz, boolean saveDefaults) {
initializeClass(clazz, null, null, null, null, saveDefaults);
}
public void initialize(Class<? extends ConfigurationRoot> rootClazz, boolean saveDefault) {
String rootSection = null;
ConfigPath sectionAnnotation = rootClazz.getAnnotation(ConfigPath.class);
if (sectionAnnotation != null && sectionAnnotation.value().length() > 1) {
rootSection = sectionAnnotation.value();
protected void initializeClass(@NotNull Class<?> clazz,
@Nullable String parentPath, @Nullable String fieldName,
@Nullable ConfigPath fieldPath, @Nullable ConfigComment filedComments,
boolean saveDefaults) {
if (!ConfigurationRoot.class.isAssignableFrom(clazz)) return;
String path = getClassPath(clazz, parentPath, fieldName, fieldPath);
if (path != null) setComments(path, getClassComments(clazz, filedComments));
for (Field field : clazz.getDeclaredFields()) {
initializeField(clazz, field, path, saveDefaults);
}
if (rootSection != null) {
//Not usable for null section.
ConfigComment comments = rootClazz.getAnnotation(ConfigComment.class);
if (comments != null && comments.value().length > 0) {
provider.setComments(rootSection, comments.value());
}
}
for (Class<?> innerClass : rootClazz.getDeclaredClasses()) {
initSection(rootSection, innerClass, saveDefault);
}
for (Field field : rootClazz.getDeclaredFields()) {
initValue(rootSection, rootClazz, field, saveDefault);
}
if (saveDefault) {
try {
provider.save();
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void initSection(String parentSection, Class<?> clazz, boolean saveDefault) {
if (!Modifier.isStatic(clazz.getModifiers()) || !Modifier.isPublic(clazz.getModifiers())) return;
String section = getSectionPath(clazz.getSimpleName(), parentSection, clazz.getAnnotation(ConfigPath.class));
ConfigComment comments = clazz.getAnnotation(ConfigComment.class);
if (comments != null && comments.value().length > 0) {
provider.setComments(parentSection, comments.value());
}
for (Field field : clazz.getDeclaredFields()) initValue(section, clazz, field, saveDefault);
for (Class<?> innerClass : clazz.getDeclaredClasses()) initSection(section, innerClass, saveDefault);
protected void initializeValue(@NotNull ConfigValue<?> value, @NotNull String path,
@NotNull String[] comments, boolean saveDefaults) {
value.initialize(provider, saveDefaults, path, comments);
}
private void initValue(String parentSection, Class<?> clazz, Field field, boolean saveDefault) {
private void initializeField(@NotNull Class<?> source, @NotNull Field field,
@Nullable String parent, boolean saveDefaults) {
try {
field.setAccessible(true);
Object object = field.get(clazz);
Object object = field.get(source);
if (object instanceof ConfigValue<?>) {
initializeValue(
(ConfigValue<?>) object, saveDefault,
getSectionPath(field.getName(), parentSection, field.getAnnotation(ConfigPath.class)),
Optional.ofNullable(field.getAnnotation(ConfigComment.class))
.map(ConfigComment::value).orElse(new String[0])
String path = getFieldPath(field, parent);
String[] comments = readComments(field.getAnnotation(ConfigComment.class));
initializeValue((ConfigValue<?>) object, path, comments, saveDefaults);
setComments(path, comments);
} else if (object instanceof Class<?>) {
initializeClass(
(Class<?>) object, parent, field.getName(),
field.getAnnotation(ConfigPath.class),
field.getAnnotation(ConfigComment.class),
saveDefaults
);
}
} catch (IllegalAccessException ignored) {
}
}
public void initializeValue(@NotNull ConfigValue<?> value, boolean saveDefault,
@NotNull String path, @NotNull String[] comments) {
value.initialize(provider, path, comments);
if (saveDefault && value.getDefaultValue() != null && !provider.getConfiguration().contains(path)) {
value.setDefault();
}
protected void setComments(@NotNull String path, @Nullable ConfigComment filedComments) {
setComments(path, readComments(filedComments));
}
public static String getSectionPath(@NotNull String name,
@Nullable String parentSection,
@Nullable ConfigPath pathAnnotation) {
@NotNull String parent = parentSection != null ? parentSection + "." : "";
@NotNull String path = getSectionName(name);
boolean root = false;
if (pathAnnotation != null) {
if (pathAnnotation.value().length() > 0) path = pathAnnotation.value();
root = pathAnnotation.root();
protected void setComments(@NotNull String path, @NotNull String[] comments) {
if (comments.length <= 0) return;
this.provider.setComments(path, comments);
}
protected static @NotNull String[] readComments(@Nullable ConfigComment filedComments) {
if (filedComments == null) return new String[0];
if (String.join("", filedComments.value()).length() <= 0) return new String[0];
return filedComments.value();
}
protected static @NotNull String[] getClassComments(@NotNull Class<?> clazz,
@Nullable ConfigComment fieldAnnotation) {
String[] clazzComments = readComments(clazz.getAnnotation(ConfigComment.class));
if (clazzComments.length > 0) return clazzComments;
else return readComments(fieldAnnotation);
}
protected static @Nullable String getClassPath(@NotNull Class<?> clazz,
@Nullable String parentPath,
@Nullable String filedName,
@Nullable ConfigPath fieldAnnotation) {
@NotNull String parent = parentPath != null ? parentPath + "." : "";
boolean fromRoot = false;
// 先获取 Class 对应的路径注解 其优先度最高
ConfigPath clazzAnnotation = clazz.getAnnotation(ConfigPath.class);
if (clazzAnnotation != null) {
fromRoot = clazzAnnotation.root();
if (clazzAnnotation.value().length() > 0) {
return (fromRoot ? "" : parent) + clazzAnnotation.value();
}
}
return (root ? "" : parent) + path;
if (fieldAnnotation != null) {
fromRoot = fromRoot || fieldAnnotation.root();
if (fieldAnnotation.value().length() > 0) {
return (fromRoot ? "" : parent) + fieldAnnotation.value();
}
}
// 再由 fieldName 获取路径
if (filedName != null) return (fromRoot ? "" : parent) + getPathFromName(filedName);
else return null; // 不满足上述条件 fieldName则说明是根路径
}
protected static @NotNull String getFieldPath(@NotNull Field field, @Nullable String parentPath) {
@NotNull String parent = parentPath != null ? parentPath + "." : "";
boolean fromRoot = false;
// 先获取 Field 对应的路径注解 其优先度最高
ConfigPath pathAnnotation = field.getAnnotation(ConfigPath.class);
if (pathAnnotation != null) {
fromRoot = pathAnnotation.root();
if (pathAnnotation.value().length() > 0) {
return (fromRoot ? "" : parent) + pathAnnotation.value();
}
}
// 最后再通过 fieldName 自动生成路径
return (fromRoot ? "" : parent) + getPathFromName(field.getName());
}
/**
@ -116,7 +136,7 @@ public class ConfigInitializer<T extends ConfigurationProvider<?>> {
* @param name 源名称
* @return 全小写-链接 路径名称
*/
public static String getSectionName(String name) {
public static String getPathFromName(String name) {
return name.replaceAll("[A-Z]", "-$0") // 将驼峰转换为蛇形;
.replaceAll("-(.*)", "$1") // 若首字母也为大写则也会被转换需要去掉第一个横线
.replaceAll("_-([A-Z])", "_$1") // 因为命名中可能包含 _因此需要被特殊处理一下

View File

@ -16,7 +16,7 @@ public @interface ConfigPath {
/**
* 指定路径的值
* 若不指定则会通过 {@link ConfigInitializer#getSectionName(String)}自动生成当前路径的值
* 若不指定则会通过 {@link ConfigInitializer#getPathFromName(String)} 自动生成当前路径的值
*
* @return 路径的值
*/

View File

@ -34,7 +34,11 @@ public abstract class ConfigurationProvider<W extends ConfigurationWrapper> {
public abstract @NotNull ConfigInitializer<? extends ConfigurationProvider<W>> getInitializer();
public void initialize(Class<? extends ConfigurationRoot> configClazz) {
getInitializer().initialize(configClazz, true);
initialize(configClazz, true);
}
public void initialize(Class<? extends ConfigurationRoot> configClazz, boolean saveDefaults) {
getInitializer().initialize(configClazz, saveDefaults);
}
}

View File

@ -29,13 +29,12 @@ public abstract class ConfigValue<T> {
this.defaultValue = defaultValue;
}
public void initialize(@NotNull ConfigurationProvider<?> provider, @NotNull String configPath, @NotNull String... comments) {
public void initialize(@NotNull ConfigurationProvider<?> provider, boolean saveDefault,
@NotNull String configPath, @NotNull String... comments) {
if (this.provider == null) this.provider = provider;
if (this.configPath == null) this.configPath = configPath;
if (this.comments.length == 0) this.comments = comments;
this.provider.setComments(this.configPath, this.comments);
get();
if (saveDefault) setDefault();
}
public @Nullable T getDefaultValue() {
@ -63,6 +62,11 @@ public abstract class ConfigValue<T> {
public abstract void set(@Nullable T value);
public void setDefault() {
setDefault(false);
}
public void setDefault(boolean override) {
if (!override && getConfiguration().contains(getConfigPath())) return;
Optional.ofNullable(getDefaultValue()).ifPresent(this::set);
}

View File

@ -7,10 +7,10 @@ public class NameTest {
@Test
public void onTest() {
System.out.println(ConfigInitializer.getSectionName("LoveGames")); // -> love-games
System.out.println(ConfigInitializer.getSectionName("EASY_GAME")); // -> easy-game
System.out.println(ConfigInitializer.getSectionName("F")); //-? f
System.out.println(ConfigInitializer.getSectionName("Test123123")); // -? test123123123
System.out.println(ConfigInitializer.getPathFromName("LoveGames")); // -> love-games
System.out.println(ConfigInitializer.getPathFromName("EASY_GAME")); // -> easy-game
System.out.println(ConfigInitializer.getPathFromName("F")); //-? f
System.out.println(ConfigInitializer.getPathFromName("Test123123")); // -? test123123123
}

View File

@ -15,7 +15,7 @@ public class ConfiguredSerializable<T extends ConfigurationSerializable> extends
}
public static <V extends ConfigurationSerializable> ConfiguredSerializable<V> of(@NotNull Class<V> valueClass,
@Nullable V defaultValue) {
@Nullable V defaultValue) {
return builder().ofSerializable(valueClass).defaults(defaultValue).build();
}

View File

@ -5,7 +5,6 @@ import cc.carm.lib.configuration.yaml.YamlConfigProvider;
import config.model.AbstractModel;
import config.model.SomeModel;
import config.model.TestModel;
import config.source.ComplexConfiguration;
import config.source.DemoConfiguration;
import config.source.ImplConfiguration;
import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerialization;
@ -13,24 +12,25 @@ import org.junit.Test;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Optional;
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() {
ConfigurationSerialization.registerClass(TestModel.class);
ConfigurationSerialization.registerClass(SomeModel.class);
provider.initialize(DemoConfiguration.class);
YamlConfigProvider provider = EasyConfiguration.from("target/config.yml", "config.yml");
testDemo(provider);
testComplex(provider);
testSerialization(provider);
testDemo();
testSerialization();
try {
provider.save();
@ -40,53 +40,40 @@ public class ConfigTester {
}
public static void testSerialization(YamlConfigProvider provider) {
public static void testDemo() {
System.out.println("----------------------------------------------------");
provider.initialize(ImplConfiguration.class);
System.out.println(ImplConfiguration.TEST.get());
ImplConfiguration.TEST.set(TestModel.random());
AbstractModel model = provider.getConfiguration().getSerializable("ImplConfiguration.test", TestModel.class);
provider.getConfiguration().set("ImplConfiguration.some", new SomeModel("lover", 123));
AbstractModel model2 = provider.getConfiguration().getSerializable("ImplConfiguration.some", SomeModel.class);
System.out.println("model1: " + Optional.ofNullable(model).map(AbstractModel::getName).orElse(null));
System.out.println("model1: " + Optional.ofNullable(model2).map(AbstractModel::getName).orElse(null));
System.out.println("----------------------------------------------------");
}
public static void testDemo(YamlConfigProvider provider) {
provider.initialize(DemoConfiguration.class);
}
public static void testComplex(YamlConfigProvider provider) {
System.out.println("----------------------------------------------------");
provider.initialize(ComplexConfiguration.class);
System.out.println("> Test Value:");
System.out.println("before: " + ComplexConfiguration.Sub.UUID_CONFIG_VALUE.get());
ComplexConfiguration.Sub.UUID_CONFIG_VALUE.set(UUID.randomUUID());
System.out.println("after: " + ComplexConfiguration.Sub.UUID_CONFIG_VALUE.get());
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:");
ComplexConfiguration.Sub.That.Operators.getNotNull().forEach(System.out::println);
DemoConfiguration.Sub.That.OPERATORS.getNotNull().forEach(System.out::println);
List<UUID> operators = IntStream.range(0, 5).mapToObj(i -> UUID.randomUUID()).collect(Collectors.toList());
ComplexConfiguration.Sub.That.Operators.set(operators);
DemoConfiguration.Sub.That.OPERATORS.set(operators);
System.out.println("> Test Section:");
System.out.println(ComplexConfiguration.USER.get());
ComplexConfiguration.USER.set(TestModel.random());
System.out.println(DemoConfiguration.MODEL_TEST.get());
DemoConfiguration.MODEL_TEST.set(TestModel.random());
System.out.println("> Test Maps:");
ComplexConfiguration.USERS.getNotNull().forEach((k, v) -> System.out.println(k + ": " + v));
DemoConfiguration.USERS.getNotNull().forEach((k, v) -> System.out.println(k + ": " + v));
LinkedHashMap<Integer, UUID> data = new LinkedHashMap<>();
for (int i = 0; i < 5; i++) {
data.put((int) (1000 * Math.random()), UUID.randomUUID());
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());
}
ComplexConfiguration.USERS.set(data);
System.out.println("----------------------------------------------------");
}

View File

@ -1,18 +1,21 @@
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() {
@Test
public void test() {
//
// output(OffsetUtil.getClassMemberOffset(ComplexConfiguration.class));
// output(OffsetUtil.getClassMemberOffset(ComplexConfiguration.Sub.class));
//
// }
// output(OffsetUtil.getClassMemberOffset(DemoConfiguration.class));
// output(OffsetUtil.getClassMemberOffset(DemoConfiguration.Sub.class));
}
protected static void output(List<FieldOffset> fieldOffsets) {
for (FieldOffset fieldOffset : fieldOffsets) {

View File

@ -1,8 +1,9 @@
package config.model;
import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerializable;
import org.jetbrains.annotations.NotNull;
public abstract class AbstractModel {
public abstract class AbstractModel implements ConfigurationSerializable {
protected final @NotNull String name;

View File

@ -1,56 +0,0 @@
package config.source;
import cc.carm.lib.configuration.core.ConfigurationRoot;
import cc.carm.lib.configuration.core.annotation.ConfigComment;
import cc.carm.lib.configuration.core.annotation.ConfigPath;
import cc.carm.lib.configuration.core.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 ComplexConfiguration extends ConfigurationRoot {
@ConfigComment({"User测试"})
public static final ConfigValue<TestModel> USER = ConfiguredSection
.builder(TestModel.class)
.defaults(new TestModel("Carm", UUID.randomUUID()))
.parseValue((section, defaultValue) -> TestModel.deserialize(section))
.serializeValue(TestModel::serialize).build();
@ConfigComment({"[ID-UUID] 对照表", "", "用于测试Map类型的解析与序列化保存"})
public static final ConfigValue<Map<Integer, UUID>> USERS = ConfiguredMap
.builder(Integer.class, UUID.class).fromString()
.parseKey(Integer::parseInt)
.parseValue(v -> Objects.requireNonNull(UUID.fromString(v)))
.build();
public static class Sub {
@ConfigPath(value = "uuid", root = true)
public static final ConfigValue<UUID> UUID_CONFIG_VALUE = ConfiguredValue
.builder(UUID.class).fromString()
.parseValue((data, defaultValue) -> UUID.fromString(data))
.build();
@ConfigPath("nothing")
public static class That {
public static final ConfigValue<List<UUID>> Operators = ConfiguredList
.builder(UUID.class).fromString()
.parseValue(s -> Objects.requireNonNull(UUID.fromString(s)))
.build();
}
}
}

View File

@ -0,0 +1,35 @@
package config.source;
import cc.carm.lib.configuration.core.ConfigurationRoot;
import cc.carm.lib.configuration.core.annotation.ConfigComment;
import cc.carm.lib.configuration.core.annotation.ConfigPath;
import cc.carm.lib.configuration.core.value.ConfigValue;
import cc.carm.lib.configuration.core.value.type.ConfiguredValue;
@ConfigComment({"数据库配置", " 用于提供数据库连接,进行数据库操作。"})
public class DatabaseConfiguration extends ConfigurationRoot {
@ConfigPath("driver")
@ConfigComment({
"数据库驱动配置,请根据数据库类型设置。",
"- MySQL: com.mysql.cj.jdbc.Driver",
"- MariaDB(推荐): org.mariadb.jdbc.Driver",
})
protected static final ConfigValue<String> DRIVER_NAME = ConfiguredValue.of(
String.class, "com.mysql.cj.jdbc.Driver"
);
protected static final ConfigValue<String> HOST = ConfiguredValue.of(String.class, "127.0.0.1");
protected static final ConfigValue<Integer> PORT = ConfiguredValue.of(Integer.class, 3306);
protected static final ConfigValue<String> DATABASE = ConfiguredValue.of(String.class, "minecraft");
protected static final ConfigValue<String> USERNAME = ConfiguredValue.of(String.class, "root");
protected static final ConfigValue<String> PASSWORD = ConfiguredValue.of(String.class, "password");
protected static final ConfigValue<String> EXTRA = ConfiguredValue.of(String.class, "?useSSL=false");
protected static String buildJDBC() {
return String.format("jdbc:mysql://%s:%s/%s%s", HOST.get(), PORT.get(), DATABASE.get(), EXTRA.get());
}
}

View File

@ -4,10 +4,17 @@ import cc.carm.lib.configuration.core.ConfigurationRoot;
import cc.carm.lib.configuration.core.annotation.ConfigComment;
import cc.carm.lib.configuration.core.annotation.ConfigPath;
import cc.carm.lib.configuration.core.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;
@ConfigPath("database")
@ConfigComment({"数据库配置", " 用于提供数据库连接,进行数据库操作。"})
public class DemoConfiguration extends ConfigurationRoot {
@ConfigPath(root = true)
@ -19,29 +26,53 @@ public class DemoConfiguration extends ConfigurationRoot {
protected static final ConfigValue<Double> VERSION = ConfiguredValue.of(Double.class, 1.0D);
@ConfigPath("driver")
@ConfigComment({
"数据库驱动配置,请根据数据库类型设置。",
"- MySQL: com.mysql.cj.jdbc.Driver",
"- MariaDB(推荐): org.mariadb.jdbc.Driver",
})
protected static final ConfigValue<String> DRIVER_NAME = ConfiguredValue.of(
String.class, "com.mysql.cj.jdbc.Driver"
);
// 注意 若对应类也有注解则优先使用类的注解
@ConfigPath("impl-test") //支持通过注解修改子配置的主路径若不修改则以变量名自动生成
@ConfigComment("Something...") // 支持给子路径直接打注释
public static final Class<?> IMPL = ImplConfiguration.class;
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);
// 可以直接写静态内部类并通过 Class<?> 声明
public static final Class<?> SUB_TEST = Sub.class;
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");
@ConfigPath("user") // 通过注解规定配置文件中的路径若不进行注解则以变量名自动生成
@ConfigComment({"Section类型数据测试"}) // 通过注解给配置添加注释
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();
protected static final ConfigValue<String> EXTRA = ConfiguredValue.of(String.class, "?useSSL=false");
// 子配置文件
@ConfigPath("database")
public static final Class<?> DB_CONFIG = DatabaseConfiguration.class;
@ConfigComment({"[ID-UUID] 对照表", "", "用于测试Map类型的解析与序列化保存"})
public static final ConfigValue<Map<Integer, UUID>> USERS = ConfiguredMap
.builder(Integer.class, UUID.class).fromString()
.parseKey(Integer::parseInt)
.parseValue(v -> Objects.requireNonNull(UUID.fromString(v)))
.build();
public static class Sub 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 = Sub.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();
}
protected static String buildJDBC() {
return String.format("jdbc:mysql://%s:%s/%s%s",
HOST.get(), PORT.get(), DATABASE.get(), EXTRA.get()
);
}

View File

@ -4,12 +4,13 @@ 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("ImplConfiguration")
@ConfigPath(root = true)
public class ImplConfiguration extends ConfigurationRoot {
public static final ConfigValue<TestModel> TEST = ConfiguredSerializable.of(TestModel.class);
public static final ConfigValue<? extends AbstractModel> TEST = ConfiguredSerializable.of(TestModel.class, TestModel.random());
}