aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/cc/polyfrost
diff options
context:
space:
mode:
authorDeDiamondPro <67508414+DeDiamondPro@users.noreply.github.com>2022-08-26 16:58:59 +0200
committerGitHub <noreply@github.com>2022-08-26 16:58:59 +0200
commitbf2cf4d8166a36ed089040889ad950ad3b71bc08 (patch)
treeeb1e4a9c5db5c70be872c7924d3cc2e5ca1446c8 /src/main/java/cc/polyfrost
parent8c6863a0c554ab75e8967618d6a0b90aaa4562f2 (diff)
downloadOneConfig-bf2cf4d8166a36ed089040889ad950ad3b71bc08.tar.gz
OneConfig-bf2cf4d8166a36ed089040889ad950ad3b71bc08.tar.bz2
OneConfig-bf2cf4d8166a36ed089040889ad950ad3b71bc08.zip
Finally remove stupid deserializePart method (#118)
* InstanceSupplier my beloved * Api my not so beloved * License header before moon kills me
Diffstat (limited to 'src/main/java/cc/polyfrost')
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/Config.java106
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/elements/BasicOption.java16
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/elements/OptionCategory.java6
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/elements/OptionPage.java6
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/elements/OptionSubcategory.java6
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/gson/InstanceSupplier.java44
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/gson/gsoninterface/GsonContext.java123
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/gson/gsoninterface/InterfaceAdapterFactory.java192
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/gson/gsoninterface/JsonDeserialization.java63
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/gson/gsoninterface/JsonDeserializes.java72
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/gson/gsoninterface/JsonSerialization.java70
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/config/gson/gsoninterface/Reflection.java513
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/internal/config/InternalConfig.java2
-rw-r--r--src/main/java/cc/polyfrost/oneconfig/internal/config/compatibility/forge/ForgeCompat.java9
14 files changed, 68 insertions, 1160 deletions
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/Config.java b/src/main/java/cc/polyfrost/oneconfig/config/Config.java
index 87ade90..fe7d7f7 100644
--- a/src/main/java/cc/polyfrost/oneconfig/config/Config.java
+++ b/src/main/java/cc/polyfrost/oneconfig/config/Config.java
@@ -34,9 +34,9 @@ import cc.polyfrost.oneconfig.config.data.PageLocation;
import cc.polyfrost.oneconfig.config.elements.BasicOption;
import cc.polyfrost.oneconfig.config.elements.OptionPage;
import cc.polyfrost.oneconfig.config.elements.OptionSubcategory;
+import cc.polyfrost.oneconfig.config.gson.InstanceSupplier;
import cc.polyfrost.oneconfig.config.gson.exclusion.NonProfileSpecificExclusionStrategy;
import cc.polyfrost.oneconfig.config.gson.exclusion.ProfileExclusionStrategy;
-import cc.polyfrost.oneconfig.config.gson.gsoninterface.InterfaceAdapterFactory;
import cc.polyfrost.oneconfig.gui.elements.config.ConfigKeyBind;
import cc.polyfrost.oneconfig.gui.OneConfigGui;
import cc.polyfrost.oneconfig.gui.elements.config.ConfigPageButton;
@@ -45,14 +45,10 @@ import cc.polyfrost.oneconfig.hud.HUDUtils;
import cc.polyfrost.oneconfig.internal.config.annotations.Option;
import cc.polyfrost.oneconfig.internal.config.core.ConfigCore;
import cc.polyfrost.oneconfig.internal.config.core.KeyBindHandler;
-import cc.polyfrost.oneconfig.utils.JsonUtils;
import cc.polyfrost.oneconfig.utils.gui.GuiUtils;
import com.google.gson.*;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
+import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.nio.charset.StandardCharsets;
@@ -64,19 +60,12 @@ import java.util.function.Supplier;
public class Config {
public final transient HashMap<String, BasicOption> optionNames = new HashMap<>();
transient protected final String configFile;
- transient protected final Gson gson = new GsonBuilder()
- .setExclusionStrategies(new ProfileExclusionStrategy())
- .registerTypeAdapterFactory(new InterfaceAdapterFactory())
- .excludeFieldsWithModifiers(Modifier.TRANSIENT)
- .setPrettyPrinting()
+ transient protected final Gson gson = addGsonOptions(new GsonBuilder()
+ .setExclusionStrategies(new ProfileExclusionStrategy()))
.create();
- transient protected final Gson nonProfileSpecificGson = new GsonBuilder()
- .setExclusionStrategies(new NonProfileSpecificExclusionStrategy())
- .registerTypeAdapterFactory(new InterfaceAdapterFactory())
- .excludeFieldsWithModifiers(Modifier.TRANSIENT)
- .setPrettyPrinting()
+ transient protected final Gson nonProfileSpecificGson = addGsonOptions(new GsonBuilder()
+ .setExclusionStrategies(new NonProfileSpecificExclusionStrategy()))
.create();
- transient protected final HashMap<Field, Object> defaults = new HashMap<>();
transient public Mod mod;
public boolean enabled;
@@ -138,12 +127,12 @@ public class Config {
*/
public void load() {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(Files.newInputStream(ConfigUtils.getProfileFile(configFile).toPath()), StandardCharsets.UTF_8))) {
- deserializePart(JsonUtils.PARSER.parse(reader).getAsJsonObject(), this);
+ gson.fromJson(reader, this.getClass());
} catch (Exception e) {
e.printStackTrace();
}
try (BufferedReader reader = new BufferedReader(new InputStreamReader(Files.newInputStream(ConfigUtils.getNonProfileSpecificFile(configFile).toPath()), StandardCharsets.UTF_8))) {
- deserializePart(JsonUtils.PARSER.parse(reader).getAsJsonObject(), this);
+ nonProfileSpecificGson.fromJson(reader, this.getClass());
} catch (Exception e) {
e.printStackTrace();
}
@@ -157,7 +146,7 @@ public class Config {
* @param mod data about the mod
* @param migrate whether the migrator should be run
*/
- protected void generateOptionList(Object instance, OptionPage page, Mod mod, boolean migrate) {
+ protected final void generateOptionList(Object instance, OptionPage page, Mod mod, boolean migrate) {
String pagePath = page.equals(mod.defaultPage) ? "" : page.name + ".";
for (Field field : instance.getClass().getDeclaredFields()) {
Option option = ConfigUtils.findAnnotation(field, Option.class);
@@ -214,45 +203,11 @@ public class Config {
return null;
}
- /**
- * Deserialize part of config and load values
- *
- * @param json json to deserialize
- * @param instance instance of target class
- */
- protected void deserializePart(JsonObject json, Object instance) {
- Class<?> clazz = instance.getClass();
- ArrayList<Field> fields = ConfigUtils.getClassFields(clazz);
- for (Map.Entry<String, JsonElement> element : json.entrySet()) {
- String name = element.getKey();
- JsonElement value = element.getValue();
- if (value.isJsonObject()) {
- Optional<Class<?>> innerClass = Arrays.stream(clazz.getClasses()).filter(aClass -> aClass.getSimpleName().equals(name)).findFirst();
- if (innerClass.isPresent()) {
- deserializePart(value.getAsJsonObject(), innerClass.get());
- continue;
- }
- }
- try {
- Field field = null;
- for (Field f : fields) {
- if (f.getName().equals(name)) {
- field = f;
- break;
- }
- }
- if (field != null) {
- TypeAdapter<?> adapter = gson.getAdapter(field.getType());
- Object object = adapter.fromJsonTree(value);
- field.setAccessible(true);
- field.set(instance, object);
- } else {
- System.out.println("Could not deserialize " + name + " in class " + clazz.getSimpleName());
- }
- } catch (Exception ignored) {
- System.out.println("Could not deserialize " + name + " in class " + clazz.getSimpleName());
- }
- }
+ protected GsonBuilder addGsonOptions(GsonBuilder builder) {
+ return builder
+ .registerTypeAdapter(this.getClass(), new InstanceSupplier<>(this))
+ .excludeFieldsWithModifiers(Modifier.TRANSIENT)
+ .setPrettyPrinting();
}
/**
@@ -269,7 +224,7 @@ public class Config {
* @param option The name of the field, or if the field is in a page "pageName.fieldName"
* @param condition The condition that has to be met for the option to be enabled
*/
- protected void addDependency(String option, Supplier<Boolean> condition) {
+ protected final void addDependency(String option, Supplier<Boolean> condition) {
if (!optionNames.containsKey(option)) return;
optionNames.get(option).addDependency(condition);
}
@@ -280,7 +235,7 @@ public class Config {
* @param option The name of the field, or if the field is in a page "pageName.fieldName"
* @param dependentOption The option that has to be enabled
*/
- protected void addDependency(String option, String dependentOption) {
+ protected final void addDependency(String option, String dependentOption) {
if (!optionNames.containsKey(option) || !optionNames.containsKey(dependentOption)) return;
optionNames.get(option).addDependency(() -> {
try {
@@ -297,7 +252,7 @@ public class Config {
* @param option The name of the field, or if the field is in a page "pageName.fieldName"
* @param value The value of the dependency
*/
- protected void addDependency(String option, boolean value) {
+ protected final void addDependency(String option, boolean value) {
if (!optionNames.containsKey(option)) return;
optionNames.get(option).addDependency(() -> value);
}
@@ -308,7 +263,7 @@ public class Config {
* @param option The name of the field, or if the field is in a page "pageName.fieldName"
* @param condition The condition that has to be met for the option to be hidden
*/
- protected void hideIf(String option, Supplier<Boolean> condition) {
+ protected final void hideIf(String option, Supplier<Boolean> condition) {
if (!optionNames.containsKey(option)) return;
optionNames.get(option).addHideCondition(condition);
}
@@ -319,7 +274,7 @@ public class Config {
* @param option The name of the field, or if the field is in a page "pageName.fieldName"
* @param dependentOption The option that has to be hidden
*/
- protected void hideIf(String option, String dependentOption) {
+ protected final void hideIf(String option, String dependentOption) {
if (!optionNames.containsKey(option) || !optionNames.containsKey(dependentOption)) return;
optionNames.get(option).addHideCondition(() -> {
try {
@@ -336,7 +291,7 @@ public class Config {
* @param option The name of the field, or if the field is in a page "pageName.fieldName"
* @param value The value of the condition
*/
- protected void hideIf(String option, boolean value) {
+ protected final void hideIf(String option, boolean value) {
if (!optionNames.containsKey(option)) return;
optionNames.get(option).addHideCondition(() -> value);
}
@@ -347,7 +302,7 @@ public class Config {
* @param option The name of the field, or if the field is in a page "pageName.fieldName"
* @param runnable What should be executed after the option is changed
*/
- protected void addListener(String option, Runnable runnable) {
+ protected final void addListener(String option, Runnable runnable) {
if (!optionNames.containsKey(option)) return;
optionNames.get(option).addListener(runnable);
}
@@ -358,7 +313,7 @@ public class Config {
* @param keyBind The keybind
* @param runnable The code to be executed
*/
- protected void registerKeyBind(OneKeyBind keyBind, Runnable runnable) {
+ protected final void registerKeyBind(OneKeyBind keyBind, Runnable runnable) {
Field field = null;
Object instance = null;
for (BasicOption option : optionNames.values()) {
@@ -379,23 +334,6 @@ public class Config {
}
/**
- * @param field The field to get the default value from
- * @return The default value of the given field
- */
- public Object getDefault(Field field) {
- return defaults.get(field);
- }
-
- /**
- * Reset this config file to its defaults.
- */
- public void reset() {
- for (BasicOption option : optionNames.values()) {
- option.reset(this);
- }
- }
-
- /**
* @return If this mod supports profiles, false for compatibility mode
*/
public boolean supportsProfiles() {
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/elements/BasicOption.java b/src/main/java/cc/polyfrost/oneconfig/config/elements/BasicOption.java
index 82d8b31..3394c52 100644
--- a/src/main/java/cc/polyfrost/oneconfig/config/elements/BasicOption.java
+++ b/src/main/java/cc/polyfrost/oneconfig/config/elements/BasicOption.java
@@ -102,7 +102,7 @@ public abstract class BasicOption {
* @param x x position
* @param y y position
*/
- public void drawLast(long vg, int x, int y , InputHandler inputHandler) {
+ public void drawLast(long vg, int x, int y, InputHandler inputHandler) {
}
/**
@@ -115,20 +115,6 @@ public abstract class BasicOption {
}
/**
- * Reset the field to its default value
- *
- * @param config The config the field is in
- */
- public void reset(Config config) {
- Object object = config.getDefault(field);
- if (object == null) return;
- try {
- set(object);
- } catch (IllegalAccessException ignored) {
- }
- }
-
- /**
* @return If the option is enabled, based on the dependencies
*/
public boolean isEnabled() {
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/elements/OptionCategory.java b/src/main/java/cc/polyfrost/oneconfig/config/elements/OptionCategory.java
index d3da143..4daefca 100644
--- a/src/main/java/cc/polyfrost/oneconfig/config/elements/OptionCategory.java
+++ b/src/main/java/cc/polyfrost/oneconfig/config/elements/OptionCategory.java
@@ -32,10 +32,4 @@ import java.util.ArrayList;
public class OptionCategory {
public final ArrayList<OptionSubcategory> subcategories = new ArrayList<>();
-
- public void reset(Config config) {
- for (OptionSubcategory subcategory : subcategories) {
- subcategory.reset(config);
- }
- }
}
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/elements/OptionPage.java b/src/main/java/cc/polyfrost/oneconfig/config/elements/OptionPage.java
index 9ac7c14..7a1dfb0 100644
--- a/src/main/java/cc/polyfrost/oneconfig/config/elements/OptionPage.java
+++ b/src/main/java/cc/polyfrost/oneconfig/config/elements/OptionPage.java
@@ -40,10 +40,4 @@ public class OptionPage {
this.name = name;
this.mod = mod;
}
-
- public void reset(Config config) {
- for (OptionCategory subcategory : categories.values()) {
- subcategory.reset(config);
- }
- }
}
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/elements/OptionSubcategory.java b/src/main/java/cc/polyfrost/oneconfig/config/elements/OptionSubcategory.java
index 282f30f..08c59b8 100644
--- a/src/main/java/cc/polyfrost/oneconfig/config/elements/OptionSubcategory.java
+++ b/src/main/java/cc/polyfrost/oneconfig/config/elements/OptionSubcategory.java
@@ -132,10 +132,4 @@ public class OptionSubcategory {
public String getName() {
return name;
}
-
- public void reset(Config config) {
- for (BasicOption option : options) {
- options.remove(config);
- }
- }
}
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/gson/InstanceSupplier.java b/src/main/java/cc/polyfrost/oneconfig/config/gson/InstanceSupplier.java
new file mode 100644
index 0000000..f20b527
--- /dev/null
+++ b/src/main/java/cc/polyfrost/oneconfig/config/gson/InstanceSupplier.java
@@ -0,0 +1,44 @@
+/*
+ * This file is part of OneConfig.
+ * OneConfig - Next Generation Config Library for Minecraft: Java Edition
+ * Copyright (C) 2021, 2022 Polyfrost.
+ * <https://polyfrost.cc> <https://github.com/Polyfrost/>
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * OneConfig is licensed under the terms of version 3 of the GNU Lesser
+ * General Public License as published by the Free Software Foundation, AND
+ * under the Additional Terms Applicable to OneConfig, as published by Polyfrost,
+ * either version 1.0 of the Additional Terms, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License. If not, see <https://www.gnu.org/licenses/>. You should
+ * have also received a copy of the Additional Terms Applicable
+ * to OneConfig, as published by Polyfrost. If not, see
+ * <https://polyfrost.cc/legal/oneconfig/additional-terms>
+ */
+
+package cc.polyfrost.oneconfig.config.gson;
+
+import com.google.gson.InstanceCreator;
+
+import java.lang.reflect.Type;
+
+public class InstanceSupplier<T> implements InstanceCreator<T> {
+ private final T instance;
+
+ public InstanceSupplier(T instance) {
+ this.instance = instance;
+ }
+
+ @Override
+ public T createInstance(Type type) {
+ return instance;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/gson/gsoninterface/GsonContext.java b/src/main/java/cc/polyfrost/oneconfig/config/gson/gsoninterface/GsonContext.java
deleted file mode 100644
index e27a362..0000000
--- a/src/main/java/cc/polyfrost/oneconfig/config/gson/gsoninterface/GsonContext.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package cc.polyfrost.oneconfig.config.gson.gsoninterface;
-
-/*
- * This file is part of OneConfig.
- * OneConfig - Next Generation Config Library for Minecraft: Java Edition
- * Copyright (C) 2021, 2022 Polyfrost.
- *
- * <https://polyfrost.cc> <https://github.com/Polyfrost/>
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * OneConfig is licensed under the terms of version 3 of the GNU Lesser
- * General Public License as published by the Free Software Foundation, AND
- * under the Additional Terms Applicable to OneConfig, as published by Polyfrost,
- * either version 1.0 of the Additional Terms, or (at your option) any later
- * version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License. If not, see <https://www.gnu.org/licenses/>. You should
- * have also received a copy of the Additional Terms Applicable
- * to OneConfig, as published by Polyfrost. If not, see
- * <https://polyfrost.cc/legal/oneconfig/additional-terms>
-
- * This file contains an adaptation of code from gson-interface
- * Project found at <https://github.com/mintern/gson-interface>
- * For the avoidance of doubt, this file is still licensed under the terms
- * of OneConfig's Licensing.
- *
- * LICENSE NOTICE FOR ADAPTED CODE
- *
- * Copyright (C) 2012, Brandon Mintern, EasyESI, Berkeley, CA
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither gson-interface nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BRANDON MINTERN OR EASYESI BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-import com.google.gson.Gson;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonIOException;
-import com.google.gson.TypeAdapter;
-import com.google.gson.internal.bind.JsonTreeReader;
-import com.google.gson.internal.bind.JsonTreeWriter;
-
-import java.io.IOException;
-import java.lang.reflect.Type;
-
-/**
- * @author mintern
- */
-public class GsonContext<T> {
- private final Gson gson;
- private final InterfaceAdapterFactory.InterfaceTypeAdapter<T> constructingAdapter;
-
- public GsonContext(Gson g, InterfaceAdapterFactory.InterfaceTypeAdapter<T> ita) {
- gson = g;
- constructingAdapter = ita;
- }
-
- public JsonElement toJsonTree(Object obj) {
- return gson.toJsonTree(obj);
- }
-
- public JsonElement thisToJsonTree(T obj) throws JsonIOException {
- JsonTreeWriter writer = new JsonTreeWriter();
- try {
- constructingAdapter.getDelegate().write(writer, obj);
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
- return writer.get();
- }
-
- public <C> C fromJsonTree(JsonElement json, Class<C> type) {
- return gson.fromJson(json, type);
- }
-
- public <C> C fromJsonTree(JsonElement json, Type typeOfC) {
- return (C) gson.fromJson(json, typeOfC);
- }
-
- public T thisFromJsonTree(JsonElement json) throws JsonIOException {
- try {
- return constructingAdapter.getDelegate().read(new JsonTreeReader(json));
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
- }
-
- public <C extends T> C thisFromJsonTree(JsonElement json, Type typeOfC) {
- TypeAdapter<C> adapter = constructingAdapter.getNextAdapter(typeOfC);
- try {
- return adapter.read(new JsonTreeReader(json));
- } catch (IOException e) {
- throw new JsonIOException(e);
- }
- }
-}
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/gson/gsoninterface/InterfaceAdapterFactory.java b/src/main/java/cc/polyfrost/oneconfig/config/gson/gsoninterface/InterfaceAdapterFactory.java
deleted file mode 100644
index 8f7d9d6..0000000
--- a/src/main/java/cc/polyfrost/oneconfig/config/gson/gsoninterface/InterfaceAdapterFactory.java
+++ /dev/null
@@ -1,192 +0,0 @@
-package cc.polyfrost.oneconfig.config.gson.gsoninterface;
-
-/*
- * This file is part of OneConfig.
- * OneConfig - Next Generation Config Library for Minecraft: Java Edition
- * Copyright (C) 2021, 2022 Polyfrost.
- *
- * <https://polyfrost.cc> <https://github.com/Polyfrost/>
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * OneConfig is licensed under the terms of version 3 of the GNU Lesser
- * General Public License as published by the Free Software Foundation, AND
- * under the Additional Terms Applicable to OneConfig, as published by Polyfrost,
- * either version 1.0 of the Additional Terms, or (at your option) any later
- * version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License. If not, see <https://www.gnu.org/licenses/>. You should
- * have also received a copy of the Additional Terms Applicable
- * to OneConfig, as published by Polyfrost. If not, see
- * <https://polyfrost.cc/legal/oneconfig/additional-terms>
-
- * This file contains an adaptation of code from gson-interface
- * Project found at <https://github.com/mintern/gson-interface>
- * For the avoidance of doubt, this file is still licensed under the terms
- * of OneConfig's Licensing.
- *
- * LICENSE NOTICE FOR ADAPTED CODE
- *
- * Copyright (C) 2012, Brandon Mintern, EasyESI, Berkeley, CA
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither gson-interface nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BRANDON MINTERN OR EASYESI BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-import com.google.gson.*;
-import com.google.gson.internal.Streams;
-import com.google.gson.reflect.TypeToken;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonWriter;
-
-import java.io.IOException;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Type;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author mintern
- */
-public class InterfaceAdapterFactory implements TypeAdapterFactory {
- @Override
- public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> tt) {
- Class<T> rawType = Reflection.classOfType(tt.getRawType());
- boolean serializes = JsonSerialization.class.isAssignableFrom(rawType);
- Constructor<JsonDeserializes<T>> deserializerConstructor = null;
- Class<JsonDeserializes<T>>[] typeParameters = Reflection.getTypeParameters(rawType, JsonDeserialization.class);
- if (typeParameters != null) {
- deserializerConstructor = Reflection.getConstructor(typeParameters[0]);
- }
- if (serializes || deserializerConstructor != null) {
- return new InterfaceTypeAdapter(serializes, deserializerConstructor, gson, tt, this);
- }
- return null;
- }
-
- public static class InterfaceTypeAdapter<T> extends TypeAdapter<T> {
- // This map ensures that only one deserializer of each type exists.
- private static final Map<Class, JsonDeserializes<?>> deserializerInstances = new HashMap();
-
- // Fields set in the constructor
- private final boolean selfSerializing;
- private final Constructor<JsonDeserializes<T>> deserializerConstructor;
- private final Gson gson;
- private final TypeToken<T> typeToken;
- private final TypeAdapterFactory thisFactory;
-
- // Adapters that follow this one in the chain for the indicated type
- private final Map<Type, TypeAdapter> nextAdapters = new HashMap();
-
- // Lazily-initialized fields. Call their corresponding getters in
- // order to access them.
- private TypeAdapter<T> delegate;
- private GsonContext gsonContext;
-
- private InterfaceTypeAdapter(
- boolean serializes,
- Constructor<JsonDeserializes<T>> dsc,
- Gson g,
- TypeToken<T> tt,
- TypeAdapterFactory factory) {
- selfSerializing = serializes;
- if (dsc != null) {
- dsc.setAccessible(true);
- }
- deserializerConstructor = dsc;
- gson = g;
- typeToken = tt;
- thisFactory = factory;
- }
-
- @Override
- public void write(JsonWriter writer, T value) throws IOException {
- if (!selfSerializing) {
- getDelegate().write(writer, value);
- } else if (value == null) {
- writer.nullValue();
- } else {
- JsonElement tree = ((JsonSerialization) value).toJsonTree(gsonContext());
- Streams.write(tree, writer);
- }
- }
-
- @Override
- public T read(JsonReader reader) throws IOException {
- if (deserializerConstructor == null) {
- return getDelegate().read(reader);
- }
- JsonElement json = Streams.parse(reader);
- if (json.isJsonNull()) {
- return null;
- }
- return (T) deserializer().fromJsonTree(json, typeToken.getType(), gsonContext());
- }
-
- synchronized TypeAdapter<T> getDelegate() {
- if (delegate == null) {
- delegate = gson.getDelegateAdapter(thisFactory, typeToken);
- }
- return delegate;
- }
-
- private synchronized GsonContext gsonContext() {
- if (gsonContext == null) {
- gsonContext = new GsonContext(gson, this);
- }
- return gsonContext;
- }
-
- synchronized <C extends T> TypeAdapter<C> getNextAdapter(Type typeOfC) {
- TypeAdapter<C> nextAdapter = nextAdapters.get(typeOfC);
- if (nextAdapter == null) {
- nextAdapter = gson.getDelegateAdapter(thisFactory, (TypeToken<C>) TypeToken.get(typeOfC));
- nextAdapters.put(typeOfC, nextAdapter);
- }
- return nextAdapter;
- }
-
- private JsonDeserializes<T> deserializer() {
- synchronized (deserializerInstances) {
- Class<JsonDeserializes<T>> c = deserializerConstructor.getDeclaringClass();
- JsonDeserializes<T> deserializer = (JsonDeserializes<T>) deserializerInstances.get(c);
- if (deserializer == null) {
- try {
- deserializer = deserializerConstructor.newInstance();
- } catch (Exception e) {
- throw new JsonParseException(e);
- }
- deserializerInstances.put(c, deserializer);
- }
- return deserializer;
- }
- }
- }
-}
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/gson/gsoninterface/JsonDeserialization.java b/src/main/java/cc/polyfrost/oneconfig/config/gson/gsoninterface/JsonDeserialization.java
deleted file mode 100644
index 436d897..0000000
--- a/src/main/java/cc/polyfrost/oneconfig/config/gson/gsoninterface/JsonDeserialization.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package cc.polyfrost.oneconfig.config.gson.gsoninterface;
-
-/*
- * This file is part of OneConfig.
- * OneConfig - Next Generation Config Library for Minecraft: Java Edition
- * Copyright (C) 2021, 2022 Polyfrost.
- *
- * <https://polyfrost.cc> <https://github.com/Polyfrost/>
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * OneConfig is licensed under the terms of version 3 of the GNU Lesser
- * General Public License as published by the Free Software Foundation, AND
- * under the Additional Terms Applicable to OneConfig, as published by Polyfrost,
- * either version 1.0 of the Additional Terms, or (at your option) any later
- * version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License. If not, see <https://www.gnu.org/licenses/>. You should
- * have also received a copy of the Additional Terms Applicable
- * to OneConfig, as published by Polyfrost. If not, see
- * <https://polyfrost.cc/legal/oneconfig/additional-terms>
-
- * This file contains an adaptation of code from gson-interface
- * Project found at <https://github.com/mintern/gson-interface>
- * For the avoidance of doubt, this file is still licensed under the terms
- * of OneConfig's Licensing.
- *
- * LICENSE NOTICE FOR ADAPTED CODE
- *
- * Copyright (C) 2012, Brandon Mintern, EasyESI, Berkeley, CA
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither gson-interface nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BRANDON MINTERN OR EASYESI BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-public interface JsonDeserialization<D extends JsonDeserializes<? extends JsonDeserialization<D>>> {
-}
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/gson/gsoninterface/JsonDeserializes.java b/src/main/java/cc/polyfrost/oneconfig/config/gson/gsoninterface/JsonDeserializes.java
deleted file mode 100644
index ecdf8e5..0000000
--- a/src/main/java/cc/polyfrost/oneconfig/config/gson/gsoninterface/JsonDeserializes.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package cc.polyfrost.oneconfig.config.gson.gsoninterface;
-
-/*
- * This file is part of OneConfig.
- * OneConfig - Next Generation Config Library for Minecraft: Java Edition
- * Copyright (C) 2021, 2022 Polyfrost.
- *
- * <https://polyfrost.cc> <https://github.com/Polyfrost/>
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * OneConfig is licensed under the terms of version 3 of the GNU Lesser
- * General Public License as published by the Free Software Foundation, AND
- * under the Additional Terms Applicable to OneConfig, as published by Polyfrost,
- * either version 1.0 of the Additional Terms, or (at your option) any later
- * version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License. If not, see <https://www.gnu.org/licenses/>. You should
- * have also received a copy of the Additional Terms Applicable
- * to OneConfig, as published by Polyfrost. If not, see
- * <https://polyfrost.cc/legal/oneconfig/additional-terms>
-
- * This file contains an adaptation of code from gson-interface
- * Project found at <https://github.com/mintern/gson-interface>
- * For the avoidance of doubt, this file is still licensed under the terms
- * of OneConfig's Licensing.
- *
- * LICENSE NOTICE FOR ADAPTED CODE
- *
- * Copyright (C) 2012, Brandon Mintern, EasyESI, Berkeley, CA
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither gson-interface nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BRANDON MINTERN OR EASYESI BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-import com.google.gson.JsonElement;
-
-import java.lang.reflect.Type;
-
-/**
- * @author mintern
- */
-public interface JsonDeserializes<T> {
- T fromJsonTree(JsonElement json, Type type, GsonContext<T> context);
-}
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/gson/gsoninterface/JsonSerialization.java b/src/main/java/cc/polyfrost/oneconfig/config/gson/gsoninterface/JsonSerialization.java
deleted file mode 100644
index 3cae64d..0000000
--- a/src/main/java/cc/polyfrost/oneconfig/config/gson/gsoninterface/JsonSerialization.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package cc.polyfrost.oneconfig.config.gson.gsoninterface;
-
-/*
- * This file is part of OneConfig.
- * OneConfig - Next Generation Config Library for Minecraft: Java Edition
- * Copyright (C) 2021, 2022 Polyfrost.
- *
- * <https://polyfrost.cc> <https://github.com/Polyfrost/>
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * OneConfig is licensed under the terms of version 3 of the GNU Lesser
- * General Public License as published by the Free Software Foundation, AND
- * under the Additional Terms Applicable to OneConfig, as published by Polyfrost,
- * either version 1.0 of the Additional Terms, or (at your option) any later
- * version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License. If not, see <https://www.gnu.org/licenses/>. You should
- * have also received a copy of the Additional Terms Applicable
- * to OneConfig, as published by Polyfrost. If not, see
- * <https://polyfrost.cc/legal/oneconfig/additional-terms>
-
- * This file contains an adaptation of code from gson-interface
- * Project found at <https://github.com/mintern/gson-interface>
- * For the avoidance of doubt, this file is still licensed under the terms
- * of OneConfig's Licensing.
- *
- * LICENSE NOTICE FOR ADAPTED CODE
- *
- * Copyright (C) 2012, Brandon Mintern, EasyESI, Berkeley, CA
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither gson-interface nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BRANDON MINTERN OR EASYESI BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-import com.google.gson.JsonElement;
-
-/**
- * @author mintern
- */
-public interface JsonSerialization<T extends JsonSerialization<T>> {
- public JsonElement toJsonTree(GsonContext<T> context);
-}
diff --git a/src/main/java/cc/polyfrost/oneconfig/config/gson/gsoninterface/Reflection.java b/src/main/java/cc/polyfrost/oneconfig/config/gson/gsoninterface/Reflection.java
deleted file mode 100644
index ee50b64..0000000
--- a/src/main/java/cc/polyfrost/oneconfig/config/gson/gsoninterface/Reflection.java
+++ /dev/null
@@ -1,513 +0,0 @@
-package cc.polyfrost.oneconfig.config.gson.gsoninterface;
-
-/*
- * This file is part of OneConfig.
- * OneConfig - Next Generation Config Library for Minecraft: Java Edition
- * Copyright (C) 2021, 2022 Polyfrost.
- *
- * <https://polyfrost.cc> <https://github.com/Polyfrost/>
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * OneConfig is licensed under the terms of version 3 of the GNU Lesser
- * General Public License as published by the Free Software Foundation, AND
- * under the Additional Terms Applicable to OneConfig, as published by Polyfrost,
- * either version 1.0 of the Additional Terms, or (at your option) any later
- * version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License. If not, see <https://www.gnu.org/licenses/>. You should
- * have also received a copy of the Additional Terms Applicable
- * to OneConfig, as published by Polyfrost. If not, see
- * <https://polyfrost.cc/legal/oneconfig/additional-terms>
-
- * This file contains an adaptation of code from gson-interface
- * Project found at <https://github.com/mintern/gson-interface>
- * For the avoidance of doubt, this file is still licensed under the terms
- * of OneConfig's Licensing.
- *
- * LICENSE NOTICE FOR ADAPTED CODE
- *
- * Copyright (C) 2012, Brandon Mintern, EasyESI, Berkeley, CA
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither gson-interface nor the names of its contributors may be used
- * to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BRANDON MINTERN OR EASYESI BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-import java.lang.reflect.*;
-import java.util.ArrayList;
-import java.util.EmptyStackException;
-
-/**
- * Provides various static helper methods that add a high-level interface to
- * introspection and reflection.
- *
- * @author mintern
- */
-public class Reflection {
- /**
- * A wrapper for Class.newInstance() that throws an unchecked Exception.
- * It also ensures that even private constructors can be called.
- *
- * @param c the class on which to call newInstance()
- * @return the object returned from c.newInstance()
- * @throws IllegalArgumentException if there was an exception
- * constructing the instance
- */
- public static <T> T newInstance(Class<T> c) {
- try {
- return constructAnyway(c.getDeclaredConstructor());
- } catch (Exception e) {
- throw new IllegalArgumentException(e);
- }
- }
-
- /**
- * Gets the aClass constructor with the given paramaters, throwing an
- * unchecked exception in the case of errors.
- *
- * @param aClass the class whose constructor should be fetched.
- * @param params the parameters to the desired constructor
- * @return the constructor for aClass that accepts params, or null if
- * there is no such constructor
- */
- public static <T> Constructor<T> getConstructor(Class<T> aClass, Class... params) {
- try {
- return aClass.getDeclaredConstructor(params);
- } catch (Exception e) {
- return null;
- }
- }
-
- /**
- * Invokes the given constructor with the given args even if it's not
- * accessible.
- *
- * @param <T> the type of value to be constructed
- * @param constructor the constructor to invoke (see getConstructor)
- * @param args the args to send to the constructor
- * @return a new instance of type T
- * @throws IllegalArgumentException if there was an exception while
- * setting the constructor to be accessible or invoking it
- */
- public static <T> T constructAnyway(Constructor<T> constructor, Object... args)
- throws IllegalArgumentException {
- try {
- boolean wasAccessible = constructor.isAccessible();
- constructor.setAccessible(true);
- try {
- T instance = constructor.newInstance(args);
- return instance;
- } finally {
- constructor.setAccessible(wasAccessible);
- }
- } catch (Exception e) {
- throw new IllegalArgumentException(e);
- }
- }
-
- /**
- * Checks whether a class is abstract.
- *
- * @param c the class to check
- * @return true iff c is an interface or abstract class
- */
- public static boolean isAbstract(Class c) {
- return c.isInterface() || Modifier.isAbstract(c.getModifiers());
- }
-
- /**
- * Obtain the value of a field even if it is not public.
- *
- * @param field the field value to obtain
- * @param fieldObj an instantiated object which defines field
- * @return the value of field in fieldObj
- * @throws IllegalArgumentException on any error
- */
- public static Object getFieldValue(Field field, Object fieldObj)
- throws IllegalArgumentException {
- try {
- boolean wasAccessible = field.isAccessible();
- field.setAccessible(true);
- try {
- return field.get(fieldObj);
- } finally {
- field.setAccessible(wasAccessible);
- }
- } catch (IllegalAccessException e) {
- throw new IllegalArgumentException(e);
- }
- }
-
- /**
- * Returns a field on which field.get(...) can be called, even if the field
- * is private.
- *
- * @param aClass the class defining the desired field
- * @param fieldName the name of the desired field
- * @return a field that is accessible regardless of its modifiers
- * @throws IllegalArgumentException on any error
- */
- public static Field getAccessibleField(Class aClass, String fieldName)
- throws IllegalArgumentException {
- try {
- Field field = aClass.getDeclaredField(fieldName);
- field.setAccessible(true);
- return field;
- } catch (Exception e) {
- // NoSuchFieldException, SecurityException
- throw new IllegalArgumentException(e);
- }
- }
-
- /**
- * For a class implClass that instantiates a generic class or interface
- * genClass, return the types that genClass is instantiated with. This
- * method has a runtime linear in the size of the type hierarchy, so if
- * the results are used at runtime, it is recommended to cache them.
- * <p>
- * An example of its usage:
- * <p>
- * import java.util.*;
- * public class IdToNameMap extends HashMap<Integer, String> {
- * public static void main (String[] args) {
- * for (Class c: getTypeParameters(IdToNameMap.class, Map.class) {
- * System.out.println(c);
- * }
- * }
- * }
- * <p>
- * Calling main() would print out:
- * <p>
- * Integer.class
- * String.class
- * <p>
- * Note that this method ascends and descends the class hierarchy to
- * determine the best bounds possible on all type parameters. For
- * example, even if the class hierarchy is:
- * <p>
- * public class IdMap<V> extends HashMap<Integer, V> {}
- * public class IdToNameMap extends IdMap<String> {}
- * <p>
- * the main() call would print the same thing. For type parameters that
- * remain unbounded, the tightest bound available is printed. So:
- * <p>
- * getTypeParameters(EnumSet.class, Set.class)
- * <p>
- * would return Enum.class. Sometimes the tightest bound available is
- * Object.class.
- * <p>
- * This method should NOT be called with implClass or genClass as a
- * primitive class. This is not sensible, anyway.
- *
- * @param implClass a class instantiating a generic class or interface
- * @param genClass the generic class or interface which has type
- * parameters you want to know
- * @return the array of instantiated parameters. If implClass does not
- * extend or implement genClass, null is returned. For any genClass
- * type parameters not instantiated by implClass, we return the
- * parameters' upper bounds.
- */
- public static Class[] getTypeParameters(Class implClass, Class genClass) {
- return getTypeParameters(implClass, genClass, new Stack());
- }
-
- /**
- * @param genClass typically a Class with generic type parameters
- * @return the array of Class bounds on those parameters, or an empty
- * Class array if genClass is not generic.
- */
- public static Class[] getParameterBounds(Class genClass) {
- Type[] parameters = genClass.getTypeParameters();
- Class[] paramClasses = new Class[parameters.length];
- for (int i = 0; i < parameters.length; i++) {
- paramClasses[i] = classOfType(parameters[i]);
- }
- return paramClasses;
- }
-
- /**
- * @param type any Type object
- * @return the most specific class of type that we can determine
- */
- public static Class classOfType(Type type) {
- if (type instanceof Class) {
- return (Class) type;
- } else if (type instanceof ParameterizedType) {
- return classOfType(((ParameterizedType) type).getRawType());
- } else if (type instanceof TypeVariable) {
- return classOfType(((TypeVariable) type).getBounds()[0]);
- } else if (type instanceof WildcardType) {
- return classOfType(((WildcardType) type).getUpperBounds()[0]);
- } else {
- // this should never happen in principle, but just in case...
- return Object.class;
- }
- }
-
- // Internal helper methods used above.
-
- /**
- * See public ... getTypeParameters. This method and the others below
- * that implement it work by ascending and descending the type hierarchy
- * in order to gather the desired information. As we ascend the type
- * hierarchy looking for genClass, we push the classes that have led us
- * there onto classStack. Later, if we find genClass but the associated
- * implClass is generic, we descend the classStack to figure out how
- * implClass is instantiated. Eventually, each type parameter is either
- * fully instantiated, in which case we use the instantiation class, or
- * the type parameter is not instantiated, in which case we return its
- * upper bound, which in some cases will be Object.class. @param
- * implClass the class extending/implementing genClass @param genClass
- * a class with generic type parameters
- *
- * @param classStack the stack of subclasses we've visited before
- * reaching this implClass
- * @return the tightest bounds implClass places on those type
- * parameters
- */
- private static Class[] getTypeParameters(Class implClass, Class genClass, Stack<Class> classStack) {
- if (genClass.isInterface()) {
- return getInterfaceParameters(implClass, genClass, classStack);
- }
- return getSuperParameters(implClass, genClass, classStack);
- }
-
- /**
- * This method implements getTypeParameters when genClass is an
- * interface. Since a class can implement multiple interfaces and since
- * they must be retrieved differently than with a superclass, we keep
- * the functions separate.
- * <p>
- * At each level, we check each interface against genClass. If none of
- * them match, we look at any interface's implemented interfaces, and so
- * on all the way up until we reach an interface with no implemented
- * interfaces.
- * <p>
- * If we still haven't found genClass at this point, we ascend into
- * implClass's superclass and perform the same work.
- * <p>
- * As mentioned in private ... getTypeParameters, any time we ascend the
- * type hierarchy, we push the implClass onto the classStack so that we
- * can later descend the class hierarchy to resolve type parameters
- * which are set further down the tree.
- */
- private static Class[] getInterfaceParameters(Class implClass, Class genClass, Stack<Class> classStack) {
- Type[] interfaces = implClass.getGenericInterfaces();
- // Check each of the interfaces implemented by implClass to see if
- // one matches genClass.
- for (Type iface : interfaces) {
- Class[] result = getParametersIfMatches(iface, implClass, genClass, classStack);
- if (result != null) {
- // We found it.
- return result;
- }
- }
- // None of the implemented interfaces matched genClass. Ascend each
- // interface's type hierarchy looking for genClass.
- for (Type iface : interfaces) {
- Class interfaceClass = classOfType(iface);
- classStack.push(implClass);
- Class[] result = getInterfaceParameters(interfaceClass, genClass, classStack);
- classStack.pop();
- if (result != null) {
- return result;
- }
- }
- // We visited the entire interface hierarchy of implClass. Ascend to
- // implClass's superclass and look for the interface there.
- Class superclass = implClass.getSuperclass();
- if (superclass == null) {
- // implClass is an interface or Object, so it has no superclass.
- // We didn't find genClass along this path.
- return null;
- }
- // The ascent.
- classStack.push(implClass);
- Class[] result = getInterfaceParameters(superclass, genClass, classStack);
- classStack.pop();
- // The result may still be null at this point, but we've visited the
- // entire type hierarchy and haven't found genClass. In these cases, we
- // want to return null, anyway.
- return result;
- }
-
- /**
- * This method implements getTypeParameters when genClass is not an
- * interface, and therefore should be found as a superclass of
- * implClass. Since a class can only have one superclass, we simply
- * check that superclass and then ascend the type hierarchy if it is not
- * a match.
- */
- private static Class[] getSuperParameters(Class implClass, Class genClass, Stack<Class> classStack) {
- Type supertype = implClass.getGenericSuperclass();
- if (supertype == null) {
- // Base case; implClass is Object; we didn't find genClass.
- return null;
- }
- Class[] result = getParametersIfMatches(supertype, implClass, genClass, classStack);
- if (result != null) {
- // We found it.
- return result;
- }
- // The superclass of implClass didn't match genClass. Ascend class
- // hierarchy.
- classStack.push(implClass);
- result = getSuperParameters(classOfType(supertype), genClass, classStack);
- classStack.pop();
- // We either have our result or null. Return.
- return result;
- }
-
- /**
- * If the Class represented by type matches genClass, return the
- * genClass type parameters. If it is not a match, returns null.
- *
- * @param type the type being considered, with all information present
- * in implClass
- * @param implClass the current class, for which type was a superclass
- * or an implemented interface
- * @param genClass the class we are looking for (to be compared against
- * type)
- * @param classStack
- * @return null if type is not of Class genClass, genClass
- * instantiated type parameters otherwise. Class[0] if genClasses has
- * no type parameters
- */
- private static Class[] getParametersIfMatches(Type type, Class implClass, Class genClass, Stack<Class> classStack) {
- if (type == genClass) {
- // type matches genClass and it's a Class Type; if genClass has
- // type parameters, they have not been instantiated by
- // implClass. Simply return the bounds on genClass's
- // parameters, if it has any parameters. If it doesn't have
- // parameters, we'll return Class[0]
- return getParameterBounds(genClass);
- }
- if (type instanceof ParameterizedType && classOfType(type) == genClass) {
- // We've found our parameterized genClass. For each type,
- // convert it to its corresponding class. If it's a TypeVariable
- // and it matches a type argument in implClass, descend down the
- // classStack to determine THAT parameter type. Otherwise, or
- // if the TypeVariable can't be resolved, simply perform a dumb
- // conversion on the type.
- Type[] types = ((ParameterizedType) type).getActualTypeArguments();
- Class[] classes = new Class[types.length];
- // The following two types declared here to avoid repeated work
- Type[] implParams = null;
- Class[] implInstantiatedParams = null;
- // This loop is probably the most complex bit in the code. An
- // instructive example is where we have a class hierarchy like:
- // IdNameMap extends IdMap<String>
- // IdMap<E> extends HashMap<Integer, E>
- // getTypeParameters(IdNameMap.class, HashMap.class)
- // When we reach this point:
- // types = [Integer, E]
- // implClass = IdMap
- // classes = []
- // classStack = [IdNameMap]
- // The outer loop iterates over types. After its first iteration
- // (for which the if-test fails), classes=[Integer]. In the
- // second iteration, E is a TypeVariable and the classStack is
- // not empty. We fetch IdMap's TypeParameters:
- // implParams = [E]
- // The inner loop iterates over implParams, finding that when j
- // = 0, implParams[j] matches types[i] (both are E). We then
- // call getTypeParameters(IdNameMap, IdMap, []) to determine the
- // type of E, which turns out to be String:
- // implInstantiatedParams = [String]
- // We update classes:
- // classes = [Integer, String]
- // and we continue to the next iteration of the outer loop,
- // where it turns out to terminate. Finally, we return classes.
- types:
- for (int i = 0; i < types.length; i++) {
- if (types[i] instanceof TypeVariable && !classStack.isEmpty()) {
- if (implParams == null) {
- implParams = implClass.getTypeParameters();
- }
- for (int j = 0; j < implParams.length; j++) {
- if (((TypeVariable) types[i]).equals(implParams[j])) {
- if (implInstantiatedParams == null) {
- Class subClass = classStack.pop();
- // the descent
- implInstantiatedParams = getTypeParameters(subClass, implClass, classStack);
- classStack.push(subClass);
- }
- classes[i] = implInstantiatedParams[j];
- continue types;
- }
- }
- // If we reach this point (we were unable to resolve the
- // parameter), type[i] will be resolved to its bound in the
- // line below.
- }
- classes[i] = classOfType(types[i]);
- }
- return classes;
- }
- // type did not match genClass
- return null;
- }
-
- /**
- * A non-threadsafe alternative to java.util.Stack.
- * Since the Reflection code is single threaded, using this should be
- * faster.
- *
- * @param E the type of elements in the stack
- */
- public static class Stack<E> extends ArrayList<E> {
- /**
- * Push an item onto the stack. The next call to pop() will return
- * the most-recently push()ed item.
- *
- * @param elt the element to add to the stack
- * @return this; convenient for chaining: stack.push(...).push(...)
- */
- public Stack<E> push(E elt) {
- add(elt);
- return this;
- }
-
- /**
- * Pop from this and return the item that was most recently pushed
- * onto this. This should never be called on an empty stack.
- *
- * @return the item that was pop()ed
- * @throws EmptyStackException if this is empty
- */
- public E pop() {
- try {
- return remove(size() - 1);
- } catch (IndexOutOfBoundsException e) {
- throw new EmptyStackException();
- }
- }
- }
-}
diff --git a/src/main/java/cc/polyfrost/oneconfig/internal/config/InternalConfig.java b/src/main/java/cc/polyfrost/oneconfig/internal/config/InternalConfig.java
index b3f59ba..0d1ab3e 100644
--- a/src/main/java/cc/polyfrost/oneconfig/internal/config/InternalConfig.java
+++ b/src/main/java/cc/polyfrost/oneconfig/internal/config/InternalConfig.java
@@ -64,7 +64,7 @@ public abstract class InternalConfig extends Config {
@Override
public void load() {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(Files.newInputStream(Paths.get("OneConfig/" + configFile)), StandardCharsets.UTF_8))) {
- deserializePart(JsonUtils.PARSER.parse(reader).getAsJsonObject(), this);
+ gson.fromJson(reader, this.getClass());
} catch (IOException e) {
e.printStackTrace();
}
diff --git a/src/main/java/cc/polyfrost/oneconfig/internal/config/compatibility/forge/ForgeCompat.java b/src/main/java/cc/polyfrost/oneconfig/internal/config/compatibility/forge/ForgeCompat.java
index 238355e..665a9f3 100644
--- a/src/main/java/cc/polyfrost/oneconfig/internal/config/compatibility/forge/ForgeCompat.java
+++ b/src/main/java/cc/polyfrost/oneconfig/internal/config/compatibility/forge/ForgeCompat.java
@@ -35,15 +35,6 @@ public class ForgeCompat {
}
@Override
- public Object getDefault(Field field) {
- return null;
- }
-
- @Override
- public void reset() {
- }
-
- @Override
public boolean supportsProfiles() {
return false;
}