FIX: Use custom instances rather than utilising reflection
This commit is contained in:
parent
353c75f0a6
commit
f237fd3848
|
@ -12,6 +12,8 @@ import org.tomlj.TomlParseError;
|
||||||
import org.tomlj.TomlParseResult;
|
import org.tomlj.TomlParseResult;
|
||||||
import org.tomlj.TomlTable;
|
import org.tomlj.TomlTable;
|
||||||
|
|
||||||
|
import fun.bb1.toml.tomj.TomlJ;
|
||||||
|
|
||||||
public final class Toml {
|
public final class Toml {
|
||||||
|
|
||||||
private Toml() { }
|
private Toml() { }
|
||||||
|
@ -62,7 +64,7 @@ public final class Toml {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final @Nullable Object recurse(@NotNull final ITomlElement toml) {
|
private static final @Nullable Object recurse(@NotNull final ITomlElement toml) {
|
||||||
return new TomlJBuilder().recurse(toml);
|
return TomlJ.recurse(toml);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,165 +0,0 @@
|
||||||
package fun.bb1.toml;
|
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.InaccessibleObjectException;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.tomlj.TomlArray;
|
|
||||||
import org.tomlj.TomlInvalidTypeException;
|
|
||||||
import org.tomlj.TomlPosition;
|
|
||||||
import org.tomlj.TomlTable;
|
|
||||||
import org.tomlj.TomlVersion;
|
|
||||||
|
|
||||||
import fun.bb1.exceptions.handler.ExceptionHandler;
|
|
||||||
|
|
||||||
final class TomlJBuilder {
|
|
||||||
|
|
||||||
private static final @NotNull Class<?> TOML_TABLE = ExceptionHandler.handle(()->Class.forName("org.tomlj.MutableTomlTable"));
|
|
||||||
private static final @NotNull Constructor<?> TOML_TABLE_CONSTRUCTOR = ExceptionHandler.handle(()->TOML_TABLE.getConstructor(TomlVersion.class, TomlPosition.class));
|
|
||||||
private static final @NotNull Field TOML_TABLE_PROPERTIES = ExceptionHandler.handle(()->TOML_TABLE.getField("properties"));
|
|
||||||
|
|
||||||
private static final @NotNull Class<?> TOML_TABLE_ELEMENT = ExceptionHandler.handle(()->Class.forName("org.tomlj.MutableTomlTable$Element"));
|
|
||||||
private static final @NotNull Constructor<?> TOML_TABLE_ELEMENT_CONSTRUCTOR = ExceptionHandler.handle(()->TOML_TABLE_ELEMENT.getConstructor(Object.class, TomlPosition.class));
|
|
||||||
|
|
||||||
private static final @NotNull Class<?> TOML_ARRAY = ExceptionHandler.handle(()->Class.forName("org.tomlj.MutableTomlArray"));
|
|
||||||
private static final @NotNull Method TOML_ARRAY_CREATE = ExceptionHandler.handle(()->TOML_ARRAY.getMethod("create", TomlVersion.class, boolean.class));
|
|
||||||
private static final @NotNull Method TOML_ARRAY_APPEND = ExceptionHandler.handle(()->TOML_ARRAY.getMethod("append", Object.class, TomlPosition.class));
|
|
||||||
|
|
||||||
private int row = 1;
|
|
||||||
private int column = 1;
|
|
||||||
|
|
||||||
TomlJBuilder() {
|
|
||||||
try {
|
|
||||||
TOML_TABLE_CONSTRUCTOR.setAccessible(true);
|
|
||||||
TOML_TABLE_PROPERTIES.setAccessible(true);
|
|
||||||
TOML_TABLE_ELEMENT_CONSTRUCTOR.setAccessible(true);
|
|
||||||
TOML_ARRAY_CREATE.setAccessible(true);
|
|
||||||
TOML_ARRAY_APPEND.setAccessible(true);
|
|
||||||
} catch (InaccessibleObjectException | SecurityException e) {
|
|
||||||
System.err.println("Failed to open up the required fields for toml, please report this as a bug!");
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public final @Nullable Object recurse(@NotNull final ITomlElement toml) {
|
|
||||||
if (toml instanceof TomlPrimitive primitive) return primitive.getInner();
|
|
||||||
if (toml instanceof fun.bb1.toml.TomlArray tomlArray) {
|
|
||||||
@Nullable final TomlArray array = buildArray();
|
|
||||||
if (array == null) return null;
|
|
||||||
for (int i = 0; i < tomlArray.getSize(); i++) {
|
|
||||||
int row = this.row;
|
|
||||||
this.row++;
|
|
||||||
@NotNull final ITomlElement preConversionObject = tomlArray.get(i);
|
|
||||||
if (preConversionObject.isTomlArray() || preConversionObject.isTomlObject()) {
|
|
||||||
this.column++;
|
|
||||||
}
|
|
||||||
@Nullable final Object convertedObject = recurse(preConversionObject);
|
|
||||||
if (preConversionObject.isTomlArray() || preConversionObject.isTomlObject()) {
|
|
||||||
this.column--;
|
|
||||||
}
|
|
||||||
if (convertedObject == null) {
|
|
||||||
this.row--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!appendToArray(array, convertedObject, row)) {
|
|
||||||
this.row--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
@NotNull final TomlObject tomlObject = toml.getAsTomlObject();
|
|
||||||
@Nullable final TomlTable table = buildTable();
|
|
||||||
if (table == null) return null;
|
|
||||||
for (@NotNull final String key : tomlObject) {
|
|
||||||
@NotNull final ITomlElement preConversionObject = tomlObject.get(key);
|
|
||||||
int row = this.row;
|
|
||||||
this.row++;
|
|
||||||
if (preConversionObject.isTomlArray() || preConversionObject.isTomlObject()) {
|
|
||||||
this.column++;
|
|
||||||
}
|
|
||||||
@Nullable final Object convertedObject = recurse(preConversionObject);
|
|
||||||
if (preConversionObject.isTomlArray() || preConversionObject.isTomlObject()) {
|
|
||||||
this.column--;
|
|
||||||
}
|
|
||||||
if (convertedObject == null) {
|
|
||||||
this.row--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!putOnTable(table, key, convertedObject, row)) {
|
|
||||||
this.row--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return tomlObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final @NotNull TomlPosition getPosition() {
|
|
||||||
return TomlPosition.positionAt(this.row, this.column);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final @Nullable TomlArray buildArray() {
|
|
||||||
return (TomlArray) new ExceptionHandler<>(()->TOML_ARRAY_CREATE.invoke(null, TomlVersion.LATEST)).catcher((e) -> {
|
|
||||||
System.err.println("Failed to load TomlArray instance via reflection, please report this as a bug!");
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}).get();
|
|
||||||
}
|
|
||||||
|
|
||||||
private final boolean appendToArray(@NotNull final TomlArray tomlArray, @NotNull Object convertedObject, int row) {
|
|
||||||
try {
|
|
||||||
if (convertedObject instanceof Double || convertedObject instanceof Float) {
|
|
||||||
convertedObject = ((Number)convertedObject).floatValue();
|
|
||||||
} else if (convertedObject instanceof Number num) {
|
|
||||||
convertedObject = num.intValue();
|
|
||||||
}
|
|
||||||
TOML_ARRAY_APPEND.invoke(tomlArray, convertedObject, TomlPosition.positionAt(row, this.column));
|
|
||||||
return true;
|
|
||||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
|
||||||
System.err.println("Failed to append to a TomlArray instance via reflection, please report this as a bug!");
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (TomlInvalidTypeException t) {
|
|
||||||
System.err.println("Failed to append to a TomlArray instance via reflection, this may be an issue with your Toml!");
|
|
||||||
t.printStackTrace();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final @Nullable TomlTable buildTable() {
|
|
||||||
return (TomlTable) new ExceptionHandler<>(()->TOML_TABLE_CONSTRUCTOR.newInstance(TomlVersion.LATEST, getPosition())).catcher((e) -> {
|
|
||||||
System.err.println("Failed to load TomlTable instance via reflection, please report this as a bug!");
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}).get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public final boolean putOnTable(@NotNull final TomlTable table, @NotNull final String key, @NotNull final Object convertedObject, int row) {
|
|
||||||
final @Nullable Map<String, Object> properties = getPropertiesOfTable(table);
|
|
||||||
if (properties == null) return false;
|
|
||||||
@Nullable final Object builtElement = buildTableElement(convertedObject);
|
|
||||||
if (builtElement == null) return false;
|
|
||||||
properties.put(key, builtElement);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private final @Nullable Map<String, Object> getPropertiesOfTable(@NotNull final TomlTable tomlTable) {
|
|
||||||
return (Map<String, Object>) new ExceptionHandler<>(()->TOML_TABLE_PROPERTIES.get(tomlTable)).catcher((e) -> {
|
|
||||||
System.err.println("Failed to get TomlTable's properties via reflection, please report this as a bug!");
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}).get();
|
|
||||||
}
|
|
||||||
|
|
||||||
private final @Nullable Object buildTableElement(@NotNull final Object toContain) {
|
|
||||||
return (TomlTable) new ExceptionHandler<>(()->TOML_TABLE_ELEMENT_CONSTRUCTOR.newInstance(toContain, getPosition())).catcher((e) -> {
|
|
||||||
System.err.println("Failed to load TomlTable$Element instance via reflection, please report this as a bug!");
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}).get();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
33
src/main/java/fun/bb1/toml/tomj/TomlJ.java
Normal file
33
src/main/java/fun/bb1/toml/tomj/TomlJ.java
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
package fun.bb1.toml.tomj;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.ApiStatus.Internal;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import fun.bb1.toml.ITomlElement;
|
||||||
|
import fun.bb1.toml.TomlObject;
|
||||||
|
import fun.bb1.toml.TomlPrimitive;
|
||||||
|
|
||||||
|
@Internal
|
||||||
|
public final class TomlJ {
|
||||||
|
|
||||||
|
private TomlJ() { }
|
||||||
|
|
||||||
|
@Internal
|
||||||
|
public static final @NotNull Object recurse(@NotNull final ITomlElement toml) {
|
||||||
|
if (toml instanceof TomlPrimitive primitive) return primitive.getInner();
|
||||||
|
if (toml instanceof fun.bb1.toml.TomlArray tomlArray) {
|
||||||
|
@NotNull final TomlJArray array = new TomlJArray();
|
||||||
|
for (int i = 0; i < tomlArray.getSize(); i++) {
|
||||||
|
array.add(recurse(tomlArray.get(i)));
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
@NotNull final TomlObject tomlObject = toml.getAsTomlObject();
|
||||||
|
@NotNull final TomlJTable table = new TomlJTable();
|
||||||
|
for (@NotNull final String key : tomlObject) {
|
||||||
|
table.put(key, recurse(tomlObject.get(key)));
|
||||||
|
}
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
119
src/main/java/fun/bb1/toml/tomj/TomlJArray.java
Normal file
119
src/main/java/fun/bb1/toml/tomj/TomlJArray.java
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
package fun.bb1.toml.tomj;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.tomlj.TomlArray;
|
||||||
|
import org.tomlj.TomlPosition;
|
||||||
|
|
||||||
|
final class TomlJArray extends ArrayList<Object> implements TomlArray {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 934814329241781225L;
|
||||||
|
|
||||||
|
TomlJArray() {}
|
||||||
|
|
||||||
|
private final @NotNull Object check(@NotNull final Object e) {
|
||||||
|
if (e instanceof Number num) {
|
||||||
|
if (num instanceof Double || num instanceof Float) {
|
||||||
|
return num.doubleValue();
|
||||||
|
}
|
||||||
|
return num.longValue();
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean add(Object e) {
|
||||||
|
return super.add(check(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(int index, Object e) {
|
||||||
|
super.add(index, check(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addAll(Collection<? extends Object> c) {
|
||||||
|
return super.addAll(c.stream().map(this::check).toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addAll(int index, Collection<? extends Object> c) {
|
||||||
|
return super.addAll(index, c.stream().map(this::check).toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsStrings() {
|
||||||
|
// Should never be called
|
||||||
|
throw new RuntimeException("Should not be here!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsLongs() {
|
||||||
|
// Should never be called
|
||||||
|
throw new RuntimeException("Should not be here!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsDoubles() {
|
||||||
|
// Should never be called
|
||||||
|
throw new RuntimeException("Should not be here!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsBooleans() {
|
||||||
|
// Should never be called
|
||||||
|
throw new RuntimeException("Should not be here!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsOffsetDateTimes() {
|
||||||
|
// Should never be called
|
||||||
|
throw new RuntimeException("Should not be here!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsLocalDateTimes() {
|
||||||
|
// Should never be called
|
||||||
|
throw new RuntimeException("Should not be here!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsLocalDates() {
|
||||||
|
// Should never be called
|
||||||
|
throw new RuntimeException("Should not be here!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsLocalTimes() {
|
||||||
|
// Should never be called
|
||||||
|
throw new RuntimeException("Should not be here!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsArrays() {
|
||||||
|
// Should never be called
|
||||||
|
throw new RuntimeException("Should not be here!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsTables() {
|
||||||
|
// Should never be called
|
||||||
|
throw new RuntimeException("Should not be here!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TomlPosition inputPositionOf(int index) {
|
||||||
|
// Should never be called
|
||||||
|
throw new RuntimeException("Should not be here!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Object> toList() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
68
src/main/java/fun/bb1/toml/tomj/TomlJTable.java
Normal file
68
src/main/java/fun/bb1/toml/tomj/TomlJTable.java
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
package fun.bb1.toml.tomj;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.tomlj.TomlPosition;
|
||||||
|
import org.tomlj.TomlTable;
|
||||||
|
|
||||||
|
final class TomlJTable extends HashMap<String, Object> implements TomlTable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 4693375646889181151L;
|
||||||
|
|
||||||
|
TomlJTable() {}
|
||||||
|
|
||||||
|
private final @NotNull Object check(@NotNull final Object e) {
|
||||||
|
if (e instanceof Number num) {
|
||||||
|
if (num instanceof Double || num instanceof Float) {
|
||||||
|
return num.doubleValue();
|
||||||
|
}
|
||||||
|
return num.longValue();
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object put(String key, Object value) {
|
||||||
|
return super.put(key, check(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object putIfAbsent(String key, Object value) {
|
||||||
|
return super.putIfAbsent(key, check(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<List<String>> keyPathSet(boolean includeTables) {
|
||||||
|
// Not called by serialiser so can be ignored
|
||||||
|
throw new RuntimeException("Should not be here!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Entry<List<String>, Object>> entryPathSet(boolean includeTables) {
|
||||||
|
// Not called by serialiser so can be ignored
|
||||||
|
throw new RuntimeException("Should not be here!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable Object get(List<String> path) {
|
||||||
|
// Not called by serialiser so can be ignored
|
||||||
|
throw new RuntimeException("Should not be here!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable TomlPosition inputPositionOf(List<String> path) {
|
||||||
|
// Not called by serialiser so can be ignored
|
||||||
|
throw new RuntimeException("Should not be here!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> toMap() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue