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; package org.saturnclient.saturnclient.config;
import com.google.gson.*; import com.google.gson.*;
import org.saturnclient.saturnclient.SaturnClient;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.*; import java.util.LinkedHashMap;
import org.saturnclient.saturnclient.SaturnClient; import java.util.Map;
public class ConfigManager { 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 final File configFile =
private static JsonObject cachedThemeJson = null; 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 Map<String, Property<?>> currentMap;
private final String namespace;
/**
* Creates a root namespace
*/
public ConfigManager(String namespace) { public ConfigManager(String namespace) {
this.namespace = namespace;
this.currentMap = new LinkedHashMap<>(); this.currentMap = new LinkedHashMap<>();
properties.put(namespace, currentMap); ROOT.put(namespace, Property.namespace(currentMap));
System.out.println("Created namespace: " + namespace);
} }
/**
* Creates a sub-namespace inside a parent
*/
public ConfigManager(ConfigManager parent, String namespace) { public ConfigManager(ConfigManager parent, String namespace) {
this.namespace = namespace;
this.currentMap = new LinkedHashMap<>(); this.currentMap = new LinkedHashMap<>();
Property<Map<String, Property<?>>> nsProp = Property.namespace(currentMap); parent.property(namespace, 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<>()));
} }
/**
* Add a property
*/
public <T> Property<T> property(String name, Property<T> value) { public <T> Property<T> property(String name, Property<T> value) {
currentMap.put(name, value); currentMap.put(name, value);
loadProp(name, value); loadSingleProperty(name, value);
return value; return value;
} }
private <T> void loadProp(String name, Property<T> prop) { /**
JsonObject source = cachedThemeJson != null ? cachedThemeJson : loadAndCache(); * Add empty namespace
if (source == null) */
return; public ConfigManager sub(String name) {
return new ConfigManager(this, name);
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;
}
} }
/**
* Load entire config
*/
public static void load() { public static void load() {
SaturnClient.LOGGER.info("Loading config..."); SaturnClient.LOGGER.info("Loading config...");
JsonObject json = loadAndCache(); JsonObject json = loadAndCache();
if (json == null) if (json == null)
return; return;
properties.forEach((namespace, map) -> { loadRecursive(json, ROOT);
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);
});
} }
/**
* Save entire config
*/
public static void save() { public static void save() {
SaturnClient.LOGGER.info("Saving config..."); SaturnClient.LOGGER.info("Saving config...");
JsonObject root = new JsonObject();
properties.forEach((namespace, map) -> { JsonObject rootJson = new JsonObject();
JsonObject nsJson = new JsonObject(); saveRecursive(rootJson, ROOT);
saveProperties(nsJson, map);
root.add(namespace, nsJson);
});
try { try {
String formatted = new GsonBuilder().setPrettyPrinting().create().toJson(root); String formatted = new GsonBuilder()
.setPrettyPrinting()
.create()
.toJson(rootJson);
Files.writeString(configFile.toPath(), formatted); Files.writeString(configFile.toPath(), formatted);
SaturnClient.LOGGER.info("Config saved successfully."); SaturnClient.LOGGER.info("Config saved successfully.");
} catch (IOException e) { } 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() { public Map<String, Property<?>> getProperties() {
return currentMap; return currentMap;
} }
} }
@@ -286,4 +286,13 @@ public class Property<T> {
if (value != null) if (value != null)
this.loadFromJson(value); 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;
}
} }