diff --git a/core/src/main/java/cc/carm/lib/configuration/adapter/ValueType.java b/core/src/main/java/cc/carm/lib/configuration/adapter/ValueType.java index 89a7b4c..abd39b4 100644 --- a/core/src/main/java/cc/carm/lib/configuration/adapter/ValueType.java +++ b/core/src/main/java/cc/carm/lib/configuration/adapter/ValueType.java @@ -4,6 +4,8 @@ import org.jetbrains.annotations.NotNull; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; +import java.util.List; +import java.util.Map; import java.util.Objects; /** @@ -29,7 +31,6 @@ public abstract class ValueType { public static final ValueType CHAR = ofPrimitiveType(Character.class); public static final ValueType CHAR_TYPE = ofPrimitiveType(char.class); - public static final ValueType[] PRIMITIVE_TYPES = { STRING, INTEGER, LONG, DOUBLE, FLOAT, BOOLEAN, BYTE, SHORT, CHAR, INTEGER_TYPE, LONG_TYPE, DOUBLE_TYPE, FLOAT_TYPE, BOOLEAN_TYPE, BYTE_TYPE, SHORT_TYPE, CHAR_TYPE diff --git a/core/src/main/java/cc/carm/lib/configuration/source/option/StandardOptions.java b/core/src/main/java/cc/carm/lib/configuration/source/option/StandardOptions.java index 79143cc..e3b489a 100644 --- a/core/src/main/java/cc/carm/lib/configuration/source/option/StandardOptions.java +++ b/core/src/main/java/cc/carm/lib/configuration/source/option/StandardOptions.java @@ -23,12 +23,13 @@ public interface StandardOptions { ConfigurationOption LOAD_SUB_CLASSES = of(true); /** - * Whether to pre parse the config values. - *
if false, the values will be parsed when calling - * {@link cc.carm.lib.configuration.value.ConfigValue#get()} + * Whether to pre parse the config values, + * may good to set true if you want to keep the config format. *
if true, the values will be parsed when * {@link ConfigurationHolder#initialize(Configuration)}. + *
if false, the values will be parsed when calling + * {@link cc.carm.lib.configuration.value.ConfigValue#get()} */ - ConfigurationOption PRELOAD = of(false); + ConfigurationOption PRELOAD = of(true); } diff --git a/core/src/main/java/cc/carm/lib/configuration/value/ValueManifest.java b/core/src/main/java/cc/carm/lib/configuration/value/ValueManifest.java index 23a7980..f733c8b 100644 --- a/core/src/main/java/cc/carm/lib/configuration/value/ValueManifest.java +++ b/core/src/main/java/cc/carm/lib/configuration/value/ValueManifest.java @@ -4,6 +4,7 @@ import cc.carm.lib.configuration.adapter.ValueType; import cc.carm.lib.configuration.source.ConfigurationHolder; import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder; import cc.carm.lib.configuration.source.section.ConfigureSource; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -108,15 +109,16 @@ public class ValueManifest { return holder().metadata(path()); } + @ApiStatus.Internal protected Object getData() { return config().get(path()); } + @ApiStatus.Internal protected void setData(@Nullable Object value) { config().set(path(), value); } - private static final @NotNull BiConsumer<@NotNull ConfigurationHolder, @NotNull String> EMPTY_INITIALIZER = (provider, valuePath) -> { }; diff --git a/demo/pom.xml b/demo/pom.xml index 9d84d6a..293fa60 100644 --- a/demo/pom.xml +++ b/demo/pom.xml @@ -33,6 +33,19 @@ compile + + ${project.parent.groupId} + easyconfiguration-feature-versioned + ${project.parent.version} + compile + + + cc.carm.lib + easyconfiguration-feature-versioned + 4.0.8 + compile + + diff --git a/demo/src/main/java/cc/carm/lib/configuration/demo/DatabaseConfiguration.java b/demo/src/main/java/cc/carm/lib/configuration/demo/DatabaseConfiguration.java index 027e46d..b2769e8 100644 --- a/demo/src/main/java/cc/carm/lib/configuration/demo/DatabaseConfiguration.java +++ b/demo/src/main/java/cc/carm/lib/configuration/demo/DatabaseConfiguration.java @@ -25,6 +25,7 @@ public interface DatabaseConfiguration extends Configuration { ConfigValue DATABASE = ConfiguredValue.of(String.class, "minecraft"); ConfigValue USERNAME = ConfiguredValue.of(String.class, "root"); ConfigValue PASSWORD = ConfiguredValue.of(String.class, "password"); + ConfigValue EXTRA = ConfiguredValue.of(String.class, "?useSSL=false"); static String buildJDBC() { diff --git a/demo/src/main/java/cc/carm/lib/configuration/demo/tests/ConfigurationTest.java b/demo/src/main/java/cc/carm/lib/configuration/demo/tests/ConfigurationTest.java index fed35a5..ce21b20 100644 --- a/demo/src/main/java/cc/carm/lib/configuration/demo/tests/ConfigurationTest.java +++ b/demo/src/main/java/cc/carm/lib/configuration/demo/tests/ConfigurationTest.java @@ -69,14 +69,14 @@ public class ConfigurationTest { provider.initialize(TEST); System.out.println("> Test Inner value before:"); - System.out.println(TEST.INSTANCE.INNER_VALUE.resolve()); + System.out.println(TEST.INSTANCE.STATUS.resolve()); double after = Math.random() * 200D; System.out.println("> Test Inner value -> " + after); - TEST.INSTANCE.INNER_VALUE.set(after); + TEST.INSTANCE.STATUS.set(after); System.out.println("> Test Inner value after:"); - System.out.println(TEST.INSTANCE.INNER_VALUE.resolve()); + System.out.println(TEST.INSTANCE.STATUS.resolve()); } diff --git a/demo/src/main/java/cc/carm/lib/configuration/demo/tests/conf/DemoConfiguration.java b/demo/src/main/java/cc/carm/lib/configuration/demo/tests/conf/DemoConfiguration.java index 6c09159..722129f 100644 --- a/demo/src/main/java/cc/carm/lib/configuration/demo/tests/conf/DemoConfiguration.java +++ b/demo/src/main/java/cc/carm/lib/configuration/demo/tests/conf/DemoConfiguration.java @@ -1,11 +1,7 @@ package cc.carm.lib.configuration.demo.tests.conf; import cc.carm.lib.configuration.Configuration; -import cc.carm.lib.configuration.annotation.ConfigPath; -import cc.carm.lib.configuration.annotation.FooterComments; -import cc.carm.lib.configuration.annotation.HeaderComments; -import cc.carm.lib.configuration.annotation.InlineComment; -import cc.carm.lib.configuration.demo.DatabaseConfiguration; +import cc.carm.lib.configuration.annotation.*; import cc.carm.lib.configuration.demo.tests.model.ItemStack; import cc.carm.lib.configuration.demo.tests.model.UserRecord; import cc.carm.lib.configuration.value.ConfigValue; @@ -29,7 +25,8 @@ import java.util.UUID; public interface DemoConfiguration extends Configuration { @ConfigPath(root = true) - ConfigValue VERSION = ConfiguredValue.of(Double.class, 1.0D); + @ConfigVersion(2) + ConfigValue VERSION = ConfiguredValue.of(Double.class, 2.0D); @ConfigPath(root = true) @FooterComments({"此处内容将显示在配置条目的下方", "可用于补充说明,但一般不建议使用"}) @@ -39,10 +36,6 @@ public interface DemoConfiguration extends Configuration { @FooterComments({"上述的枚举内容本质上是通过STRING解析的"}) ConfigValue TEST_ENUM = ConfiguredValue.of(ChronoUnit.class, ChronoUnit.DAYS); - // 支持通过 Class 变量标注子配置,一并注册。 - // 注意: 若对应类也有注解,则优先使用类的注解。 - Class DATABASE = DatabaseConfiguration.class; - @ConfigPath("registered_users") // 通过注解规定配置文件中的路径,若不进行注解则以变量名自动生成。 @HeaderComments({"Section类型数据测试"}) // 通过注解给配置添加注释。 @InlineComment("默认地注释会加到Section的首行末尾") // 通过注解给配置添加注释。 diff --git a/demo/src/main/java/cc/carm/lib/configuration/demo/tests/conf/InstanceConfig.java b/demo/src/main/java/cc/carm/lib/configuration/demo/tests/conf/InstanceConfig.java index 034db9a..4d69316 100644 --- a/demo/src/main/java/cc/carm/lib/configuration/demo/tests/conf/InstanceConfig.java +++ b/demo/src/main/java/cc/carm/lib/configuration/demo/tests/conf/InstanceConfig.java @@ -8,6 +8,6 @@ import cc.carm.lib.configuration.value.standard.ConfiguredValue; @HeaderComments("Inner Test") public class InstanceConfig implements Configuration { - public final ConfigValue INNER_VALUE = ConfiguredValue.of(1.0D); + public final ConfigValue STATUS = ConfiguredValue.of(1.0D); } diff --git a/demo/src/main/java/cc/carm/lib/configuration/demo/tests/conf/RegistryConfig.java b/demo/src/main/java/cc/carm/lib/configuration/demo/tests/conf/RegistryConfig.java index 4a44d48..7d5d922 100644 --- a/demo/src/main/java/cc/carm/lib/configuration/demo/tests/conf/RegistryConfig.java +++ b/demo/src/main/java/cc/carm/lib/configuration/demo/tests/conf/RegistryConfig.java @@ -20,7 +20,7 @@ public class RegistryConfig implements Configuration { @FooterComments({"12313213212"}) @InlineComment(value = "用户名(匹配注释)", regex = "name") // 通过注解给配置添加注释。 @InlineComment(value = "信息", regex = {"info.*", "info.game.*"}) // 通过注解给配置添加注释。 - public final ConfigValue TEST_MODEL = ConfiguredValue.builderOf(UserRecord.class).fromSection() + public final ConfigValue OWNER = ConfiguredValue.builderOf(UserRecord.class).fromSection() .defaults(new UserRecord("Carm", UUID.randomUUID())) .parse((holder, section) -> UserRecord.deserialize(section)) .serialize((holder, data) -> data.serialize()).build(); diff --git a/providers/sql/src/main/java/cc/carm/lib/configuration/source/sql/SQLConfigFactory.java b/providers/sql/src/main/java/cc/carm/lib/configuration/source/sql/SQLConfigFactory.java index bc3c37b..16e5033 100644 --- a/providers/sql/src/main/java/cc/carm/lib/configuration/source/sql/SQLConfigFactory.java +++ b/providers/sql/src/main/java/cc/carm/lib/configuration/source/sql/SQLConfigFactory.java @@ -5,6 +5,7 @@ import cc.carm.lib.configuration.commentable.Commentable; import cc.carm.lib.configuration.function.DataFunction; import cc.carm.lib.configuration.source.ConfigurationFactory; import cc.carm.lib.configuration.source.ConfigurationHolder; +import cc.carm.lib.configuration.versioned.VersionedMetaTypes; import cc.carm.lib.easysql.api.SQLManager; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -79,34 +80,19 @@ public class SQLConfigFactory extends ConfigurationFactory SQLConfigFactory resolver(@Range(from = 0, to = 255) int id, @NotNull ValueType type, @NotNull DataFunction parser) { - return resolver(id, new SQLValueResolver(type) { - @Override - public @NotNull T resolve(@NotNull ConfigurationHolder holder, String data) throws Exception { - return parser.handle(data); - } - }); + return resolver(id, SQLValueResolver.of(type, parser)); } public SQLConfigFactory resolver(@Range(from = 0, to = 255) int id, @NotNull Class clazz, @NotNull DataFunction parser, - @NotNull DataFunction serializer) { + @NotNull DataFunction serializer) { return resolver(id, ValueType.of(clazz), parser, serializer); } public SQLConfigFactory resolver(@Range(from = 0, to = 255) int id, @NotNull ValueType type, @NotNull DataFunction parser, - @NotNull DataFunction serializer) { - return resolver(id, new SQLValueResolver(type) { - @Override - public @NotNull T resolve(@NotNull ConfigurationHolder holder, String data) throws Exception { - return parser.handle(data); - } - - @Override - public @NotNull String serialize(@NotNull ConfigurationHolder holder, Object value) throws Exception { - return serializer.handle(value); - } - }); + @NotNull DataFunction serializer) { + return resolver(id, SQLValueResolver.of(type, parser, serializer)); } public SQLConfigFactory tableName(@NotNull String tableName) { @@ -128,6 +114,7 @@ public class SQLConfigFactory extends ConfigurationFactory(this.adapters, this.options, this.metadata, this.initializer) { final SQLSource source = new SQLSource( diff --git a/providers/sql/src/main/java/cc/carm/lib/configuration/source/sql/SQLOptions.java b/providers/sql/src/main/java/cc/carm/lib/configuration/source/sql/SQLOptions.java index 2777d98..1232772 100644 --- a/providers/sql/src/main/java/cc/carm/lib/configuration/source/sql/SQLOptions.java +++ b/providers/sql/src/main/java/cc/carm/lib/configuration/source/sql/SQLOptions.java @@ -1,6 +1,12 @@ package cc.carm.lib.configuration.source.sql; +import cc.carm.lib.configuration.source.option.ConfigurationOption; + public interface SQLOptions { + /** + * Whether to purge the configuration's in-database data when saving. + */ + ConfigurationOption PURGE = ConfigurationOption.of( true); } diff --git a/providers/sql/src/main/java/cc/carm/lib/configuration/source/sql/SQLSource.java b/providers/sql/src/main/java/cc/carm/lib/configuration/source/sql/SQLSource.java index 1ae67bf..ec95151 100644 --- a/providers/sql/src/main/java/cc/carm/lib/configuration/source/sql/SQLSource.java +++ b/providers/sql/src/main/java/cc/carm/lib/configuration/source/sql/SQLSource.java @@ -1,6 +1,5 @@ package cc.carm.lib.configuration.source.sql; -import cc.carm.lib.configuration.adapter.ValueType; import cc.carm.lib.configuration.commentable.Commentable; import cc.carm.lib.configuration.source.ConfigurationHolder; import cc.carm.lib.configuration.source.section.ConfigureSource; @@ -93,6 +92,10 @@ public class SQLSource extends ConfigureSource> values = holder().registeredValues(); for (Map.Entry> entry : values.entrySet()) { @NotNull String path = entry.getKey(); - @NotNull ConfigValue value = entry.getValue(); + @NotNull ConfigValue config = entry.getValue(); + @Nullable Object value = section.get(path); - try { - int typeID = typeOf(entry.getValue()); - String data = null; - - if (value != null) { - if (value instanceof SourcedSection) { - data = serialize(typeID, ((SourcedSection) value).rawMap()); - } else if (value instanceof List) { - List list = new ArrayList<>(); - for (Object obj : (List) value) { - if (obj instanceof SourcedSection) { - list.add(((SourcedSection) obj).rawMap()); - } else { - list.add(obj); - } - } - data = serialize(typeID, list); + if (value instanceof SourcedSection) { + value = ((SourcedSection) value).rawMap(); + } else if (value instanceof List) { + List list = new ArrayList<>(); + for (Object obj : (List) value) { + if (obj instanceof SourcedSection) { + list.add(((SourcedSection) obj).rawMap()); } else { - data = serialize(typeID, value); + list.add(obj); } } + value = list; + } + + if (value == null) continue; + + try { + int typeID = typeIdOf(value); + String data = serialize(typeID, value); + if (data == null) continue; int version = holder().metadata(path).get(VersionedMetaTypes.VERSION, 0); dataValues.add(new Object[]{ @@ -138,6 +141,9 @@ public class SQLSource extends ConfigureSource Value = " + val); - loaded.put(path, val); - if (ver != 0) { - holder().metadata(path).set(VersionedMetaTypes.VERSION, ver); - } + loaded.put(path, parse(rs.getInt("type"), rs.getString("value"))); + if (ver != 0) holder().metadata(path).set(VersionedMetaTypes.VERSION, ver); } catch (Exception e) { e.printStackTrace(); } @@ -175,20 +177,20 @@ public class SQLSource extends ConfigureSource function = this.resolvers.get(type); if (function == null) throw new IllegalStateException("No resolvers for type #" + type); - return function.resolve(holder(), value); + return function.resolve(this, value); } protected @Nullable String serialize(int type, @NotNull Object value) throws Exception { SQLValueResolver function = this.resolvers.get(type); if (function == null) throw new IllegalStateException("No resolvers for type #" + type); - return function.serialize(holder(), value); + return function.serialize(this, value); } - protected int typeOf(@NotNull ValueType value) { + protected int typeIdOf(@NotNull Object value) { return this.resolvers.entrySet().stream() - .filter(entry -> entry.getValue().isTypeOf(value)) + .filter(entry -> entry.getValue().isInstance(value)) .findFirst().map(Map.Entry::getKey) - .orElseThrow(() -> new IllegalStateException("No resolvers for value " + value)); + .orElseThrow(() -> new IllegalStateException("No resolvers for value " + value.getClass().getName())); } diff --git a/providers/sql/src/main/java/cc/carm/lib/configuration/source/sql/SQLValueResolver.java b/providers/sql/src/main/java/cc/carm/lib/configuration/source/sql/SQLValueResolver.java index 706bd04..d5263cc 100644 --- a/providers/sql/src/main/java/cc/carm/lib/configuration/source/sql/SQLValueResolver.java +++ b/providers/sql/src/main/java/cc/carm/lib/configuration/source/sql/SQLValueResolver.java @@ -2,7 +2,6 @@ package cc.carm.lib.configuration.source.sql; import cc.carm.lib.configuration.adapter.ValueType; import cc.carm.lib.configuration.function.DataFunction; -import cc.carm.lib.configuration.source.ConfigurationHolder; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -26,26 +25,26 @@ public abstract class SQLValueResolver { public static final @NotNull SQLValueResolver> LIST = new SQLValueResolver>(new ValueType>() { }) { @Override - public @Nullable List resolve(@NotNull ConfigurationHolder holder, String data) throws Exception { - return holder.config().gson().fromJson(data, List.class); + public @Nullable List resolve(@NotNull SQLSource source, String data) throws Exception { + return source.gson().fromJson(data, List.class); } @Override - public @Nullable String serialize(@NotNull ConfigurationHolder holder, Object value) { - return holder.config().gson().toJson(value); + public @Nullable String serialize(@NotNull SQLSource source, Object value) { + return source.gson().toJson(value); } }; public static final @NotNull SQLValueResolver> MAP = new SQLValueResolver>(new ValueType>() { }) { @Override - public @Nullable Map resolve(@NotNull ConfigurationHolder holder, String data) throws Exception { - return holder.config().gson().fromJson(data, LinkedHashMap.class); + public @Nullable Map resolve(@NotNull SQLSource source, String data) throws Exception { + return source.gson().fromJson(data, LinkedHashMap.class); } @Override - public @Nullable String serialize(@NotNull ConfigurationHolder holder, Object value) { - return holder.config().gson().toJson(value); + public @Nullable String serialize(@NotNull SQLSource source, Object value) { + return source.gson().toJson(value); } }; @@ -70,12 +69,29 @@ public abstract class SQLValueResolver { public static SQLValueResolver of(@NotNull ValueType type, @NotNull DataFunction resolver) { return new SQLValueResolver(type) { @Override - public @NotNull V resolve(@NotNull ConfigurationHolder holder, String data) throws Exception { + public @NotNull V resolve(@NotNull SQLSource source, String data) throws Exception { return resolver.handle(data); } }; } + public static SQLValueResolver of(@NotNull ValueType type, + @NotNull DataFunction resolver, + @NotNull DataFunction serializer) { + return new SQLValueResolver(type) { + @Override + public @NotNull V resolve(@NotNull SQLSource source, String data) throws Exception { + return resolver.handle(data); + } + + @Override + public @NotNull String serialize(@NotNull SQLSource source, Object value) throws Exception { + return serializer.handle(type.cast(value)); + } + }; + } + + protected final @NotNull ValueType type; protected SQLValueResolver(@NotNull ValueType type) { @@ -86,17 +102,13 @@ public abstract class SQLValueResolver { return type; } - public boolean isTypeOf(@NotNull Class clazz) { - return type.isSubtypeOf(clazz); + public boolean isInstance(@NotNull Object obj) { + return getType().isInstance(obj); } - public boolean isTypeOf(@NotNull ValueType valueType) { - return valueType.equals(type); - } + public abstract @Nullable T resolve(@NotNull SQLSource source, String data) throws Exception; - public abstract @Nullable T resolve(@NotNull ConfigurationHolder holder, String data) throws Exception; - - public @Nullable String serialize(@NotNull ConfigurationHolder holder, Object value) throws Exception { + public @Nullable String serialize(@NotNull SQLSource source, Object value) throws Exception { return String.valueOf(value); }