198 lines
7.3 KiB
Java
198 lines
7.3 KiB
Java
package io.gitlab.jfronny.libjf.config.impl.dsl;
|
|
|
|
import io.gitlab.jfronny.commons.serialize.gson.api.v2.GsonHolders;
|
|
import io.gitlab.jfronny.commons.throwable.ThrowingConsumer;
|
|
import io.gitlab.jfronny.commons.throwable.ThrowingSupplier;
|
|
import io.gitlab.jfronny.gson.stream.*;
|
|
import io.gitlab.jfronny.libjf.LibJf;
|
|
import io.gitlab.jfronny.libjf.config.api.v2.Entry;
|
|
import io.gitlab.jfronny.libjf.config.api.v2.EntryInfo;
|
|
import io.gitlab.jfronny.libjf.config.api.v2.type.Type;
|
|
import io.gitlab.jfronny.libjf.config.impl.entrypoint.JfConfigSafe;
|
|
|
|
import java.io.IOException;
|
|
import java.lang.reflect.Field;
|
|
import java.util.Arrays;
|
|
import java.util.Objects;
|
|
import java.util.stream.Collectors;
|
|
|
|
public class DslEntryInfo<T> implements EntryInfo<T> {
|
|
private final String name;
|
|
private final T defaultValue;
|
|
private final ThrowingSupplier<T, IllegalAccessException> get;
|
|
private final ThrowingConsumer<T, IllegalAccessException> set;
|
|
private final Type type;
|
|
private final int width;
|
|
private final double minValue;
|
|
private final double maxValue;
|
|
|
|
public DslEntryInfo(String name,
|
|
T defaultValue,
|
|
ThrowingSupplier<T, IllegalAccessException> get,
|
|
ThrowingConsumer<T, IllegalAccessException> set,
|
|
Type type,
|
|
int width,
|
|
double minValue,
|
|
double maxValue) {
|
|
this.name = name;
|
|
this.defaultValue = defaultValue;
|
|
this.get = get;
|
|
this.set = set;
|
|
this.type = type;
|
|
this.width = width;
|
|
this.minValue = minValue;
|
|
this.maxValue = maxValue;
|
|
}
|
|
|
|
public DslEntryInfo(String name,
|
|
T def,
|
|
ThrowingSupplier<T, IllegalAccessException> get,
|
|
ThrowingConsumer<T, IllegalAccessException> set,
|
|
Type type) {
|
|
this(name, def, get, set, type, 100, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
|
|
}
|
|
|
|
public static DslEntryInfo<Object> ofField(Field field) {
|
|
Entry entry = field.getAnnotation(Entry.class);
|
|
Object defaultValue = null;
|
|
try {
|
|
defaultValue = field.get(null);
|
|
} catch (IllegalAccessException ignored) {
|
|
}
|
|
//noinspection unchecked,rawtypes
|
|
return new DslEntryInfo<Object>(
|
|
field.getName(),
|
|
defaultValue,
|
|
() -> field.get(null),
|
|
v -> field.set(null, v),
|
|
(Type) Type.ofClass(field.getGenericType()),
|
|
entry == null ? 100 : entry.width(),
|
|
entry == null ? Double.NEGATIVE_INFINITY : entry.min(),
|
|
entry == null ? Double.POSITIVE_INFINITY : entry.max()
|
|
);
|
|
}
|
|
|
|
@Override
|
|
public String getName() {
|
|
return name;
|
|
}
|
|
|
|
@Override
|
|
public T getDefault() {
|
|
return defaultValue;
|
|
}
|
|
|
|
@Override
|
|
public T getValue() throws IllegalAccessException {
|
|
return get.get();
|
|
}
|
|
|
|
@Override
|
|
public void setValue(T value) throws IllegalAccessException {
|
|
set.accept(value);
|
|
}
|
|
|
|
@Override
|
|
public Type getValueType() {
|
|
return type;
|
|
}
|
|
|
|
@Override
|
|
public void fix() {
|
|
Object value;
|
|
try {
|
|
value = getValue();
|
|
} catch (IllegalAccessException e) {
|
|
LibJf.LOGGER.error("Could not read value", e);
|
|
return;
|
|
}
|
|
final Object valueOriginal = value;
|
|
if (value instanceof final Integer v) {
|
|
if (v < minValue) value = (int)minValue;
|
|
if (v > maxValue) value = (int)maxValue;
|
|
} else if (value instanceof final Float v) {
|
|
if (v < minValue) value = (float)minValue;
|
|
if (v > maxValue) value = (float)maxValue;
|
|
} else if (value instanceof final Double v) {
|
|
if (v < minValue) value = minValue;
|
|
if (v > maxValue) value = maxValue;
|
|
}
|
|
if (valueOriginal != value) {
|
|
try {
|
|
setUnchecked(value);
|
|
} catch (IllegalAccessException e) {
|
|
LibJf.LOGGER.error("Could not write value", e);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void loadFromJson(JsonReader reader) throws IOException, IllegalAccessException {
|
|
var next = reader.peek();
|
|
if (type.isBool()) {
|
|
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 (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 (next == JsonToken.NUMBER) setUnchecked(reader.nextInt());
|
|
else LibJf.LOGGER.error("Unexpected value for " + name + ": expected number but got " + next);
|
|
} else if (type.isLong()) {
|
|
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 (next == JsonToken.NUMBER) {
|
|
setUnchecked(reader.nextDouble());
|
|
}
|
|
else LibJf.LOGGER.error("Unexpected value for " + name + ": expected number but got " + next);
|
|
} else if (type.isFloat()) {
|
|
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 (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(reader, type.asClass()));
|
|
}
|
|
}
|
|
|
|
@SuppressWarnings("unchecked")
|
|
private void setUnchecked(Object object) throws IllegalAccessException {
|
|
if (object == null) return;
|
|
setValue((T) object);
|
|
}
|
|
|
|
@Override
|
|
public void writeTo(JsonWriter writer, String translationPrefix) throws IOException, IllegalAccessException {
|
|
T value = getValue();
|
|
String commentText;
|
|
if ((commentText = JfConfigSafe.TRANSLATION_SUPPLIER.apply(translationPrefix + getName() + ".tooltip")) != null) {
|
|
writer.comment(commentText);
|
|
}
|
|
if (type.isEnum()) {
|
|
writer.comment("Valid: [" + Arrays.stream(((Type.TEnum<T>)type).options()).map(Objects::toString).collect(Collectors.joining(", ")) + "]");
|
|
}
|
|
writer.name(name);
|
|
GsonHolders.CONFIG.getGson().toJson(value, Objects.requireNonNullElse(type.asClass(), String.class), writer);
|
|
}
|
|
|
|
@Override
|
|
public int getWidth() {
|
|
return width;
|
|
}
|
|
|
|
@Override
|
|
public double getMinValue() {
|
|
return minValue;
|
|
}
|
|
|
|
@Override
|
|
public double getMaxValue() {
|
|
return maxValue;
|
|
}
|
|
}
|