1
mirror of https://github.com/CarmJos/EasyConfiguration.git synced 2026-06-04 10:38:19 +08:00

feat(json): Finished json version's provider

This commit is contained in:
2025-02-13 01:30:10 +08:00
parent 05ff61a9d9
commit 79f59bafe6
20 changed files with 125 additions and 95 deletions
@@ -14,7 +14,7 @@ public @interface ConfigPath {
/** /**
* The path value of the current configuration. * The path value of the current configuration.
* If not set,will generate the path by {@link PathGenerator}. * If not set,will generate the path by {@link cc.carm.lib.configuration.source.loader.PathGenerator}.
* *
* @return The path value of the current configuration * @return The path value of the current configuration
*/ */
@@ -41,7 +41,7 @@ public abstract class AbstractConfigBuilder<
public abstract @NotNull RESULT build(); public abstract @NotNull RESULT build();
public @NotNull SELF provider(@Nullable PROVIDER provider) { public @NotNull SELF holder(@Nullable PROVIDER provider) {
this.provider = provider; this.provider = provider;
return self(); return self();
} }
@@ -83,29 +83,31 @@ public class ConfigurationInitializer {
} }
public @Nullable String getFieldPath(ConfigurationHolder<?> holder, @Nullable String parentPath, @NotNull Field field) { public @Nullable String getFieldPath(@NotNull ConfigurationHolder<?> holder, @Nullable String parentPath, @NotNull Field field) {
return pathGenerator.getFieldPath(holder, parentPath, field); return pathGenerator.getFieldPath(holder, parentPath, field);
} }
public @Nullable String getClassPath(ConfigurationHolder<?> holder, @Nullable String parentPath, public @Nullable String getClassPath(@NotNull ConfigurationHolder<?> holder, @Nullable String parentPath,
@NotNull Class<?> clazz, @Nullable Field clazzField) { @NotNull Class<?> clazz, @Nullable Field clazzField) {
return pathGenerator.getClassPath(holder, parentPath, clazz, clazzField); return pathGenerator.getClassPath(holder, parentPath, clazz, clazzField);
} }
public void initialize(ConfigurationHolder<?> holder, @NotNull Configuration config) throws Exception { public void initialize(@NotNull ConfigurationHolder<?> holder,
@NotNull Configuration config) throws Exception {
initializeInstance(holder, config, null, null); initializeInstance(holder, config, null, null);
if (holder.options().get(StandardOptions.SET_DEFAULTS)) holder.save(); if (holder.options().get(StandardOptions.SET_DEFAULTS)) holder.save();
} }
public void initialize(ConfigurationHolder<?> holder, @NotNull Class<? extends Configuration> clazz) throws Exception { public void initialize(@NotNull ConfigurationHolder<?> holder,
@NotNull Class<? extends Configuration> clazz) throws Exception {
initializeStaticClass(holder, clazz, null, null); initializeStaticClass(holder, clazz, null, null);
if (holder.options().get(StandardOptions.SET_DEFAULTS)) holder.save(); if (holder.options().get(StandardOptions.SET_DEFAULTS)) holder.save();
} }
// 针对实例类的初始化方法 // 针对实例类的初始化方法
protected void initializeInstance(@NotNull ConfigurationHolder<?> holder, protected void initializeInstance(@NotNull ConfigurationHolder<?> holder, @NotNull Configuration root,
@NotNull Configuration root, @Nullable String parentPath, @Nullable Field configField) { @Nullable String parentPath, @Nullable Field configField) {
String path = getClassPath(holder, parentPath, root.getClass(), configField); String path = getClassPath(holder, parentPath, root.getClass(), configField);
try { try {
this.classInitializer.whenInitialize(holder, path, root.getClass()); this.classInitializer.whenInitialize(holder, path, root.getClass());
@@ -118,8 +120,9 @@ public class ConfigurationInitializer {
// 针对静态类的初始化方法 // 针对静态类的初始化方法
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected void initializeStaticClass(@NotNull ConfigurationHolder<?> holder, protected void initializeStaticClass(@NotNull ConfigurationHolder<?> holder,
@NotNull Class<?> clazz, @Nullable String parentPath, @Nullable Field configField) { @NotNull Class<?> clazz,
if (!Configuration.class.isAssignableFrom(clazz)) return; // 只解析继承了 ConfigurationRoot 的类 @Nullable String parentPath, @Nullable Field configField) {
if (!Configuration.class.isAssignableFrom(clazz)) return; // Only Configuration class can be initialized.
String path = getClassPath(holder, parentPath, clazz, configField); String path = getClassPath(holder, parentPath, clazz, configField);
@@ -158,6 +161,9 @@ public class ConfigurationInitializer {
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
if (holder.options().get(StandardOptions.SET_DEFAULTS)) {
value.setDefault();
}
} else if (source instanceof Configuration && object instanceof Configuration) { } else if (source instanceof Configuration && object instanceof Configuration) {
// 当且仅当 源字段与字段 均为Configuration实例时,才对目标字段进行下一步初始化加载。 // 当且仅当 源字段与字段 均为Configuration实例时,才对目标字段进行下一步初始化加载。
initializeInstance(holder, (Configuration) object, parent, field); initializeInstance(holder, (Configuration) object, parent, field);
@@ -40,8 +40,9 @@ public class PathGenerator {
public @Nullable String getFieldPath(@NotNull ConfigurationHolder<?> holder, public @Nullable String getFieldPath(@NotNull ConfigurationHolder<?> holder,
@Nullable String parentPath, @NotNull Field field) { @Nullable String parentPath, @NotNull Field field) {
ConfigPath path = field.getAnnotation(ConfigPath.class); ConfigPath path = field.getAnnotation(ConfigPath.class);
if (path == null) return link(holder, parentPath, false, field.getName()); // No annotation, use field name. if (path == null)
else return link(holder, parentPath, path.root(), select(path.value(), field.getName())); return link(holder, parentPath, false, covertPath(field.getName())); // No annotation, use field name.
else return link(holder, parentPath, path.root(), select(path.value(), covertPath(field.getName())));
} }
public @Nullable String getClassPath(@NotNull ConfigurationHolder<?> holder, public @Nullable String getClassPath(@NotNull ConfigurationHolder<?> holder,
@@ -51,14 +52,14 @@ public class PathGenerator {
// 2. If the class defined as a field, check if the field has a ConfigPath annotation, // 2. If the class defined as a field, check if the field has a ConfigPath annotation,
// and use filed information. // and use filed information.
ConfigPath clazzPath = clazz.getAnnotation(ConfigPath.class); ConfigPath clazzPath = clazz.getAnnotation(ConfigPath.class);
if (clazzPath != null) return link(holder, parentPath, clazzPath.root(), clazzPath.value()); if (clazzPath != null) return link(holder, parentPath, clazzPath.root(), clazzPath.value());
if (clazzField == null) { if (clazzField == null) {
return link(holder, parentPath, false, clazz.getSimpleName()); // No field, use class name. return link(holder, parentPath, false, parentPath == null ? null : covertPath(clazz.getSimpleName())); // No field, use class name.
} }
ConfigPath fieldPath = clazzField.getAnnotation(ConfigPath.class); ConfigPath fieldPath = clazzField.getAnnotation(ConfigPath.class);
if (fieldPath == null) return link(holder, parentPath, false, clazzField.getName()); if (fieldPath == null) return link(holder, parentPath, false, covertPath(clazzField.getName()));
else return getFieldPath(holder, parentPath, clazzField); else return getFieldPath(holder, parentPath, clazzField);
} }
@@ -70,7 +71,7 @@ public class PathGenerator {
protected @Nullable String link(@NotNull ConfigurationHolder<?> holder, protected @Nullable String link(@NotNull ConfigurationHolder<?> holder,
@Nullable String parent, boolean root, @Nullable String path) { @Nullable String parent, boolean root, @Nullable String path) {
if (path == null || path.isEmpty()) return root ? null : parent; if (path == null || path.isEmpty()) return root ? null : parent;
return root || parent == null ? covertPath(path) : parent + pathSeparator(holder) + covertPath(path); return root || parent == null ? path : parent + pathSeparator(holder) + path;
} }
public static boolean isBlank(String path) { public static boolean isBlank(String path) {
@@ -93,16 +94,16 @@ public class PathGenerator {
public static String covertPathName(String name) { public static String covertPathName(String name) {
return name return name
// Replace all uppercase letters with dashes // Replace all uppercase letters with dashes
.replaceAll("[A-Z]", "-$0") .replaceAll("[A-Z]", "=$0")
// If the first letter is also capitalized, // If the first letter is also capitalized,
// it will also be converted and the first dash will need to be removed // it will also be converted and the first dash will need to be removed
.replaceAll("-(.*)", "$1") .replaceAll("^=(.*)$", "$1")
// Because the name may contain _, it needs to be treated a little differently // Because the name may contain _, it needs to be treated a little differently
.replaceAll("_-([A-Z])", "_$1") .replaceAll("_=([A-Z])", "_$1")
// The content that is not named in all caps is then converted // The content that is not named in all caps is then converted
.replaceAll("([a-z])-([A-Z])", "$1_$2") .replaceAll("([a-z])=([A-Z])", "$1_$2")
// Remove any extra horizontal lines // Remove any extra horizontal lines
.replace("-", "") .replaceAll("=", "")
// Replace the underscore with a dash // Replace the underscore with a dash
.replace("_", "-") .replace("_", "-")
// Finally, convert it to all lowercase // Finally, convert it to all lowercase
@@ -1,8 +1,8 @@
package cc.carm.lib.configuration.demo.tests; package cc.carm.lib.configuration.demo.tests;
import cc.carm.lib.configuration.demo.tests.conf.DemoConfiguration; 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.conf.RegistryConfig;
import cc.carm.lib.configuration.demo.tests.model.TestModel; import cc.carm.lib.configuration.demo.tests.model.UserRecord;
import cc.carm.lib.configuration.source.ConfigurationHolder; import cc.carm.lib.configuration.source.ConfigurationHolder;
import org.jetbrains.annotations.TestOnly; import org.jetbrains.annotations.TestOnly;
@@ -16,7 +16,7 @@ public class ConfigurationTest {
@TestOnly @TestOnly
public static void testDemo(ConfigurationHolder<?> holder) { public static void testDemo(ConfigurationHolder<?> holder) {
try { try {
holder.initializer().initialize(holder, DemoConfiguration.class); holder.initialize(DemoConfiguration.class);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
@@ -30,27 +30,27 @@ public class ConfigurationTest {
System.out.println("after: " + DemoConfiguration.TEST_NUMBER.get()); System.out.println("after: " + DemoConfiguration.TEST_NUMBER.get());
System.out.println("> Test Value:"); System.out.println("> Test Value:");
System.out.println("before: " + DemoConfiguration.Sub.UUID_CONFIG_VALUE.get()); System.out.println("before: " + DemoConfiguration.SUB.UUID_CONFIG_VALUE.get());
DemoConfiguration.Sub.UUID_CONFIG_VALUE.set(UUID.randomUUID()); DemoConfiguration.SUB.UUID_CONFIG_VALUE.set(UUID.randomUUID());
System.out.println("after: " + DemoConfiguration.Sub.UUID_CONFIG_VALUE.get()); System.out.println("after: " + DemoConfiguration.SUB.UUID_CONFIG_VALUE.get());
System.out.println("> Test List:"); System.out.println("> Test List:");
System.out.println(" Before:"); System.out.println(" Before:");
DemoConfiguration.Sub.That.OPERATORS.forEach(System.out::println); DemoConfiguration.SUB.That.OPERATORS.forEach(System.out::println);
List<UUID> operators = IntStream.range(0, 5).mapToObj(i -> UUID.randomUUID()).collect(Collectors.toList()); List<UUID> operators = IntStream.range(0, 5).mapToObj(i -> UUID.randomUUID()).collect(Collectors.toList());
DemoConfiguration.Sub.That.OPERATORS.set(operators); DemoConfiguration.SUB.That.OPERATORS.set(operators);
System.out.println(" After:"); System.out.println(" After:");
DemoConfiguration.Sub.That.OPERATORS.forEach(System.out::println); DemoConfiguration.SUB.That.OPERATORS.forEach(System.out::println);
System.out.println("> Clear List:"); System.out.println("> Clear List:");
System.out.println(" Before: size :" + DemoConfiguration.Sub.That.OPERATORS.size()); System.out.println(" Before: size :" + DemoConfiguration.SUB.That.OPERATORS.size());
DemoConfiguration.Sub.That.OPERATORS.modify(List::clear); DemoConfiguration.SUB.That.OPERATORS.modify(List::clear);
System.out.println(" After size :" + DemoConfiguration.Sub.That.OPERATORS.size()); System.out.println(" After size :" + DemoConfiguration.SUB.That.OPERATORS.size());
System.out.println("> Test Section:"); System.out.println("> Test Section:");
System.out.println(DemoConfiguration.MODEL_TEST.get()); System.out.println(DemoConfiguration.USERS.get());
DemoConfiguration.MODEL_TEST.set(TestModel.random()); DemoConfiguration.USERS.add(UserRecord.random());
// System.out.println("> Test Maps:"); // System.out.println("> Test Maps:");
// DemoConfiguration.USERS.forEach((k, v) -> System.out.println(k + ": " + v)); // DemoConfiguration.USERS.forEach((k, v) -> System.out.println(k + ": " + v));
@@ -64,19 +64,19 @@ public class ConfigurationTest {
public static void testInner(ConfigurationHolder<?> provider) { public static void testInner(ConfigurationHolder<?> provider) {
TestConfiguration TEST = new TestConfiguration(); RegistryConfig TEST = new RegistryConfig();
provider.initialize(TEST); provider.initialize(TEST);
System.out.println("> Test Inner value before:"); System.out.println("> Test Inner value before:");
System.out.println(TEST.INNER.INNER_VALUE.getNotNull()); System.out.println(TEST.INSTANCE.INNER_VALUE.getNotNull());
double after = Math.random() * 200D; double after = Math.random() * 200D;
System.out.println("> Test Inner value -> " + after); System.out.println("> Test Inner value -> " + after);
TEST.INNER.INNER_VALUE.set(after); TEST.INSTANCE.INNER_VALUE.set(after);
System.out.println("> Test Inner value after:"); System.out.println("> Test Inner value after:");
System.out.println(TEST.INNER.INNER_VALUE.getNotNull()); System.out.println(TEST.INSTANCE.INNER_VALUE.getNotNull());
} }
@@ -4,7 +4,8 @@ import cc.carm.lib.configuration.Configuration;
import cc.carm.lib.configuration.annotation.ConfigPath; import cc.carm.lib.configuration.annotation.ConfigPath;
import cc.carm.lib.configuration.annotation.HeaderComment; import cc.carm.lib.configuration.annotation.HeaderComment;
import cc.carm.lib.configuration.annotation.InlineComment; import cc.carm.lib.configuration.annotation.InlineComment;
import cc.carm.lib.configuration.demo.tests.model.TestModel; import cc.carm.lib.configuration.demo.DatabaseConfiguration;
import cc.carm.lib.configuration.demo.tests.model.UserRecord;
import cc.carm.lib.configuration.value.ConfigValue; import cc.carm.lib.configuration.value.ConfigValue;
import cc.carm.lib.configuration.value.standard.ConfiguredList; import cc.carm.lib.configuration.value.standard.ConfiguredList;
import cc.carm.lib.configuration.value.standard.ConfiguredValue; import cc.carm.lib.configuration.value.standard.ConfiguredValue;
@@ -27,18 +28,14 @@ public interface DemoConfiguration extends Configuration {
// 支持通过 Class<?> 变量标注子配置,一并注册。 // 支持通过 Class<?> 变量标注子配置,一并注册。
// 注意: 若对应类也有注解,则优先使用类的注解。 // 注意: 若对应类也有注解,则优先使用类的注解。
@ConfigPath("other-class-config") //支持通过注解修改子配置的主路径,若不修改则以变量名自动生成。 Class<?> DATABASE = DatabaseConfiguration.class;
@HeaderComment({"", "Something..."}) // 支持给子路径直接打注释
@InlineComment("InlineComments for class path")
Class<?> OTHER = OtherConfiguration.class;
@ConfigPath("user") // 通过注解规定配置文件中的路径,若不进行注解则以变量名自动生成。 @ConfigPath("registered_users") // 通过注解规定配置文件中的路径,若不进行注解则以变量名自动生成。
@HeaderComment({"Section类型数据测试"}) // 通过注解给配置添加注释。 @HeaderComment({"Section类型数据测试"}) // 通过注解给配置添加注释。
@InlineComment("Section数据也支持InlineComment注释") @InlineComment("Section数据也支持InlineComment注释")
ConfigValue<TestModel> MODEL_TEST = ConfiguredValue.builderOf(TestModel.class).fromSection() ConfiguredList<UserRecord> USERS = ConfiguredList.builderOf(UserRecord.class).fromSection()
.defaults(new TestModel("Carm", UUID.randomUUID())) .parse(UserRecord::deserialize).serialize(UserRecord::serialize)
.parse((holder, section) -> TestModel.deserialize(section)) .defaults(UserRecord.CARM).build();
.serialize(TestModel::serialize).build();
// @HeaderComment({"[ID - UUID]对照表", "", "用于测试Map类型的解析与序列化保存"}) // @HeaderComment({"[ID - UUID]对照表", "", "用于测试Map类型的解析与序列化保存"})
// ConfiguredMap<Integer, UUID> USERS = ConfiguredMap.builderOf(Integer.class, UUID.class) // ConfiguredMap<Integer, UUID> USERS = ConfiguredMap.builderOf(Integer.class, UUID.class)
@@ -52,7 +49,7 @@ public interface DemoConfiguration extends Configuration {
* 支持内部类的直接注册。 * 支持内部类的直接注册。
* 注意,需要启用 {@link cc.carm.lib.configuration.source.option.StandardOptions#LOAD_SUB_CLASSES} * 注意,需要启用 {@link cc.carm.lib.configuration.source.option.StandardOptions#LOAD_SUB_CLASSES}
*/ */
class Sub implements Configuration { class SUB implements Configuration {
@ConfigPath(value = "uuid-value", root = true) @ConfigPath(value = "uuid-value", root = true)
@InlineComment("This is an inline comment") @InlineComment("This is an inline comment")
@@ -6,7 +6,7 @@ import cc.carm.lib.configuration.value.ConfigValue;
import cc.carm.lib.configuration.value.standard.ConfiguredValue; import cc.carm.lib.configuration.value.standard.ConfiguredValue;
@HeaderComment("Inner Test") @HeaderComment("Inner Test")
public class TestInnerConfiguration implements Configuration { public class InstanceConfig implements Configuration {
public final ConfigValue<Double> INNER_VALUE = ConfiguredValue.of(1.0D); public final ConfigValue<Double> INNER_VALUE = ConfiguredValue.of(1.0D);
@@ -1,4 +0,0 @@
package cc.carm.lib.configuration.demo.tests.conf;
public class OtherConfiguration {
}
@@ -4,24 +4,23 @@ import cc.carm.lib.configuration.Configuration;
import cc.carm.lib.configuration.annotation.ConfigPath; import cc.carm.lib.configuration.annotation.ConfigPath;
import cc.carm.lib.configuration.annotation.HeaderComment; import cc.carm.lib.configuration.annotation.HeaderComment;
import cc.carm.lib.configuration.annotation.InlineComment; import cc.carm.lib.configuration.annotation.InlineComment;
import cc.carm.lib.configuration.demo.tests.model.TestModel; import cc.carm.lib.configuration.demo.tests.model.UserRecord;
import cc.carm.lib.configuration.value.ConfigValue; import cc.carm.lib.configuration.value.ConfigValue;
import cc.carm.lib.configuration.value.standard.ConfiguredValue; import cc.carm.lib.configuration.value.standard.ConfiguredValue;
import java.util.UUID; import java.util.UUID;
public class TestConfiguration implements Configuration { public class RegistryConfig implements Configuration {
public final TestInnerConfiguration INNER = new TestInnerConfiguration(); @HeaderComment("Support for configurations as instances")
public final InstanceConfig INSTANCE = new InstanceConfig();
public final ConfigValue<Double> CLASS_VALUE = ConfiguredValue.of(1.0D);
@ConfigPath("test.user") // 通过注解规定配置文件中的路径若不进行注解则以变量名自动生成 @ConfigPath("test.user") // 通过注解规定配置文件中的路径若不进行注解则以变量名自动生成
@HeaderComment({"Section类型数据测试"}) // 通过注解给配置添加注释 @HeaderComment({"Section类型数据测试"}) // 通过注解给配置添加注释
@InlineComment("Section数据也支持InlineComment注释") @InlineComment("Section数据也支持InlineComment注释")
public final ConfigValue<TestModel> TEST_MODEL = ConfiguredValue.builderOf(TestModel.class).fromSection() public final ConfigValue<UserRecord> TEST_MODEL = ConfiguredValue.builderOf(UserRecord.class).fromSection()
.defaults(new TestModel("Carm", UUID.randomUUID())) .defaults(new UserRecord("Carm", UUID.randomUUID()))
.parse((holder, section) -> TestModel.deserialize(section)) .parse((holder, section) -> UserRecord.deserialize(section))
.serialize((holder, data) -> data.serialize()).build(); .serialize((holder, data) -> data.serialize()).build();
@@ -2,11 +2,11 @@ package cc.carm.lib.configuration.demo.tests.model;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public abstract class AbstractModel { public abstract class AbstractRecord {
protected final @NotNull String name; protected final @NotNull String name;
public AbstractModel(@NotNull String name) { public AbstractRecord(@NotNull String name) {
this.name = name; this.name = name;
} }
@@ -7,20 +7,22 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
public class TestModel extends AbstractModel { public class UserRecord extends AbstractRecord {
public UUID uuid; public static final UserRecord CARM = new UserRecord("Carm", UUID.fromString("f7b3b3b3-3b3b-3b3b-3b3b-3b3b3b3b3b3b"));
public TestModel(String name, UUID uuid) { protected UUID uuid;
public UserRecord(String name, UUID uuid) {
super(name); super(name);
this.uuid = uuid; this.uuid = uuid;
} }
public void setUuid(UUID uuid) { public void uuid(UUID uuid) {
this.uuid = uuid; this.uuid = uuid;
} }
public UUID getUuid() { public UUID uuid() {
return uuid; return uuid;
} }
@@ -33,16 +35,16 @@ public class TestModel extends AbstractModel {
return map; return map;
} }
public static TestModel deserialize(ConfigureSection section) { public static UserRecord deserialize(ConfigureSection section) {
String name = section.getString("name"); String name = section.getString("name");
if (name == null) throw new NullPointerException("name is null"); if (name == null) throw new NullPointerException("name is null");
String uuidString = section.getString("info.uuid"); String uuidString = section.getString("info.uuid");
if (uuidString == null) throw new NullPointerException("uuid is null"); if (uuidString == null) throw new NullPointerException("uuid is null");
return new TestModel(name, UUID.fromString(uuidString)); return new UserRecord(name, UUID.fromString(uuidString));
} }
public static TestModel random() { public static UserRecord random() {
return new TestModel(UUID.randomUUID().toString().substring(0, 5), UUID.randomUUID()); return new UserRecord(UUID.randomUUID().toString().substring(0, 5), UUID.randomUUID());
} }
@@ -46,16 +46,17 @@ public abstract class FileConfigSource<SECTION extends ConfigureSection, ORIGINA
throw new IOException("Failed to create directory " + file.getParentFile().getAbsolutePath()); throw new IOException("Failed to create directory " + file.getParentFile().getAbsolutePath());
} }
if (!this.file.createNewFile()) {
throw new IOException("Failed to create file " + file.getAbsolutePath());
}
if (resourcePath != null && copyDefaults()) { if (resourcePath != null && copyDefaults()) {
try { try {
saveResource(resourcePath, false); saveResource(resourcePath, false);
} catch (IllegalArgumentException ignored) { } catch (IllegalArgumentException e) {
e.printStackTrace();
} }
} }
if (!this.file.exists() && !this.file.createNewFile()) {
throw new IOException("Failed to create file " + file.getAbsolutePath());
}
} }
protected <R> R fileInputStream(@NotNull DataFunction<InputStream, R> loader) throws Exception { protected <R> R fileInputStream(@NotNull DataFunction<InputStream, R> loader) throws Exception {
@@ -65,7 +66,11 @@ public abstract class FileConfigSource<SECTION extends ConfigureSection, ORIGINA
} }
protected <R> R fileReader(@NotNull DataFunction<Reader, R> loader) throws Exception { protected <R> R fileReader(@NotNull DataFunction<Reader, R> loader) throws Exception {
return fileInputStream(is -> loader.handle(new InputStreamReader(is, charset()))); try (InputStream is = Files.newInputStream(file.toPath())) {
try (Reader r = new InputStreamReader(is, charset())) {
return loader.handle(r);
}
}
} }
protected void fileOutputStream(@NotNull Consumer<OutputStream> stream) throws Exception { protected void fileOutputStream(@NotNull Consumer<OutputStream> stream) throws Exception {
@@ -75,7 +80,11 @@ public abstract class FileConfigSource<SECTION extends ConfigureSection, ORIGINA
} }
protected void fileWriter(@NotNull Consumer<Writer> writer) throws Exception { protected void fileWriter(@NotNull Consumer<Writer> writer) throws Exception {
fileOutputStream(os -> writer.accept(new OutputStreamWriter(os, charset()))); try (OutputStream os = Files.newOutputStream(file.toPath())) {
try (Writer w = new OutputStreamWriter(os, charset())) {
writer.accept(w);
}
}
} }
protected void saveResource(@NotNull String resourcePath, boolean replace) protected void saveResource(@NotNull String resourcePath, boolean replace)
+1 -1
View File
@@ -21,7 +21,7 @@
<module>features/commentable</module> <module>features/commentable</module>
<module>features/file</module> <module>features/file</module>
<!-- <module>providers/yaml</module>--> <module>providers/yaml</module>
<module>providers/gson</module> <module>providers/gson</module>
<!-- <module>providers/sql</module>--> <!-- <module>providers/sql</module>-->
<!-- <module>providers/hocon</module>--> <!-- <module>providers/hocon</module>-->
@@ -22,6 +22,16 @@ public class JSONSection implements ConfigureSection {
if (entry.getValue() instanceof Map) { if (entry.getValue() instanceof Map) {
this.data.put(key, new JSONSection(source, (Map<?, ?>) entry.getValue())); this.data.put(key, new JSONSection(source, (Map<?, ?>) entry.getValue()));
} else if (entry.getValue() instanceof List) {
List<Object> list = new ArrayList<>();
for (Object obj : (List<?>) entry.getValue()) {
if (obj instanceof Map) {
list.add(new JSONSection(source, (Map<?, ?>) obj));
} else {
list.add(obj);
}
}
this.data.put(key, list);
} else { } else {
this.data.put(key, entry.getValue()); this.data.put(key, entry.getValue());
} }
@@ -3,7 +3,10 @@ package config;
import cc.carm.lib.configuration.demo.tests.ConfigurationTest; import cc.carm.lib.configuration.demo.tests.ConfigurationTest;
import cc.carm.lib.configuration.json.JSONConfigFactory; import cc.carm.lib.configuration.json.JSONConfigFactory;
import cc.carm.lib.configuration.source.ConfigurationHolder; import cc.carm.lib.configuration.source.ConfigurationHolder;
import cc.carm.lib.configuration.source.loader.PathGenerator;
import cc.carm.lib.configuration.source.option.StandardOptions; import cc.carm.lib.configuration.source.option.StandardOptions;
import cc.carm.lib.configuration.value.ConfigValue;
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
import org.junit.Test; import org.junit.Test;
import java.io.File; import java.io.File;
@@ -12,11 +15,17 @@ public class JSONConfigTest {
protected final ConfigurationHolder<?> holder = JSONConfigFactory protected final ConfigurationHolder<?> holder = JSONConfigFactory
.from(new File("target"), "config.json") .from(new File("target"), "config.json")
.option(StandardOptions.PATH_SEPARATOR, '-') .resourcePath("example.json")
.build(); .build();
@Test @Test
public void onTest() { public void onTest() {
ConfigValue<Boolean> EXAMPLE = ConfiguredValue.of(false);
EXAMPLE.initialize(this.holder, "example");
System.out.println("Example: " + EXAMPLE.get());
ConfigurationTest.testDemo(this.holder); ConfigurationTest.testDemo(this.holder);
ConfigurationTest.testInner(this.holder); ConfigurationTest.testInner(this.holder);
@@ -0,0 +1,3 @@
{
"example": "true"
}
@@ -2,7 +2,7 @@ package config;
import cc.carm.lib.configuration.EasyConfiguration; import cc.carm.lib.configuration.EasyConfiguration;
import cc.carm.lib.configuration.demo.tests.ConfigurationTest; import cc.carm.lib.configuration.demo.tests.ConfigurationTest;
import cc.carm.lib.configuration.demo.tests.model.AbstractModel; import cc.carm.lib.configuration.demo.tests.model.AbstractRecord;
import cc.carm.lib.configuration.yaml.YAMLConfigProvider; import cc.carm.lib.configuration.yaml.YAMLConfigProvider;
import config.model.AnyModel; import config.model.AnyModel;
import config.model.SomeModel; import config.model.SomeModel;
@@ -10,8 +10,6 @@ import config.source.ModelConfiguration;
import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerialization; import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerialization;
import org.junit.Test; import org.junit.Test;
import java.io.IOException;
public class DemoConfigTest { public class DemoConfigTest {
static { static {
@@ -37,10 +35,10 @@ public class DemoConfigTest {
provider.initialize(ModelConfiguration.class); provider.initialize(ModelConfiguration.class);
System.out.println("----------------------------------------------------"); System.out.println("----------------------------------------------------");
AbstractModel someModel = ModelConfiguration.SOME_MODEL.get(); AbstractRecord someModel = ModelConfiguration.SOME_MODEL.get();
if (someModel != null) System.out.println(someModel.getName()); if (someModel != null) System.out.println(someModel.getName());
AbstractModel anyModel = ModelConfiguration.ANY_MODEL.get(); AbstractRecord anyModel = ModelConfiguration.ANY_MODEL.get();
if (anyModel != null) System.out.println(anyModel.getName()); if (anyModel != null) System.out.println(anyModel.getName());
ModelConfiguration.MODELS.forEach(System.out::println); ModelConfiguration.MODELS.forEach(System.out::println);
@@ -1,6 +1,6 @@
package config.model; package config.model;
import cc.carm.lib.configuration.demo.tests.model.AbstractModel; import cc.carm.lib.configuration.demo.tests.model.AbstractRecord;
import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerializable; import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerializable;
import org.bspfsystems.yamlconfiguration.serialization.SerializableAs; import org.bspfsystems.yamlconfiguration.serialization.SerializableAs;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -11,7 +11,7 @@ import java.util.Map;
import java.util.UUID; import java.util.UUID;
@SerializableAs("AnyModel") @SerializableAs("AnyModel")
public class AnyModel extends AbstractModel implements ConfigurationSerializable { public class AnyModel extends AbstractRecord implements ConfigurationSerializable {
public final boolean bool; public final boolean bool;
@@ -1,6 +1,6 @@
package config.model; package config.model;
import cc.carm.lib.configuration.demo.tests.model.AbstractModel; import cc.carm.lib.configuration.demo.tests.model.AbstractRecord;
import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerializable; import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerializable;
import org.bspfsystems.yamlconfiguration.serialization.SerializableAs; import org.bspfsystems.yamlconfiguration.serialization.SerializableAs;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -11,7 +11,7 @@ import java.util.Map;
import java.util.UUID; import java.util.UUID;
@SerializableAs("SomeModel") @SerializableAs("SomeModel")
public class SomeModel extends AbstractModel implements ConfigurationSerializable { public class SomeModel extends AbstractRecord implements ConfigurationSerializable {
public final int num; public final int num;
@@ -7,7 +7,7 @@ import cc.carm.lib.configuration.value.ConfigValue;
import cc.carm.lib.configuration.value.standard.ConfiguredList; import cc.carm.lib.configuration.value.standard.ConfiguredList;
import cc.carm.lib.configuration.value.standard.ConfiguredMap; import cc.carm.lib.configuration.value.standard.ConfiguredMap;
import cc.carm.lib.configuration.value.standard.ConfiguredSectionMap; import cc.carm.lib.configuration.value.standard.ConfiguredSectionMap;
import cc.carm.lib.configuration.demo.tests.model.AbstractModel; import cc.carm.lib.configuration.demo.tests.model.AbstractRecord;
import cc.carm.lib.configuration.yaml.value.ConfiguredSerializable; import cc.carm.lib.configuration.yaml.value.ConfiguredSerializable;
import config.model.AnyModel; import config.model.AnyModel;
import config.model.SomeModel; import config.model.SomeModel;
@@ -16,11 +16,11 @@ import config.model.SomeModel;
@ConfigPath("model-test") @ConfigPath("model-test")
public class ModelConfiguration implements Configuration { public class ModelConfiguration implements Configuration {
public static final ConfigValue<? extends AbstractModel> SOME_MODEL = ConfiguredSerializable.of( public static final ConfigValue<? extends AbstractRecord> SOME_MODEL = ConfiguredSerializable.of(
SomeModel.class, SomeModel.random() SomeModel.class, SomeModel.random()
); );
public static final ConfigValue<? extends AbstractModel> ANY_MODEL = ConfiguredSerializable.of( public static final ConfigValue<? extends AbstractRecord> ANY_MODEL = ConfiguredSerializable.of(
AnyModel.class, AnyModel.random() AnyModel.class, AnyModel.random()
); );