Files
common/src/main/java/org/saturnclient/config/ConfigManager.java
T
selimaj-devandclaude df5afe99e3 Remove the upgrade of opaque theme colors from before 0.1.3
Configs saved before 0.1.3 (without a menu blur) had their preset
background and primary colors made translucent on load. It's no longer
needed, so Theme drops it, along with ConfigManager.isSaved, which only
it used.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-30 21:47:45 +02:00

216 lines
5.2 KiB
Java

package org.saturnclient.config;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.LinkedHashMap;
import java.util.Map;
import org.saturnclient.config.property.NamespaceProperty;
import org.saturnclient.config.property.Property;
public class ConfigManager {
private static final ObjectMapper MAPPER = new ObjectMapper();
private static File configFile;
// SINGLE ROOT TREE
private static final Map<String, Property> ROOT = new LinkedHashMap<>();
private static JsonNode cachedJson = null;
private final Map<String, Property> currentMap;
private final String[] path;
/**
* Creates a root namespace
*/
public ConfigManager(File configFile, String namespace) {
ConfigManager.configFile = configFile;
this.currentMap = new LinkedHashMap<>();
this.path = new String[] { namespace };
ROOT.put(namespace, Property.namespace(currentMap));
}
/**
* Creates a root namespace
*/
public ConfigManager(String namespace) {
this.currentMap = new LinkedHashMap<>();
this.path = new String[] { namespace };
ROOT.put(namespace, Property.namespace(currentMap));
}
/**
* Creates a sub-namespace inside a parent
*/
public ConfigManager(ConfigManager parent, String namespace) {
this.currentMap = new LinkedHashMap<>();
this.path = new String[parent.path.length + 1];
System.arraycopy(parent.path, 0, this.path, 0, parent.path.length);
this.path[this.path.length - 1] = namespace;
parent.property(namespace, Property.namespace(currentMap));
}
/**
* Add a property
*/
public Property property(String name, Property value) {
currentMap.put(name, value);
loadSingleProperty(name, value);
return value;
}
/**
* Add a property with the line shown under its name
*/
public Property property(String name, Property value, String description) {
value.description = description;
return property(name, value);
}
/**
* Add empty namespace
*/
public ConfigManager sub(String name) {
return new ConfigManager(this, name);
}
/**
* Load entire config
*/
public void load() {
JsonNode json = loadAndCache();
if (json == null || !json.isObject())
return;
loadRecursive((ObjectNode) json, ROOT);
}
/**
* Save entire config
*/
public static void save() {
ObjectNode rootJson = MAPPER.createObjectNode();
saveRecursive(rootJson, ROOT);
try {
MAPPER.writerWithDefaultPrettyPrinter().writeValue(configFile, rootJson);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Recursive save
*/
private static void saveRecursive(ObjectNode json, Map<String, Property> map) {
map.forEach((name, prop) -> {
if (prop instanceof NamespaceProperty n) {
ObjectNode child = json.objectNode();
saveRecursive(child, n.value);
json.set(name, child);
} else {
json.set(name, prop.toJson());
}
});
}
/**
* Recursive load
*/
private static void loadRecursive(ObjectNode json, Map<String, Property> map) {
map.forEach((name, prop) -> {
JsonNode element = json.get(name);
if (element == null)
return;
if (prop instanceof NamespaceProperty n) {
loadRecursive((ObjectNode) element, n.value);
} else {
prop.loadFromJson(element);
}
});
}
/**
* Load only a single property immediately after creation
*/
private void loadSingleProperty(String name, Property prop) {
JsonNode element = getSaved(name);
if (element != null) {
prop.loadFromJson(element);
}
}
private JsonNode getSaved(String name) {
JsonNode source = cachedJson != null ? cachedJson : loadAndCache();
if (source == null || !source.isObject())
return null;
JsonNode currentScope = source;
for (String segment : path) {
JsonNode next = currentScope.get(segment);
if (next != null && next.isObject()) {
currentScope = next;
} else {
return null;
}
}
return currentScope.get(name);
}
/**
* Reads file and caches json
*/
private JsonNode loadAndCache() {
try {
if (!configFile.exists()) {
Files.writeString(configFile.toPath(), "{}");
cachedJson = MAPPER.createObjectNode();
return cachedJson;
}
cachedJson = MAPPER.readTree(configFile);
return cachedJson;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public Map<String, Property> getProperties() {
return currentMap;
}
}