Cleaner Config

This commit is contained in:
2026-02-21 22:55:47 +01:00
parent 2096925a02
commit d3258edbc7
2 changed files with 118 additions and 69 deletions
@@ -1,107 +1,86 @@
package org.saturnclient.saturnclient.config;
import com.google.gson.*;
import org.saturnclient.saturnclient.SaturnClient;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.*;
import org.saturnclient.saturnclient.SaturnClient;
import java.util.LinkedHashMap;
import java.util.Map;
public class ConfigManager {
private static final File configFile = new File(SaturnClient.client.runDirectory, "saturn.json");
private static final Map<String, Map<String, Property<?>>> properties = new HashMap<>();
private static JsonObject cachedThemeJson = null;
private static final File configFile =
new File(SaturnClient.client.runDirectory, "saturn.json");
// SINGLE ROOT TREE
private static final Map<String, Property<?>> ROOT = new LinkedHashMap<>();
private static JsonObject cachedJson = null;
private final Map<String, Property<?>> currentMap;
private final String namespace;
/**
* Creates a root namespace
*/
public ConfigManager(String namespace) {
this.namespace = namespace;
this.currentMap = new LinkedHashMap<>();
properties.put(namespace, currentMap);
System.out.println("Created namespace: " + namespace);
ROOT.put(namespace, Property.namespace(currentMap));
}
/**
* Creates a sub-namespace inside a parent
*/
public ConfigManager(ConfigManager parent, String namespace) {
this.namespace = namespace;
this.currentMap = new LinkedHashMap<>();
Property<Map<String, Property<?>>> nsProp = Property.namespace(currentMap);
parent.property(namespace, nsProp);
System.out.println("Created sub-namespace: " + namespace);
}
public void sub(String name) {
property(name, Property.namespace(new LinkedHashMap<>()));
parent.property(namespace, Property.namespace(currentMap));
}
/**
* Add a property
*/
public <T> Property<T> property(String name, Property<T> value) {
currentMap.put(name, value);
loadProp(name, value);
loadSingleProperty(name, value);
return value;
}
private <T> void loadProp(String name, Property<T> prop) {
JsonObject source = cachedThemeJson != null ? cachedThemeJson : loadAndCache();
if (source == null)
return;
JsonElement namespaceJson = source.get(namespace);
if (namespaceJson == null || !namespaceJson.isJsonObject())
return;
JsonElement value = namespaceJson.getAsJsonObject().get(name);
if (value != null)
prop.loadFromJson(value);
}
private static JsonObject loadAndCache() {
try {
if (!configFile.exists()) {
Files.writeString(configFile.toPath(), "{}");
return new JsonObject();
}
String json = Files.readString(configFile.toPath());
cachedThemeJson = JsonParser.parseString(json).getAsJsonObject();
return cachedThemeJson;
} catch (IOException e) {
SaturnClient.LOGGER.error("Error reading config file", e);
return null;
}
/**
* Add empty namespace
*/
public ConfigManager sub(String name) {
return new ConfigManager(this, name);
}
/**
* Load entire config
*/
public static void load() {
SaturnClient.LOGGER.info("Loading config...");
JsonObject json = loadAndCache();
if (json == null)
return;
properties.forEach((namespace, map) -> {
JsonElement nsElement = json.get(namespace);
if (nsElement != null && nsElement.isJsonObject()) {
loadProperties(nsElement.getAsJsonObject(), map);
}
});
}
private static void loadProperties(JsonObject json, Map<String, Property<?>> props) {
props.forEach((name, prop) -> {
JsonElement el = json.get(name);
if (el != null)
prop.loadFromJson(el);
});
loadRecursive(json, ROOT);
}
/**
* Save entire config
*/
public static void save() {
SaturnClient.LOGGER.info("Saving config...");
JsonObject root = new JsonObject();
properties.forEach((namespace, map) -> {
JsonObject nsJson = new JsonObject();
saveProperties(nsJson, map);
root.add(namespace, nsJson);
});
JsonObject rootJson = new JsonObject();
saveRecursive(rootJson, ROOT);
try {
String formatted = new GsonBuilder().setPrettyPrinting().create().toJson(root);
String formatted = new GsonBuilder()
.setPrettyPrinting()
.create()
.toJson(rootJson);
Files.writeString(configFile.toPath(), formatted);
SaturnClient.LOGGER.info("Config saved successfully.");
} catch (IOException e) {
@@ -109,11 +88,72 @@ public class ConfigManager {
}
}
private static void saveProperties(JsonObject json, Map<String, Property<?>> props) {
props.forEach((name, prop) -> json.add(name, prop.toJson()));
/**
* Recursive save
*/
private static void saveRecursive(JsonObject json, Map<String, Property<?>> map) {
map.forEach((name, prop) -> {
if (prop.isNamespace()) {
JsonObject child = new JsonObject();
saveRecursive(child, prop.getNamespaceMap());
json.add(name, child);
} else {
json.add(name, prop.toJson());
}
});
}
/**
* Recursive load
*/
private static void loadRecursive(JsonObject json, Map<String, Property<?>> map) {
map.forEach((name, prop) -> {
JsonElement element = json.get(name);
if (element == null)
return;
if (prop.isNamespace() && element.isJsonObject()) {
loadRecursive(element.getAsJsonObject(), prop.getNamespaceMap());
} else {
prop.loadFromJson(element);
}
});
}
/**
* Load only a single property immediately after creation
*/
private void loadSingleProperty(String name, Property<?> prop) {
JsonObject source = cachedJson != null ? cachedJson : loadAndCache();
if (source == null)
return;
JsonElement element = source.get(name);
if (element != null)
prop.loadFromJson(element);
}
/**
* Reads file and caches json
*/
private static JsonObject loadAndCache() {
try {
if (!configFile.exists()) {
Files.writeString(configFile.toPath(), "{}");
return new JsonObject();
}
String json = Files.readString(configFile.toPath());
cachedJson = JsonParser.parseString(json).getAsJsonObject();
return cachedJson;
} catch (IOException e) {
SaturnClient.LOGGER.error("Error reading config file", e);
return null;
}
}
public Map<String, Property<?>> getProperties() {
return currentMap;
}
}
}
@@ -286,4 +286,13 @@ public class Property<T> {
if (value != null)
this.loadFromJson(value);
}
public boolean isNamespace() {
return type == PropertyType.NAMESPACE;
}
@SuppressWarnings("unchecked")
public Map<String, Property<?>> getNamespaceMap() {
return isNamespace() ? (Map<String, Property<?>>) (Object) value : null;
}
}