Respackopts/src/main/java/io/gitlab/jfronny/respackopts/gson/ConfigEntryTypeAdapter.java

79 lines
4.3 KiB
Java

package io.gitlab.jfronny.respackopts.gson;
import io.gitlab.jfronny.commons.serialize.MalformedDataException;
import io.gitlab.jfronny.commons.serialize.SerializeReader;
import io.gitlab.jfronny.commons.serialize.SerializeWriter;
import io.gitlab.jfronny.commons.serialize.databind.api.SerializerFor;
import io.gitlab.jfronny.commons.serialize.databind.api.TypeAdapter;
import io.gitlab.jfronny.commons.serialize.emulated.DataElement;
import io.gitlab.jfronny.commons.serialize.emulated.EmulatedReader;
import io.gitlab.jfronny.commons.serialize.emulated.EmulatedWriter;
import io.gitlab.jfronny.respackopts.Respackopts;
import io.gitlab.jfronny.respackopts.gson.entry.BooleanEntrySerializer;
import io.gitlab.jfronny.respackopts.gson.entry.EnumEntrySerializer;
import io.gitlab.jfronny.respackopts.gson.entry.NumericEntrySerializer;
import io.gitlab.jfronny.respackopts.model.tree.*;
@SerializerFor(targets = ConfigEntry.class)
public class ConfigEntryTypeAdapter extends TypeAdapter<ConfigEntry<?>> {
@Override
public <TEx extends Exception, Writer extends SerializeWriter<TEx, Writer>> void serialize(ConfigEntry<?> entry, Writer writer) throws TEx, MalformedDataException {
switch (entry) {
case ConfigBooleanEntry bl -> GC_ConfigBooleanEntry.serialize(bl, writer);
case ConfigNumericEntry num -> GC_ConfigNumericEntry.serialize(num, writer);
case ConfigEnumEntry en -> GC_ConfigEnumEntry.serialize(en, writer);
case ConfigBranch br -> GC_ConfigBranch.serialize(br, writer);
default -> throw new MalformedDataException("Unknown entry type: " + entry.getClass().getName());
}
}
@Override
public <TEx extends Exception, Reader extends SerializeReader<TEx, Reader>> ConfigEntry<?> deserialize(Reader reader) throws TEx, MalformedDataException {
return switch (reader.peek()) {
case BOOLEAN -> GC_ConfigBooleanEntry.deserialize(reader);
case NUMBER -> GC_ConfigNumericEntry.deserialize(reader);
case STRING, BEGIN_ARRAY -> GC_ConfigEnumEntry.deserialize(reader);
case BEGIN_OBJECT -> {
final ConfigEntry<?> entry;
String type = null;
DataElement.Object de;
reader.beginObject();
try (EmulatedWriter ew = new EmulatedWriter()) {
ew.beginObject();
while (reader.hasNext()) {
String key;
ew.name(key = reader.nextName());
if (key.equals("type")) ew.value(type = reader.nextString());
else reader.copyTo(ew);
}
ew.endObject();
de = (DataElement.Object) ew.get();
}
reader.endObject();
if (type != null) {
if (BooleanEntrySerializer.TYPES.contains(type)) {
entry = GC_ConfigBooleanEntry.deserialize(new EmulatedReader(de));
} else if (NumericEntrySerializer.TYPES.contains(type)) {
var e = GC_ConfigNumericEntry.deserialize(new EmulatedReader(de));
entry = NumericEntrySerializer.INT_TYPES.contains(type) ? e.asInteger() : e;
} else if (EnumEntrySerializer.TYPES.contains(type)) {
entry = GC_ConfigEnumEntry.deserialize(new EmulatedReader(de));
} else {
throw new MalformedDataException("Invalid type for entry: " + type);
}
} else {
if (de.members().keySet().stream().allMatch(k -> "default".equals(k) || "min".equals(k) || "max".equals(k))) {
Respackopts.LOGGER.info("No \"type\" property for non-branch entry object, assuming slider");
entry = GC_ConfigNumericEntry.deserialize(new EmulatedReader(de));
} else {
entry = GC_ConfigBranch.deserialize(new EmulatedReader(de));
}
}
yield entry;
}
case NULL -> throw new MalformedDataException("Unexpected null value for entry");
default -> throw new MalformedDataException("Invalid data type for entry");
};
}
}