diff --git a/Core/src/main/java/fr/altarik/toolbox/core/config/ConfigI.java b/Core/src/main/java/fr/altarik/toolbox/core/config/ConfigI.java new file mode 100644 index 0000000..2d79082 --- /dev/null +++ b/Core/src/main/java/fr/altarik/toolbox/core/config/ConfigI.java @@ -0,0 +1,63 @@ +package fr.altarik.toolbox.core.config; + +import com.google.gson.*; + +import java.io.FileReader; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; +import java.nio.file.Files; +import java.nio.file.Path; + +/** + * Code "inspired" from + * https://github.com/CaffeineMC/sodium-fabric/blob/dev/src/main/java/me/jellysquid/mods/sodium/client/gui/SodiumGameOptions.java + * + */ +public class ConfigI { + + protected static final Gson GSON = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).setPrettyPrinting().excludeFieldsWithModifiers(Modifier.PROTECTED, Modifier.PRIVATE).create(); + + protected Path configPath; + + protected static Path getConfigPath(Path configPath, String name) { + return configPath.resolve(name); + } + + public static ConfigI load(Path configPath, String name, Class clazz) throws IOException, JsonSyntaxException, JsonIOException { + Path path = getConfigPath(configPath, name); + + ConfigI file; + + if(Files.exists(path)) { + FileReader reader = new FileReader(path.toFile()); + file = GSON.fromJson(reader, clazz); + } else { + try { + file = clazz.getConstructor().newInstance(); + } catch (InstantiationException | InvocationTargetException | IllegalAccessException | NoSuchMethodException e) { + throw new IOException(e); + } + } + + file.configPath = path; + + file.writeChanges(); + return file; + } + + public void writeChanges() throws IOException { + Path dir = this.configPath.getParent(); + if(!Files.exists(dir)) { + Files.createDirectories(dir); + } else if (!Files.isDirectory(dir)) { + throw new IOException("Not a directory: " + dir); + } + // Use a temporary location next to the config's final destination to replace it atomically +// Path tempPath = this.configPath.resolveSibling(this.configPath.getFileName() + ".tmp"); + Files.writeString(this.configPath, GSON.toJson(this)); +// Files.copy(tempPath, this.configPath, StandardCopyOption.REPLACE_EXISTING); +// Files.delete(tempPath); + } + +} diff --git a/Core/src/test/java/ConfigITest.java b/Core/src/test/java/ConfigITest.java new file mode 100644 index 0000000..c2280d3 --- /dev/null +++ b/Core/src/test/java/ConfigITest.java @@ -0,0 +1,40 @@ +import fr.altarik.toolbox.core.config.ConfigI; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.nio.file.Path; + +public class ConfigITest { + + public static class ConfigClazz extends ConfigI { + + public int par1 = 5; + public String par2 = "bad"; + public double para3 = 3.14; + + public static ConfigClazz load() throws IOException { + return (ConfigClazz) load(Path.of("."), "test.json", ConfigClazz.class); + } + + } + + @Test + public void testConfig() throws IOException { + ConfigClazz config = ConfigClazz.load(); + Assertions.assertEquals(5, config.par1); + Assertions.assertEquals("bad", config.par2); + Assertions.assertEquals(3.14, config.para3); + config.par1 = 6; + config.par2 = "good"; + config.para3 = 4.2; + Assertions.assertEquals(6, config.par1); + config.writeChanges(); + config = ConfigClazz.load(); + Assertions.assertEquals(6, config.par1); + Assertions.assertEquals("good", config.par2); + Assertions.assertEquals(4.2, config.para3); + + Path.of(".").resolve("test.json").toFile().delete(); + } +} diff --git a/gradle.properties b/gradle.properties index ed82a78..077c6fd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ loader_version=0.15.3 fabric_version=0.91.3+1.20.2 maven_group=fr.altarik.toolbox -maven_version=4.4.0 +maven_version=4.5.0 git_owner=quentinlegot git_repo=Toolbox \ No newline at end of file