chore(config-core): plumb TypeTokens throughout internal representation
ci/woodpecker/push/docs Pipeline was successful Details
ci/woodpecker/push/jfmod Pipeline was successful Details
ci/woodpecker/tag/docs Pipeline was successful Details
ci/woodpecker/tag/jfmod Pipeline was successful Details

This commit is contained in:
Johannes Frohnmeyer 2024-04-26 09:11:28 +02:00
parent 64f0f38668
commit d579c19f6b
Signed by: Johannes
GPG Key ID: E76429612C2929F4
10 changed files with 142 additions and 70 deletions

View File

@ -174,7 +174,7 @@ public class ConfigProcessor extends AbstractProcessor2 {
default -> { default -> {
code.add("$L, $L, ", e.min(), e.max()); code.add("$L, $L, ", e.min(), e.max());
if (tm instanceof DeclaredType dt && !dt.getTypeArguments().isEmpty()) { if (tm instanceof DeclaredType dt && !dt.getTypeArguments().isEmpty()) {
code.add("$T.ofClass(new $T<$T>() {}.getType())", Type.class, TypeToken.class, tm); code.add("$T.ofToken(new $T<$T>() {})", Type.class, TypeToken.class, tm);
} else code.add("$T.class", tm); } else code.add("$T.class", tm);
code.add(", $L, () -> $T.$L, value -> $T.$L = value", e.width(), source, name, source, name); code.add(", $L, () -> $T.$L, value -> $T.$L = value", e.width(), source, name, source, name);
} }

View File

@ -1,12 +1,14 @@
package io.gitlab.jfronny.libjf.config.api.v2; package io.gitlab.jfronny.libjf.config.api.v2;
import io.gitlab.jfronny.commons.serialize.MalformedDataException;
import io.gitlab.jfronny.commons.serialize.SerializeReader; import io.gitlab.jfronny.commons.serialize.SerializeReader;
import io.gitlab.jfronny.commons.serialize.SerializeWriter; import io.gitlab.jfronny.commons.serialize.SerializeWriter;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeToken;
import io.gitlab.jfronny.libjf.LibJf;
import io.gitlab.jfronny.libjf.config.api.v2.type.Type; import io.gitlab.jfronny.libjf.config.api.v2.type.Type;
import io.gitlab.jfronny.libjf.config.impl.dsl.DslEntryInfo; import io.gitlab.jfronny.libjf.config.impl.dsl.DslEntryInfo;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import java.io.IOException;
import java.lang.reflect.Field; import java.lang.reflect.Field;
public interface EntryInfo<T> { public interface EntryInfo<T> {
@ -77,6 +79,18 @@ public interface EntryInfo<T> {
*/ */
<TEx extends Exception, Writer extends SerializeWriter<TEx, Writer>> void writeTo(Writer writer, String translationPrefix) throws TEx, IllegalAccessException; <TEx extends Exception, Writer extends SerializeWriter<TEx, Writer>> void writeTo(Writer writer, String translationPrefix) throws TEx, IllegalAccessException;
default <TEx extends Exception, Reader extends SerializeReader<TEx, Reader>> T deserializeOneFrom(Reader reader) throws TEx, MalformedDataException {
return LibJf.MAPPER.getAdapter(getTypeToken()).deserialize(reader);
}
default <TEx extends Exception, Writer extends SerializeWriter<TEx, Writer>> void serializeOneTo(T value, String translationPrefix, Writer writer) throws TEx, MalformedDataException {
LibJf.MAPPER.getAdapter(getTypeToken()).serialize(value, writer);
}
default TypeToken<T> getTypeToken() {
return (TypeToken<T>) getValueType().asToken();
}
/** /**
* @return Get the width for this entry * @return Get the width for this entry
*/ */

View File

@ -1,5 +1,6 @@
package io.gitlab.jfronny.libjf.config.api.v2.type; package io.gitlab.jfronny.libjf.config.api.v2.type;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeToken;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
/** /**
@ -14,7 +15,19 @@ public sealed interface Type {
else if (klazz == String.class) return TString.INSTANCE; else if (klazz == String.class) return TString.INSTANCE;
else if (klazz == boolean.class || klazz == Boolean.class) return TBool.INSTANCE; else if (klazz == boolean.class || klazz == Boolean.class) return TBool.INSTANCE;
else if (klazz instanceof Class<?> k && k.isEnum()) return new TEnum<>(k); else if (klazz instanceof Class<?> k && k.isEnum()) return new TEnum<>(k);
else return new TUnknown(klazz); else return new TUnknown(klazz, TypeToken.get(klazz));
}
static Type ofToken(TypeToken<?> token) {
java.lang.reflect.Type klazz = token.getRawType();
if (klazz == int.class || klazz == Integer.class) return TInt.INSTANCE;
else if (klazz == long.class || klazz == Long.class) return TLong.INSTANCE;
else if (klazz == float.class || klazz == Float.class) return TFloat.INSTANCE;
else if (klazz == double.class || klazz == Double.class) return TDouble.INSTANCE;
else if (klazz == String.class) return TString.INSTANCE;
else if (klazz == boolean.class || klazz == Boolean.class) return TBool.INSTANCE;
else if (klazz instanceof Class<?> k && k.isEnum()) return new TEnum<>(k);
else return new TUnknown(klazz, token);
} }
default boolean isInt() { default boolean isInt() {
@ -45,6 +58,10 @@ public sealed interface Type {
} }
@Nullable java.lang.reflect.Type asClass(); @Nullable java.lang.reflect.Type asClass();
@Nullable default TypeToken<?> asToken() {
java.lang.reflect.Type type = asClass();
return type == null ? null : TypeToken.get(type);
}
String getName(); String getName();
@ -162,13 +179,13 @@ public sealed interface Type {
} }
} }
record TEnum<T>(@Nullable Class<T> klazz, String name, T[] options) implements Type { record TEnum<T>(@Nullable Class<T> klazz, TypeToken<T> token, String name, T[] options) implements Type {
public TEnum(Class<T> klazz) { public TEnum(Class<T> klazz) {
this(klazz, klazz.getSimpleName(), klazz.getEnumConstants()); this(klazz, TypeToken.get(klazz), klazz.getSimpleName(), klazz.getEnumConstants());
} }
public static TEnum<String> create(String name, String[] options) { public static TEnum<String> create(String name, String[] options) {
return new TEnum<>(null, name, options); return new TEnum<>(null, null, name, options);
} }
@Override @Override
@ -181,6 +198,11 @@ public sealed interface Type {
return klazz; return klazz;
} }
@Override
public @Nullable TypeToken<?> asToken() {
return token;
}
@Override @Override
public String getName() { public String getName() {
return name; return name;
@ -194,12 +216,17 @@ public sealed interface Type {
} }
} }
record TUnknown(java.lang.reflect.Type klazz) implements Type { record TUnknown(java.lang.reflect.Type klazz, TypeToken<?> token) implements Type {
@Override @Override
public @Nullable java.lang.reflect.Type asClass() { public @Nullable java.lang.reflect.Type asClass() {
return klazz; return klazz;
} }
@Override
public @Nullable TypeToken<?> asToken() {
return token;
}
@Override @Override
public String getName() { public String getName() {
return klazz instanceof Class<?> k ? k.getSimpleName() : klazz.getTypeName(); return klazz instanceof Class<?> k ? k.getSimpleName() : klazz.getTypeName();

View File

@ -1,6 +1,5 @@
package io.gitlab.jfronny.libjf.config.impl.dsl; package io.gitlab.jfronny.libjf.config.impl.dsl;
import io.gitlab.jfronny.commons.Serializer;
import io.gitlab.jfronny.commons.serialize.MalformedDataException; import io.gitlab.jfronny.commons.serialize.MalformedDataException;
import io.gitlab.jfronny.commons.serialize.SerializeReader; import io.gitlab.jfronny.commons.serialize.SerializeReader;
import io.gitlab.jfronny.commons.serialize.SerializeWriter; import io.gitlab.jfronny.commons.serialize.SerializeWriter;
@ -63,12 +62,12 @@ public class DslEntryInfo<T> implements EntryInfo<T> {
} catch (IllegalAccessException ignored) { } catch (IllegalAccessException ignored) {
} }
//noinspection unchecked,rawtypes //noinspection unchecked,rawtypes
return new DslEntryInfo<Object>( return new DslEntryInfo<>(
field.getName(), field.getName(),
defaultValue, defaultValue,
() -> field.get(null), () -> field.get(null),
v -> field.set(null, v), v -> field.set(null, v),
(Type) Type.ofClass(field.getGenericType()), Type.ofClass(field.getGenericType()),
entry == null ? 100 : entry.width(), entry == null ? 100 : entry.width(),
entry == null ? Double.NEGATIVE_INFINITY : entry.min(), entry == null ? Double.NEGATIVE_INFINITY : entry.min(),
entry == null ? Double.POSITIVE_INFINITY : entry.max() entry == null ? Double.POSITIVE_INFINITY : entry.max()
@ -122,7 +121,7 @@ public class DslEntryInfo<T> implements EntryInfo<T> {
} }
if (valueOriginal != value) { if (valueOriginal != value) {
try { try {
setUnchecked(value); setValue(cast(value));
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
LibJf.LOGGER.error("Could not write value", e); LibJf.LOGGER.error("Could not write value", e);
} }
@ -131,53 +130,66 @@ public class DslEntryInfo<T> implements EntryInfo<T> {
@Override @Override
public <TEx extends Exception, Reader extends SerializeReader<TEx, Reader>> void loadFromJson(Reader reader) throws TEx, IllegalAccessException { public <TEx extends Exception, Reader extends SerializeReader<TEx, Reader>> void loadFromJson(Reader reader) throws TEx, IllegalAccessException {
try {
setValue(deserializeOneFrom(reader));
} catch (MalformedDataException e) {
LibJf.LOGGER.error("Could not read " + name, e);
} catch (NothingSerializedException ignored) {
}
}
@Override
public <TEx extends Exception, Reader extends SerializeReader<TEx, Reader>> T deserializeOneFrom(Reader reader) throws TEx, MalformedDataException {
var next = reader.peek(); var next = reader.peek();
if (type.isBool()) { if (type.isBool()) {
if (next == Token.BOOLEAN) setUnchecked(reader.nextBoolean()); if (next == Token.BOOLEAN) return cast(reader.nextBoolean());
else LibJf.LOGGER.error("Unexpected value for " + name + ": expected boolean but got " + next); else LibJf.LOGGER.error("Unexpected value for " + name + ": expected boolean but got " + next);
} else if (type.isString()) { } else if (type.isString()) {
if (next == Token.STRING || next == Token.NUMBER) setUnchecked(reader.nextString()); if (next == Token.STRING || next == Token.NUMBER) return cast(reader.nextString());
else if (next == Token.BOOLEAN) setUnchecked(Boolean.toString(reader.nextBoolean())); else if (next == Token.BOOLEAN) return cast(Boolean.toString(reader.nextBoolean()));
else if (next == Token.NULL) { else if (next == Token.NULL) {
reader.nextNull(); reader.nextNull();
setUnchecked(null); return cast(null);
} else LibJf.LOGGER.error("Unexpected value for " + name + ": expected string but got " + next); } else LibJf.LOGGER.error("Unexpected value for " + name + ": expected string but got " + next);
} else if (type.isInt()) { } else if (type.isInt()) {
if (next == Token.NUMBER) setUnchecked(reader.nextInt()); if (next == Token.NUMBER) return cast(reader.nextInt());
else LibJf.LOGGER.error("Unexpected value for " + name + ": expected number but got " + next); else LibJf.LOGGER.error("Unexpected value for " + name + ": expected number but got " + next);
} else if (type.isLong()) { } else if (type.isLong()) {
if (next == Token.NUMBER) setUnchecked(reader.nextLong()); if (next == Token.NUMBER) return cast(reader.nextLong());
else LibJf.LOGGER.error("Unexpected value for " + name + ": expected number but got " + next); else LibJf.LOGGER.error("Unexpected value for " + name + ": expected number but got " + next);
} else if (type.isDouble()) { } else if (type.isDouble()) {
if (next == Token.NUMBER) { if (next == Token.NUMBER) {
setUnchecked(reader.nextDouble()); return cast(reader.nextDouble());
} }
else LibJf.LOGGER.error("Unexpected value for " + name + ": expected number but got " + next); else LibJf.LOGGER.error("Unexpected value for " + name + ": expected number but got " + next);
} else if (type.isFloat()) { } else if (type.isFloat()) {
if (next == Token.NUMBER) setUnchecked((float) reader.nextDouble()); if (next == Token.NUMBER) return cast((float) reader.nextDouble());
else LibJf.LOGGER.error("Unexpected value for " + name + ": expected number but got " + next); else LibJf.LOGGER.error("Unexpected value for " + name + ": expected number but got " + next);
} else if (type.isEnum()) { } else if (type.isEnum()) {
Type.TEnum<T> e = (Type.TEnum<T>) type; Type.TEnum<T> e = (Type.TEnum<T>) type;
if (next == Token.STRING) setUnchecked(e.optionForString(reader.nextString())); if (next == Token.STRING) return cast(e.optionForString(reader.nextString()));
else LibJf.LOGGER.error("Unexpected value for " + name + ": expected string but got " + next); else LibJf.LOGGER.error("Unexpected value for " + name + ": expected string but got " + next);
} else { } else {
try { try {
setValue((T) LibJf.MAPPER.getAdapter(TypeToken.get(type.asClass())).deserialize(reader)); return cast((T) LibJf.MAPPER.getAdapter(type.asToken()).deserialize(reader));
} catch (MalformedDataException e) { } catch (MalformedDataException e) {
LibJf.LOGGER.error("Could not read " + name, e); LibJf.LOGGER.error("Could not read " + name, e);
} }
} }
throw new NothingSerializedException();
} }
@SuppressWarnings("unchecked") private T cast(Object object) {
private void setUnchecked(Object object) throws IllegalAccessException { return (T) object;
if (object == null) return;
setValue((T) object);
} }
@Override @Override
public <TEx extends Exception, Writer extends SerializeWriter<TEx, Writer>> void writeTo(Writer writer, String translationPrefix) throws TEx, IllegalAccessException { public <TEx extends Exception, Writer extends SerializeWriter<TEx, Writer>> void writeTo(Writer writer, String translationPrefix) throws TEx, IllegalAccessException {
T value = getValue(); serializeOneTo(getValue(), translationPrefix, writer);
}
@Override
public <TEx extends Exception, Writer extends SerializeWriter<TEx, Writer>> void serializeOneTo(T value, String translationPrefix, Writer writer) throws TEx {
String commentText; String commentText;
if ((commentText = JfConfigSafe.TRANSLATION_SUPPLIER.apply(translationPrefix + getName() + ".tooltip")) != null) { if ((commentText = JfConfigSafe.TRANSLATION_SUPPLIER.apply(translationPrefix + getName() + ".tooltip")) != null) {
writer.comment(commentText); writer.comment(commentText);
@ -187,7 +199,7 @@ public class DslEntryInfo<T> implements EntryInfo<T> {
} }
writer.name(name); writer.name(name);
try { try {
LibJf.MAPPER.getAdapter((TypeToken<T>) TypeToken.get(Objects.requireNonNullElse(type.asClass(), String.class))).serialize(value, writer); LibJf.MAPPER.getAdapter((TypeToken<T>) Objects.requireNonNullElse(type.asToken(), TypeToken.get(String.class))).serialize(value, writer);
} catch (MalformedDataException e) { } catch (MalformedDataException e) {
LibJf.LOGGER.error("Could not write " + name, e); LibJf.LOGGER.error("Could not write " + name, e);
} }

View File

@ -0,0 +1,4 @@
package io.gitlab.jfronny.libjf.config.impl.dsl;
public class NothingSerializedException extends RuntimeException {
}

View File

@ -1,5 +1,6 @@
package io.gitlab.jfronny.libjf.config.impl.network.rci.entry; package io.gitlab.jfronny.libjf.config.impl.network.rci.entry;
import io.gitlab.jfronny.commons.serialize.MalformedDataException;
import io.gitlab.jfronny.commons.serialize.SerializeReader; import io.gitlab.jfronny.commons.serialize.SerializeReader;
import io.gitlab.jfronny.commons.serialize.SerializeWriter; import io.gitlab.jfronny.commons.serialize.SerializeWriter;
import io.gitlab.jfronny.libjf.config.api.v2.EntryInfo; import io.gitlab.jfronny.libjf.config.api.v2.EntryInfo;
@ -39,6 +40,16 @@ public abstract class MirrorEntryInfoBase<T> extends MirrorObject implements Ent
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public <TEx extends Exception, Reader extends SerializeReader<TEx, Reader>> T deserializeOneFrom(Reader reader) throws TEx, MalformedDataException {
throw new UnsupportedOperationException();
}
@Override
public <TEx extends Exception, Writer extends SerializeWriter<TEx, Writer>> void serializeOneTo(T value, String translationPrefix, Writer writer) throws TEx, MalformedDataException {
throw new UnsupportedOperationException();
}
@Override @Override
public void fix() { public void fix() {
PacketByteBuf buf = PacketByteBufs.create(); PacketByteBuf buf = PacketByteBufs.create();

View File

@ -1,8 +1,6 @@
package io.gitlab.jfronny.libjf.config.impl.ui.tiny; package io.gitlab.jfronny.libjf.config.impl.ui.tiny;
import io.gitlab.jfronny.commons.Serializer;
import io.gitlab.jfronny.commons.serialize.Transport; import io.gitlab.jfronny.commons.serialize.Transport;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeToken;
import io.gitlab.jfronny.commons.serialize.json.JsonReader; import io.gitlab.jfronny.commons.serialize.json.JsonReader;
import io.gitlab.jfronny.libjf.LibJf; import io.gitlab.jfronny.libjf.LibJf;
import io.gitlab.jfronny.libjf.config.api.v2.ConfigInstance; import io.gitlab.jfronny.libjf.config.api.v2.ConfigInstance;
@ -26,47 +24,48 @@ public class TinyConfigScreenFactory implements ConfigScreenFactory<Screen, Tiny
&& config.getPresets().keySet().stream().allMatch(s -> s.equals(CategoryBuilder.CONFIG_PRESET_DEFAULT)) && config.getPresets().keySet().stream().allMatch(s -> s.equals(CategoryBuilder.CONFIG_PRESET_DEFAULT))
&& config.getReferencedConfigs().isEmpty() && config.getReferencedConfigs().isEmpty()
&& config.getCategories().isEmpty()) { && config.getCategories().isEmpty()) {
EntryInfo entry = config.getEntries().getFirst(); EntryInfo<?> entry = config.getEntries().getFirst();
Type type = entry.supportsRepresentation() ? entry.getValueType() : null; Type type = entry.supportsRepresentation() ? entry.getValueType() : null;
if (type != null && !type.isInt() && !type.isLong() && !type.isFloat() && !type.isDouble() && !type.isString() && !type.isBool() && !type.isEnum()) { if (type != null && !type.isInt() && !type.isLong() && !type.isFloat() && !type.isDouble() && !type.isString() && !type.isBool() && !type.isEnum()) {
final String jsonified; return createJson(config, parent, entry);
try {
var value = entry.getValue();
jsonified = LibJf.LENIENT_TRANSPORT.write(writer -> LibJf.MAPPER.serialize(value, writer));
} catch (IllegalAccessException | IOException e) {
throw new RuntimeException(e);
}
String key = config.getTranslationPrefix() + entry.getName();
return new Built(new EditorScreen(
Text.translatable(key),
I18n.hasTranslation(key + ".tooltip") ? Text.translatable(key + ".tooltip") : null,
parent,
jsonified,
json -> {
try {
entry.setValue(LibJf.LENIENT_TRANSPORT.read(
json,
(Transport.Returnable<JsonReader, ? extends Object, IOException>) reader -> LibJf.MAPPER
.getAdapter(TypeToken.get(type.asClass()))
.deserialize(reader)));
entry.setValue(Serializer.getInstance().deserialize(json, type.asClass()));
config.write();
} catch (Throwable e) {
LibJf.LOGGER.error("Could not write element", e);
SystemToast.add(
MinecraftClient.getInstance().getToastManager(),
SystemToast.Type.PACK_LOAD_FAILURE,
Text.translatable("libjf-config-ui-tiny.entry.json.write.fail.title"),
Text.translatable("libjf-config-ui-tiny.entry.json.write.fail.description")
);
}
}
));
} }
} }
return new Built(new TinyConfigScreen(config, parent)); return new Built(new TinyConfigScreen(config, parent));
} }
private <T> Built createJson(ConfigInstance config, Screen parent, EntryInfo<T> entry) {
final String jsonified;
try {
var value = entry.getValue();
jsonified = LibJf.LENIENT_TRANSPORT.write(writer -> entry.serializeOneTo(value, config.getTranslationPrefix(), writer));
} catch (IllegalAccessException | IOException e) {
throw new RuntimeException(e);
}
String key = config.getTranslationPrefix() + entry.getName();
return new Built(new EditorScreen(
Text.translatable(key),
I18n.hasTranslation(key + ".tooltip") ? Text.translatable(key + ".tooltip") : null,
parent,
jsonified,
json -> {
try {
entry.setValue(LibJf.LENIENT_TRANSPORT.read(
json,
(Transport.Returnable<JsonReader, ? extends T, IOException>) entry::deserializeOneFrom));
config.write();
} catch (Throwable e) {
LibJf.LOGGER.error("Could not write element", e);
SystemToast.add(
MinecraftClient.getInstance().getToastManager(),
SystemToast.Type.PACK_LOAD_FAILURE,
Text.translatable("libjf-config-ui-tiny.entry.json.write.fail.title"),
Text.translatable("libjf-config-ui-tiny.entry.json.write.fail.description")
);
}
}
));
}
@Override @Override
public int getPriority() { public int getPriority() {
return 0; return 0;

View File

@ -1,9 +1,7 @@
package io.gitlab.jfronny.libjf.config.impl.ui.tiny.entry; package io.gitlab.jfronny.libjf.config.impl.ui.tiny.entry;
import io.gitlab.jfronny.commons.Serializer;
import io.gitlab.jfronny.commons.ref.R; import io.gitlab.jfronny.commons.ref.R;
import io.gitlab.jfronny.commons.serialize.Transport; import io.gitlab.jfronny.commons.serialize.Transport;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeToken;
import io.gitlab.jfronny.commons.serialize.json.JsonReader; import io.gitlab.jfronny.commons.serialize.json.JsonReader;
import io.gitlab.jfronny.commons.throwable.Try; import io.gitlab.jfronny.commons.throwable.Try;
import io.gitlab.jfronny.libjf.LibJf; import io.gitlab.jfronny.libjf.LibJf;
@ -175,7 +173,7 @@ public class EntryInfoWidgetBuilder {
final String jsonified; final String jsonified;
if (state.tempValue == null) { if (state.tempValue == null) {
try { try {
jsonified = LibJf.LENIENT_TRANSPORT.write(writer -> LibJf.MAPPER.serialize(state.cachedValue, writer)); jsonified = LibJf.LENIENT_TRANSPORT.write(writer -> info.serializeOneTo(state.cachedValue, config.getTranslationPrefix(), writer));
} catch (Throwable e) { } catch (Throwable e) {
LibJf.LOGGER.error("Could not stringify element", e); LibJf.LOGGER.error("Could not stringify element", e);
SystemToast.add( SystemToast.add(
@ -199,9 +197,8 @@ public class EntryInfoWidgetBuilder {
try { try {
state.updateCache(LibJf.LENIENT_TRANSPORT.read( state.updateCache(LibJf.LENIENT_TRANSPORT.read(
json, json,
(Transport.Returnable<JsonReader, ? extends T, IOException>) reader -> LibJf.MAPPER (Transport.Returnable<JsonReader, ? extends T, IOException>) info::deserializeOneFrom
.getAdapter((TypeToken<T>) TypeToken.get(info.getValueType().asClass())) ));
.deserialize(reader)));
state.tempValue = null; state.tempValue = null;
} catch (Throwable e) { } catch (Throwable e) {
LibJf.LOGGER.error("Could not write element", e); LibJf.LOGGER.error("Could not write element", e);

View File

@ -1,4 +1,6 @@
{ {
"libjf-config-ui-tiny.entry.json.read.fail.title": "Could not read", "libjf-config-ui-tiny.entry.json.read.fail.title": "Could not read",
"libjf-config-ui-tiny.entry.json.read.fail.description": "The given entry could not be stringified. Please edit the config manually" "libjf-config-ui-tiny.entry.json.read.fail.description": "The given entry could not be read from a string. Please edit the config manually",
"libjf-config-ui-tiny.entry.json.write.fail.title": "Could not write",
"libjf-config-ui-tiny.entry.json.write.fail.description": "The given entry could not be stringified. Please edit the config manually"
} }

View File

@ -1,7 +1,10 @@
package io.gitlab.jfronny.libjf.config.test.tiny; package io.gitlab.jfronny.libjf.config.test.tiny;
import io.gitlab.jfronny.commons.data.String2ObjectMap;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeToken;
import io.gitlab.jfronny.libjf.config.api.v2.JfCustomConfig; import io.gitlab.jfronny.libjf.config.api.v2.JfCustomConfig;
import io.gitlab.jfronny.libjf.config.api.v2.dsl.DSL; import io.gitlab.jfronny.libjf.config.api.v2.dsl.DSL;
import io.gitlab.jfronny.libjf.config.api.v2.type.Type;
public class TestConfig implements JfCustomConfig { public class TestConfig implements JfCustomConfig {
private int value1 = 0; private int value1 = 0;
@ -12,6 +15,7 @@ public class TestConfig implements JfCustomConfig {
private int value4 = 0; private int value4 = 0;
private String value5 = ""; private String value5 = "";
private boolean value6 = false; private boolean value6 = false;
private String2ObjectMap<String> map = new String2ObjectMap<>();
@Override @Override
public void register(DSL.Defaulted dsl) { public void register(DSL.Defaulted dsl) {
@ -30,6 +34,8 @@ public class TestConfig implements JfCustomConfig {
.value("value5", value5, () -> value5, v -> value5 = v) .value("value5", value5, () -> value5, v -> value5 = v)
).category("ca6", builder1 -> builder1 ).category("ca6", builder1 -> builder1
.value("value6", value6, () -> value6, v -> value6 = v) .value("value6", value6, () -> value6, v -> value6 = v)
).category("ca7", builder1 -> builder1
.value("mappy", map, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Type.ofToken(new TypeToken<String2ObjectMap<String>>() {}), 100, () -> map, v -> map = v)
) )
); );
} }