kerosene/src/main/java/pm/j4/kerosene/util/config/ConfigManager.java

309 lines
8.5 KiB
Java

package pm.j4.kerosene.util.config;
import com.google.common.reflect.TypeToken;
import com.google.gson.*;
import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.*;
import net.fabricmc.loader.api.FabricLoader;
import pm.j4.kerosene.modules.bindings.BindingInfo;
import pm.j4.kerosene.util.data.ModInfoProvider;
import pm.j4.kerosene.util.data.ModuleConfig;
import pm.j4.kerosene.util.data.OptionSerializiable;
import pm.j4.kerosene.util.module.ModuleBase;
/**
* The type Config manager.
*/
public class ConfigManager {
/**
* The constant GSON.
*/
public static final Gson GSON = new GsonBuilder()
.registerTypeAdapter(GlobalConfig.class, SerializationHelper.getGlobalSerializer())
.registerTypeAdapter(GlobalConfig.class, SerializationHelper.getGlobalDeserializer())
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).setPrettyPrinting().create();
/**
* The constant config.
*/
private static final Map<String, ConfigHolder> configs = new HashMap<>();
/**
* Prepare config file.
*
* @param path the path
* @param filename the filename
* @return the file
*/
private static File prepareConfigFile(String path, String filename) {
if (!Objects.equals(path, "")) {
File directory = new File(FabricLoader.getInstance().getConfigDir().toString(), path);
if (!directory.exists()) //noinspection ResultOfMethodCallIgnored
directory.mkdir();
}
return new File(FabricLoader.getInstance().getConfigDir().toString(), path + filename);
}
/**
* Init config.
*
* @param moduleName the module name
*/
public static void initConfig(String moduleName, Class parent) {
try {
Annotation moduleAnnotation = parent.getAnnotation(Modules.class);
if (moduleAnnotation != null) {
Module[] modules = ((Modules)moduleAnnotation).value();
System.out.println(modules);
for (int i = 0; i < modules.length; i++) {
System.out.println(modules[i].value());
ModInfoProvider.registerMod(modules[i].value());
}
}
}
catch (Exception e) {
System.out.println(e);
}
System.out.println("init " + moduleName);
if (configs.containsKey(moduleName)) {
System.out.println("contains " + configs.get(moduleName));
return;
}
ConfigHolder config = new ConfigHolder();
config.globalConfig = new GlobalConfig();
config.serverConfigs = new HashMap<>();
System.out.println("load cfg");
config = load(moduleName + "/", moduleName +".json", ConfigHolder.class);
initModules();
System.out.println("put cfg");
configs.put(moduleName, config);
}
/**
* Init modules.
*
*/
public static void initModules() {
ModInfoProvider.getRegisteredMods().forEach(module -> {
System.out.println("module" + module.getModuleName() + " initialized " + module.initialized);
if (!module.initialized) {
ModuleConfig options = load(module.getParent() + "/modules/", module.getModuleName() + ".json", ModuleConfig.class);
System.out.println("initialize " + module.getModuleName());
if (options != null && options.options != null) {
options.options.forEach((key, option) -> {
if (module.hasOption(option.key) && option.value != null) {
module.setConfigOption(option.key, option.value);
}
else {
System.out.println("ignoring unknown option " + option.key);
}
});
}
module.initialized = true;
}
});
}
/**
* Load.
*
* @param <T> the type parameter
* @param path the path
* @param filename the filename
* @param tClass the t class
* @return the t
*/
private static <T> T load(String path, String filename, Class<T> tClass) {
File file = prepareConfigFile(path, filename);
try {
if (!file.exists()) {
save(path, filename, tClass.newInstance());
}
if (file.exists()) {
BufferedReader reader = new BufferedReader(new FileReader(file));
T parsedConfig = null;
try {
parsedConfig = GSON.fromJson(reader, tClass);
} catch (Exception e) {
System.out.println("Couldn't parse config file");
e.printStackTrace();
}
if (parsedConfig != null) {
return parsedConfig;
}
}
} catch (FileNotFoundException | InstantiationException | IllegalAccessException e) {
System.out.println("Couldn't load configuration file at " + path);
e.printStackTrace();
}
return null;
}
/**
* Deserialize element t.
*
* @param <T> the type parameter
* @param element the element
* @param valueClass the t class
* @return the t
*/
public static <T> T deserializeElement(JsonElement element, Class<T> valueClass) {
return GSON.fromJson(element, valueClass);
}
public static <T> JsonElement serializeElement(T value) {
return GSON.toJsonTree(value);
}
/**
* Save.
*
* @param <T> the type parameter
* @param path the path
* @param filename the filename
* @param data the data
*/
private static <T> void save(String path, String filename, T data) {
File file = prepareConfigFile(path, filename);
String json = GSON.toJson(data);
try (FileWriter fileWriter = new FileWriter(file)) {
fileWriter.write(json);
} catch (IOException e) {
System.out.println("Couldn't save configuration file at " + path);
e.printStackTrace();
}
}
/**
* Save module.
*
* @param modName the mod name
* @param b the b
*/
public static void saveModule(String modName, ModuleBase b) {
ModuleConfig c = new ModuleConfig();
c.options = GlobalConfig.serializeModuleConfiguration(b);
save(modName + "/modules/", b.getModuleName() + ".json", c);
}
/**
* Save all modules.
*/
public static void saveAllModules() {
List<ModuleBase> mods = ModInfoProvider.getRegisteredMods();
mods.forEach((module) -> ConfigManager.saveModule(module.getParent(), module));
}
/**
* Save global config.
*
* @param modName the mod name
*/
public static void saveGlobalConfig(String modName) {
if(configs.containsKey(modName)) {
save(modName + "/", modName + ".json", configs.get(modName));
}
}
public static void saveEverything() {
configs.keySet().forEach(key -> {
saveGlobalConfig(key);
});
saveAllModules();
}
/**
* Gets config.
*
* @param modName the mod name
* @return the config
*/
public static Optional<ConfigHolder> getConfig(String modName) {
if (configs.containsKey(modName)) {
return Optional.of(configs.get(modName));
}
return Optional.empty();
}
public static Map<String, ConfigHolder> getAllConfigs() {
return configs;
}
}
/**
* The type Serialization helper.
*/
@SuppressWarnings("UnstableApiUsage")
class SerializationHelper {
/**
* The constant s.
*/
private static final JsonSerializer<GlobalConfig> GLOBAL_CONFIG_JSON_SERIALIZER = (src, typeOfSrc, ctx) -> {
JsonObject jsonConfig = new JsonObject();
JsonArray bindings = ctx.serialize(src.serializeBindings()).getAsJsonArray();
jsonConfig.add("bindings", bindings);
JsonArray modules = ctx.serialize(src.enabledModules).getAsJsonArray();
jsonConfig.add("enabled_modules", modules);
return jsonConfig;
};
/**
* The constant ds.
*/
private static final JsonDeserializer<GlobalConfig> GLOBAL_CONFIG_JSON_DESERIALIZER = ((json, typeOfT, ctx) -> {
JsonObject obj = json.getAsJsonObject();
List<BindingInfo> bindings = new ArrayList<>();
if (obj.has("bindings")) {
obj.get("bindings").getAsJsonArray().forEach(b -> bindings.add(ctx.deserialize(b, BindingInfo.class)));
}
List<String> modules = new ArrayList<>();
if (obj.has("enabled_modules")) {
obj.get("enabled_modules").getAsJsonArray().forEach(m -> modules.add(m.getAsString()));
}
GlobalConfig cfg = new GlobalConfig();
Map<String, List<OptionSerializiable>> options;
Type type = new TypeToken<Map<String, List<OptionSerializiable>>>() {
}.getType();
if (obj.has("module_configuration")) {
options = ctx.deserialize(obj.get("module_configuration"), type);
} else {
options = new HashMap<>();
}
ModInfoProvider.getRegisteredMods().forEach(module -> {
if (options.containsKey(module.getModuleName())) {
cfg.deserializeModuleConfiguration(options.get(module.getModuleName()), module);
}
});
cfg.deserializeBindings(bindings);
cfg.enabledModules = modules;
return cfg;
});
/**
* Gets serializer.
*
* @return the serializer
*/
public static JsonSerializer<GlobalConfig> getGlobalSerializer() {
return GLOBAL_CONFIG_JSON_SERIALIZER;
}
/**
* Gets deserializer.
*
* @return the deserializer
*/
public static JsonDeserializer<GlobalConfig> getGlobalDeserializer() {
return GLOBAL_CONFIG_JSON_DESERIALIZER;
}
}