mirror of
https://github.com/CarmJos/EasyConfiguration.git
synced 2026-06-04 18:48:20 +08:00
feat(sql): Support SQL sources
This commit is contained in:
+6
-19
@@ -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<SQLSource, Configurat
|
||||
|
||||
public <T> SQLConfigFactory resolver(@Range(from = 0, to = 255) int id, @NotNull ValueType<T> type,
|
||||
@NotNull DataFunction<String, T> parser) {
|
||||
return resolver(id, new SQLValueResolver<T>(type) {
|
||||
@Override
|
||||
public @NotNull T resolve(@NotNull ConfigurationHolder<? extends SQLSource> holder, String data) throws Exception {
|
||||
return parser.handle(data);
|
||||
}
|
||||
});
|
||||
return resolver(id, SQLValueResolver.of(type, parser));
|
||||
}
|
||||
|
||||
public <T> SQLConfigFactory resolver(@Range(from = 0, to = 255) int id, @NotNull Class<T> clazz,
|
||||
@NotNull DataFunction<String, T> parser,
|
||||
@NotNull DataFunction<Object, String> serializer) {
|
||||
@NotNull DataFunction<T, String> serializer) {
|
||||
return resolver(id, ValueType.of(clazz), parser, serializer);
|
||||
}
|
||||
|
||||
public <T> SQLConfigFactory resolver(@Range(from = 0, to = 255) int id, @NotNull ValueType<T> type,
|
||||
@NotNull DataFunction<String, T> parser,
|
||||
@NotNull DataFunction<Object, String> serializer) {
|
||||
return resolver(id, new SQLValueResolver<T>(type) {
|
||||
@Override
|
||||
public @NotNull T resolve(@NotNull ConfigurationHolder<? extends SQLSource> holder, String data) throws Exception {
|
||||
return parser.handle(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String serialize(@NotNull ConfigurationHolder<? extends SQLSource> holder, Object value) throws Exception {
|
||||
return serializer.handle(value);
|
||||
}
|
||||
});
|
||||
@NotNull DataFunction<T, String> serializer) {
|
||||
return resolver(id, SQLValueResolver.of(type, parser, serializer));
|
||||
}
|
||||
|
||||
public SQLConfigFactory tableName(@NotNull String tableName) {
|
||||
@@ -128,6 +114,7 @@ public class SQLConfigFactory extends ConfigurationFactory<SQLSource, Configurat
|
||||
if (manager == null) throw new NullPointerException("No SQLManager instance provided.");
|
||||
|
||||
Commentable.registerMeta(this.initializer);
|
||||
VersionedMetaTypes.register(this.initializer);
|
||||
|
||||
return new ConfigurationHolder<SQLSource>(this.adapters, this.options, this.metadata, this.initializer) {
|
||||
final SQLSource source = new SQLSource(
|
||||
|
||||
@@ -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<Boolean> PURGE = ConfigurationOption.of( true);
|
||||
|
||||
}
|
||||
|
||||
@@ -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<SourcedSection, Map<String, Objec
|
||||
return Objects.requireNonNull(this.rootSection, "Root section is not initialized.");
|
||||
}
|
||||
|
||||
public int purge() throws Exception {
|
||||
return this.table.createDelete().addCondition("namespace", namespace).build().execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() throws Exception {
|
||||
LocalDateTime time = LocalDateTime.now(); // Update time
|
||||
@@ -102,29 +105,29 @@ public class SQLSource extends ConfigureSource<SourcedSection, Map<String, Objec
|
||||
Map<String, ConfigValue<?>> values = holder().registeredValues();
|
||||
for (Map.Entry<String, ConfigValue<?>> 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<Object> 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<Object> 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<SourcedSection, Map<String, Objec
|
||||
}
|
||||
}
|
||||
|
||||
if (holder.option(SQLOptions.PURGE)) {
|
||||
purge();
|
||||
}
|
||||
this.table.createReplaceBatch()
|
||||
.setColumnNames(
|
||||
"namespace", "path", "update_time", "version", "type", "value",
|
||||
@@ -157,12 +163,8 @@ public class SQLSource extends ConfigureSource<SourcedSection, Map<String, Objec
|
||||
if (path == null) continue; // Path should be not null
|
||||
int ver = rs.getInt("version");
|
||||
try {
|
||||
Object val = parse(rs.getInt("type"), rs.getString("value"));
|
||||
System.out.println("Path <" + path + "> 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<SourcedSection, Map<String, Objec
|
||||
protected @Nullable Object parse(int type, String value) throws Exception {
|
||||
SQLValueResolver<?> 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()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
+30
-18
@@ -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<T> {
|
||||
public static final @NotNull SQLValueResolver<List<?>> LIST = new SQLValueResolver<List<?>>(new ValueType<List<?>>() {
|
||||
}) {
|
||||
@Override
|
||||
public @Nullable List<?> resolve(@NotNull ConfigurationHolder<? extends SQLSource> 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<? extends SQLSource> 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<?, ?>> MAP = new SQLValueResolver<Map<?, ?>>(new ValueType<Map<?, ?>>() {
|
||||
}) {
|
||||
@Override
|
||||
public @Nullable Map<?, ?> resolve(@NotNull ConfigurationHolder<? extends SQLSource> 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<? extends SQLSource> 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<T> {
|
||||
public static <V> SQLValueResolver<V> of(@NotNull ValueType<V> type, @NotNull DataFunction<String, V> resolver) {
|
||||
return new SQLValueResolver<V>(type) {
|
||||
@Override
|
||||
public @NotNull V resolve(@NotNull ConfigurationHolder<? extends SQLSource> holder, String data) throws Exception {
|
||||
public @NotNull V resolve(@NotNull SQLSource source, String data) throws Exception {
|
||||
return resolver.handle(data);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static <V> SQLValueResolver<V> of(@NotNull ValueType<V> type,
|
||||
@NotNull DataFunction<String, V> resolver,
|
||||
@NotNull DataFunction<V, String> serializer) {
|
||||
return new SQLValueResolver<V>(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<T> type;
|
||||
|
||||
protected SQLValueResolver(@NotNull ValueType<T> type) {
|
||||
@@ -86,17 +102,13 @@ public abstract class SQLValueResolver<T> {
|
||||
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<? extends SQLSource> holder, String data) throws Exception;
|
||||
|
||||
public @Nullable String serialize(@NotNull ConfigurationHolder<? extends SQLSource> holder, Object value) throws Exception {
|
||||
public @Nullable String serialize(@NotNull SQLSource source, Object value) throws Exception {
|
||||
return String.valueOf(value);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user