LibJF/libjf-config-core-v1/src/main/java/io/gitlab/jfronny/libjf/config/impl/dsl/ConfigBuilderImpl.java

143 lines
5.4 KiB
Java

package io.gitlab.jfronny.libjf.config.impl.dsl;
import io.gitlab.jfronny.commons.serialize.gson.api.v1.GsonHolders;
import io.gitlab.jfronny.gson.JsonElement;
import io.gitlab.jfronny.gson.JsonObject;
import io.gitlab.jfronny.gson.JsonParser;
import io.gitlab.jfronny.gson.stream.JsonWriter;
import io.gitlab.jfronny.libjf.LibJf;
import io.gitlab.jfronny.libjf.config.api.v1.ConfigCategory;
import io.gitlab.jfronny.libjf.config.api.v1.ConfigInstance;
import io.gitlab.jfronny.libjf.config.api.v1.EntryInfo;
import io.gitlab.jfronny.libjf.config.api.v1.dsl.ConfigBuilder;
import io.gitlab.jfronny.libjf.config.impl.entrypoint.JfConfigSafe;
import io.gitlab.jfronny.libjf.config.impl.watch.JfConfigWatchService;
import net.fabricmc.loader.api.FabricLoader;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import java.util.function.Consumer;
public class ConfigBuilderImpl extends CategoryBuilderImpl<ConfigBuilderImpl> implements ConfigBuilder<ConfigBuilderImpl> {
public DslConfigInstance built;
public Consumer<ConfigInstance> load;
public Consumer<ConfigInstance> write;
public Path path;
public ConfigBuilderImpl(String id) {
super(id, "");
load = c -> {
c.getFilePath().ifPresent(path -> {
if (Files.exists(path)) {
try (BufferedReader br = Files.newBufferedReader(path)) {
JsonElement element = JsonParser.parseReader(br);
if (element.isJsonObject()) loadFrom(element.getAsJsonObject(), c);
else LibJf.LOGGER.error("Invalid config: Not a JSON object for " + id);
} catch (Exception e) {
LibJf.LOGGER.error("Could not read config for " + id, e);
}
}
c.write();
});
};
write = c -> {
c.getFilePath().ifPresent(path -> JfConfigWatchService.lock(path, () -> {
try (BufferedWriter bw = Files.newBufferedWriter(path);
JsonWriter jw = GsonHolders.CONFIG.getGson().newJsonWriter(bw)) {
writeTo(jw, c);
} catch (Exception e) {
LibJf.LOGGER.error("Could not write config for " + id, e);
}
}));
};
path = FabricLoader.getInstance().getConfigDir().resolve(id + ".json5");
}
private static void loadFrom(JsonObject source, ConfigCategory category) {
for (EntryInfo<?> entry : category.getEntries()) {
if (source.has(entry.getName())) {
try {
entry.loadFromJson(source.get(entry.getName()));
} catch (IllegalAccessException e) {
LibJf.LOGGER.error("Could not set config entry value of " + entry.getName(), e);
}
} else LibJf.LOGGER.error("Config does not contain entry for " + entry.getName());
}
for (Map.Entry<String, ConfigCategory> entry : category.getCategories().entrySet()) {
if (source.has(entry.getKey())) {
JsonElement el = source.get(entry.getKey());
if (el.isJsonObject()) loadFrom(el.getAsJsonObject(), entry.getValue());
else LibJf.LOGGER.error("Config category is not a JSON object, skipping");
} else LibJf.LOGGER.error("Config does not contain entry for subcategory " + entry.getKey());
}
}
private static void writeTo(JsonWriter writer, ConfigCategory category) throws IOException {
category.fix();
writer.beginObject();
String val;
for (EntryInfo<?> entry : category.getEntries()) {
try {
entry.writeTo(writer, category.getTranslationPrefix());
} catch (IllegalAccessException e) {
LibJf.LOGGER.error("Could not write entry", e);
}
}
for (Map.Entry<String, ConfigCategory> entry : category.getCategories().entrySet()) {
if ((val = JfConfigSafe.TRANSLATION_SUPPLIER.apply(category.getTranslationPrefix() + entry.getKey() + ".title")) != null)
writer.comment(val);
writer.name(entry.getKey());
writeTo(writer, entry.getValue());
}
writer.endObject();
}
@Override
public ConfigBuilderImpl setLoadMethod(Consumer<ConfigInstance> load) {
checkBuilt();
this.load = load;
return this;
}
public ConfigBuilderImpl setWriteMethod(Consumer<ConfigInstance> write) {
checkBuilt();
this.write = write;
return this;
}
@Override
public ConfigBuilderImpl executeAfterWrite(Consumer<ConfigInstance> method) {
checkBuilt();
this.write = this.write.andThen(method);
return null;
}
public ConfigBuilderImpl setPath(Path path) {
checkBuilt();
this.path = path;
return this;
}
@Override
public DslConfigInstance build() {
markBuilt();
built = new DslConfigInstance(id,
translationPrefix,
entries,
presets,
referencedConfigs,
categories,
() -> built,
verifiers,
load,
write,
path);
built.load();
return built;
}
}