feat(config): Completely migrate to using JsonReader instead of JsonElement
This commit is contained in:
parent
0f3933a946
commit
d2c2af2049
|
@ -1,7 +1,8 @@
|
|||
package io.gitlab.jfronny.libjf.config.api.v1;
|
||||
|
||||
import io.gitlab.jfronny.gson.JsonElement;
|
||||
import io.gitlab.jfronny.gson.stream.JsonWriter;
|
||||
import io.gitlab.jfronny.gson.JsonParseException;
|
||||
import io.gitlab.jfronny.gson.stream.*;
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.type.Type;
|
||||
import io.gitlab.jfronny.libjf.config.impl.dsl.DslEntryInfo;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
@ -61,7 +62,20 @@ public interface EntryInfo<T> {
|
|||
* Set this entry's value to that of the element
|
||||
* @param element The element to read from
|
||||
*/
|
||||
void loadFromJson(JsonElement element) throws IllegalAccessException;
|
||||
@Deprecated
|
||||
default void loadFromJson(JsonElement element) throws IllegalAccessException {
|
||||
try {
|
||||
loadFromJson(new JsonTreeReader(element));
|
||||
} catch (IOException e) {
|
||||
throw new JsonParseException("Could not read Json", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this entry's value to that of the element
|
||||
* @param reader The reader to read from
|
||||
*/
|
||||
void loadFromJson(JsonReader reader) throws IOException, IllegalAccessException;
|
||||
|
||||
/**
|
||||
* Write the currently cached value to the writer
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package io.gitlab.jfronny.libjf.config.api.v1.dsl;
|
||||
|
||||
import io.gitlab.jfronny.gson.JsonElement;
|
||||
import io.gitlab.jfronny.gson.stream.JsonReader;
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.*;
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.type.Type;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
@ -38,7 +39,7 @@ public interface CategoryBuilder<Builder extends CategoryBuilder<Builder>> {
|
|||
<T> Builder value(String id, T def, double min, double max, Type type, int width, Supplier<T> get, Consumer<T> set);
|
||||
<T> Builder value(EntryInfo<T> entry);
|
||||
|
||||
@ApiStatus.Experimental Builder addMigration(String element, Consumer<JsonElement> apply);
|
||||
@ApiStatus.Experimental Builder addMigration(String element, Migration migration);
|
||||
|
||||
String getId();
|
||||
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
package io.gitlab.jfronny.libjf.config.api.v1.dsl;
|
||||
|
||||
import io.gitlab.jfronny.gson.stream.JsonReader;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Migration {
|
||||
void apply(JsonReader reader) throws IOException;
|
||||
}
|
|
@ -1,9 +1,11 @@
|
|||
package io.gitlab.jfronny.libjf.config.impl.dsl;
|
||||
|
||||
import io.gitlab.jfronny.gson.JsonElement;
|
||||
import io.gitlab.jfronny.commons.throwable.Coerce;
|
||||
import io.gitlab.jfronny.gson.stream.JsonReader;
|
||||
import io.gitlab.jfronny.libjf.LibJf;
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.*;
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.dsl.CategoryBuilder;
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.dsl.Migration;
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.type.Type;
|
||||
|
||||
import java.util.*;
|
||||
|
@ -19,7 +21,7 @@ public class CategoryBuilderImpl<Builder extends CategoryBuilderImpl<Builder>> i
|
|||
public final Map<String, Consumer<ConfigCategory>> presets = new LinkedHashMap<>();
|
||||
public final List<Supplier<List<ConfigInstance>>> referencedConfigs = new LinkedList<>();
|
||||
public final List<Consumer<ConfigCategory>> verifiers = new LinkedList<>();
|
||||
public final Map<String, Consumer<JsonElement>> migrations = new LinkedHashMap<>();
|
||||
public final Map<String, Consumer<JsonReader>> migrations = new LinkedHashMap<>();
|
||||
private boolean built = false;
|
||||
|
||||
public CategoryBuilderImpl(String id, String categoryPath) {
|
||||
|
@ -169,10 +171,10 @@ public class CategoryBuilderImpl<Builder extends CategoryBuilderImpl<Builder>> i
|
|||
}
|
||||
|
||||
@Override
|
||||
public Builder addMigration(String element, Consumer<JsonElement> apply) {
|
||||
public Builder addMigration(String element, Migration migration) {
|
||||
checkBuilt();
|
||||
if (migrations.containsKey(element)) LibJf.LOGGER.warn("Duplicate migration registered for " + categoryPath + id + ": " + element + ", overriding");
|
||||
migrations.put(element, apply);
|
||||
migrations.put(element, Coerce.consumer(migration::apply).addHandler(e -> LibJf.LOGGER.error("Could not apply migration for " + element, e)));
|
||||
return asBuilder();
|
||||
}
|
||||
|
||||
|
|
|
@ -37,28 +37,30 @@ public class DefaultConfigIO {
|
|||
|
||||
private static void runActions(String id, Map<String, Action> actions, JsonReader reader) {
|
||||
try {
|
||||
if (reader.peek() == JsonToken.BEGIN_OBJECT) {
|
||||
Set<String> appeared = new HashSet<>();
|
||||
reader.beginObject();
|
||||
while (reader.peek() != JsonToken.END_OBJECT) {
|
||||
String name = reader.nextName();
|
||||
if (!actions.containsKey(name)) {
|
||||
LibJf.LOGGER.warn("Unrecognized key in config for " + id + ": " + name);
|
||||
continue;
|
||||
}
|
||||
if (!appeared.add(name)) {
|
||||
LibJf.LOGGER.warn("Duplicate key in config for " + id + ": " + name);
|
||||
continue;
|
||||
}
|
||||
actions.get(name).task.accept(reader);
|
||||
if (reader.peek() != JsonToken.BEGIN_OBJECT) {
|
||||
LibJf.LOGGER.error("Invalid config: Not a JSON object for " + id);
|
||||
return;
|
||||
}
|
||||
Set<String> appeared = new HashSet<>();
|
||||
reader.beginObject();
|
||||
while (reader.peek() != JsonToken.END_OBJECT) {
|
||||
String name = reader.nextName();
|
||||
if (!actions.containsKey(name)) {
|
||||
LibJf.LOGGER.warn("Unrecognized key in config for " + id + ": " + name);
|
||||
continue;
|
||||
}
|
||||
reader.endObject();
|
||||
actions.forEach((name, action) -> {
|
||||
if (action.required && !appeared.contains(name)) {
|
||||
LibJf.LOGGER.error("Missing entry in config for " + id + ": " + name);
|
||||
}
|
||||
});
|
||||
} LibJf.LOGGER.error("Invalid config: Not a JSON object for " + id);
|
||||
if (!appeared.add(name)) {
|
||||
LibJf.LOGGER.warn("Duplicate key in config for " + id + ": " + name);
|
||||
continue;
|
||||
}
|
||||
actions.get(name).task.accept(reader);
|
||||
}
|
||||
reader.endObject();
|
||||
actions.forEach((name, action) -> {
|
||||
if (action.required && !appeared.contains(name)) {
|
||||
LibJf.LOGGER.error("Missing entry in config for " + id + ": " + name);
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
throw new JsonParseException("Could not read config", e);
|
||||
}
|
||||
|
@ -68,8 +70,8 @@ public class DefaultConfigIO {
|
|||
Map<String, Action> actions = new HashMap<>();
|
||||
category.getEntries().forEach(entry -> actions.putIfAbsent(entry.getName(), new Action(reader -> {
|
||||
try {
|
||||
entry.loadFromJson(JsonParser.parseReader(reader));
|
||||
} catch (IllegalAccessException e) {
|
||||
entry.loadFromJson(reader);
|
||||
} catch (IllegalAccessException | IOException e) {
|
||||
LibJf.LOGGER.error("Could not set config entry value of " + entry.getName(), e);
|
||||
}
|
||||
})));
|
||||
|
@ -80,9 +82,7 @@ public class DefaultConfigIO {
|
|||
});
|
||||
if (category instanceof DslConfigCategory cat) {
|
||||
cat.migrations.forEach((id, migration) -> {
|
||||
actions.putIfAbsent(id, new Action(reader -> {
|
||||
migration.accept(JsonParser.parseReader(reader));
|
||||
}, false));
|
||||
actions.putIfAbsent(id, new Action(migration, false));
|
||||
});
|
||||
}
|
||||
return Map.copyOf(actions);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package io.gitlab.jfronny.libjf.config.impl.dsl;
|
||||
|
||||
import io.gitlab.jfronny.gson.JsonElement;
|
||||
import io.gitlab.jfronny.gson.stream.JsonReader;
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.*;
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.dsl.CategoryBuilder;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
@ -17,7 +17,7 @@ public class DslConfigCategory implements ConfigCategory {
|
|||
private final List<EntryInfo<?>> entries;
|
||||
private final Map<String, Runnable> presets;
|
||||
private final List<Supplier<List<ConfigInstance>>> referencedConfigs;
|
||||
@ApiStatus.Internal public final Map<String, Consumer<JsonElement>> migrations;
|
||||
@ApiStatus.Internal public final Map<String, Consumer<JsonReader>> migrations;
|
||||
private final Map<String, ConfigCategory> categories;
|
||||
private final Supplier<ConfigInstance> root;
|
||||
private final List<Consumer<ConfigCategory>> verifiers;
|
||||
|
@ -31,7 +31,7 @@ public class DslConfigCategory implements ConfigCategory {
|
|||
List<CategoryBuilder<?>> categories,
|
||||
Supplier<ConfigInstance> root,
|
||||
List<Consumer<ConfigCategory>> verifiers,
|
||||
Map<String, Consumer<JsonElement>> migrations) {
|
||||
Map<String, Consumer<JsonReader>> migrations) {
|
||||
this.id = id;
|
||||
this.categoryPath = categoryPath;
|
||||
this.translationPrefix = translationPrefix;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package io.gitlab.jfronny.libjf.config.impl.dsl;
|
||||
|
||||
import io.gitlab.jfronny.gson.JsonElement;
|
||||
import io.gitlab.jfronny.gson.stream.JsonReader;
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.*;
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.dsl.CategoryBuilder;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
@ -23,7 +23,7 @@ public class DslConfigInstance extends DslConfigCategory implements ConfigInstan
|
|||
List<CategoryBuilder<?>> categories,
|
||||
Supplier<ConfigInstance> root,
|
||||
List<Consumer<ConfigCategory>> verifiers,
|
||||
Map<String, Consumer<JsonElement>> migrations,
|
||||
Map<String, Consumer<JsonReader>> migrations,
|
||||
Consumer<ConfigInstance> load,
|
||||
Consumer<ConfigInstance> write,
|
||||
@Nullable Path path) {
|
||||
|
|
|
@ -4,7 +4,7 @@ import io.gitlab.jfronny.commons.serialize.gson.api.v1.GsonHolders;
|
|||
import io.gitlab.jfronny.commons.throwable.ThrowingConsumer;
|
||||
import io.gitlab.jfronny.commons.throwable.ThrowingSupplier;
|
||||
import io.gitlab.jfronny.gson.JsonElement;
|
||||
import io.gitlab.jfronny.gson.stream.JsonWriter;
|
||||
import io.gitlab.jfronny.gson.stream.*;
|
||||
import io.gitlab.jfronny.libjf.LibJf;
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.Entry;
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.EntryInfo;
|
||||
|
@ -128,38 +128,36 @@ public class DslEntryInfo<T> implements EntryInfo<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void loadFromJson(JsonElement element) throws IllegalAccessException {
|
||||
public void loadFromJson(JsonReader reader) throws IOException, IllegalAccessException {
|
||||
var next = reader.peek();
|
||||
if (type.isBool()) {
|
||||
if (element.isJsonPrimitive() && element.getAsJsonPrimitive().isBoolean()) {
|
||||
setUnchecked(element.getAsBoolean());
|
||||
}
|
||||
if (next == JsonToken.BOOLEAN) setUnchecked(reader.nextBoolean());
|
||||
else LibJf.LOGGER.error("Unexpected value for " + name + ": expected boolean but got " + next);
|
||||
} else if (type.isString()) {
|
||||
if (element.isJsonPrimitive()) {
|
||||
setUnchecked(element.getAsString());
|
||||
}
|
||||
if (next == JsonToken.STRING || next == JsonToken.NUMBER) setUnchecked(reader.nextString());
|
||||
else if (next == JsonToken.BOOLEAN) setUnchecked(Boolean.toString(reader.nextBoolean()));
|
||||
else if (next == JsonToken.NULL) setUnchecked(null);
|
||||
else LibJf.LOGGER.error("Unexpected value for " + name + ": expected string but got " + next);
|
||||
} else if (type.isInt()) {
|
||||
if (element.isJsonPrimitive() && element.getAsJsonPrimitive().isNumber()) {
|
||||
setUnchecked(element.getAsNumber().intValue());
|
||||
}
|
||||
if (next == JsonToken.NUMBER) setUnchecked(reader.nextInt());
|
||||
else LibJf.LOGGER.error("Unexpected value for " + name + ": expected number but got " + next);
|
||||
} else if (type.isLong()) {
|
||||
if (element.isJsonPrimitive() && element.getAsJsonPrimitive().isNumber()) {
|
||||
setUnchecked(element.getAsNumber().longValue());
|
||||
}
|
||||
if (next == JsonToken.NUMBER) setUnchecked(reader.nextLong());
|
||||
else LibJf.LOGGER.error("Unexpected value for " + name + ": expected number but got " + next);
|
||||
} else if (type.isDouble()) {
|
||||
if (element.isJsonPrimitive() && element.getAsJsonPrimitive().isNumber()) {
|
||||
setUnchecked(element.getAsNumber().doubleValue());
|
||||
if (next == JsonToken.NUMBER) {
|
||||
setUnchecked(reader.nextDouble());
|
||||
}
|
||||
else LibJf.LOGGER.error("Unexpected value for " + name + ": expected number but got " + next);
|
||||
} else if (type.isFloat()) {
|
||||
if (element.isJsonPrimitive() && element.getAsJsonPrimitive().isNumber()) {
|
||||
setUnchecked(element.getAsNumber().floatValue());
|
||||
}
|
||||
if (next == JsonToken.NUMBER) setUnchecked((float) reader.nextDouble());
|
||||
else LibJf.LOGGER.error("Unexpected value for " + name + ": expected number but got " + next);
|
||||
} else if (type.isEnum()) {
|
||||
Type.TEnum<T> e = (Type.TEnum<T>) type;
|
||||
if (element.isJsonPrimitive() && element.getAsJsonPrimitive().isString()) {
|
||||
setUnchecked(e.optionForString(element.getAsString()));
|
||||
}
|
||||
if (next == JsonToken.STRING) setUnchecked(e.optionForString(reader.nextString()));
|
||||
else LibJf.LOGGER.error("Unexpected value for " + name + ": expected string but got " + next);
|
||||
} else {
|
||||
setValue(GsonHolders.CONFIG.getGson().fromJson(element, type.asClass()));
|
||||
setValue(GsonHolders.CONFIG.getGson().fromJson(reader, type.asClass()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@ public class TestConfigTweaker {
|
|||
public static ConfigBuilder<?> tweak(ConfigBuilder<?> builder) {
|
||||
if (!Objects.equals("libjf-config-reflect-v1-testmod", builder.getId())) throw new IllegalStateException("No!");
|
||||
LibJf.LOGGER.info("Called config tweaker");
|
||||
return builder.addMigration("joe", jsonElement -> {
|
||||
TestConfig.disablePacks = jsonElement.getAsJsonPrimitive().getAsBoolean();
|
||||
return builder.addMigration("joe", reader -> {
|
||||
TestConfig.disablePacks = reader.nextBoolean();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue