HidekoBot/src/main/java/wtf/beatrice/hidekobot/datasources/ConfigurationSource.java

150 lines
5.5 KiB
Java
Raw Normal View History

2022-11-22 23:44:34 +01:00
package wtf.beatrice.hidekobot.datasources;
2022-11-21 20:19:35 +01:00
2023-01-15 02:05:23 +01:00
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.DumperOptions;
2022-11-21 20:19:35 +01:00
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import wtf.beatrice.hidekobot.HidekoBot;
2022-11-21 20:19:35 +01:00
import java.io.*;
import java.util.LinkedHashMap;
import java.util.Map;
2022-11-21 20:19:35 +01:00
2022-11-22 00:28:33 +01:00
public class ConfigurationSource
2022-11-21 20:19:35 +01:00
{
2022-11-21 23:36:42 +01:00
private final LinkedHashMap<String, Object> configurationEntries = new LinkedHashMap<>();
2023-01-15 02:05:23 +01:00
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationSource.class);
2022-11-21 20:19:35 +01:00
private final String configFilePath;
2022-11-22 00:28:33 +01:00
public ConfigurationSource(String configFilePath)
2022-11-21 20:19:35 +01:00
{
this.configFilePath = configFilePath;
}
public void initConfig()
{
// load the YAML file from the archive's resources folder
/*
* note: this is no longer technically a YAML file, but we are using a very similar structure
* to what SnakeYaml does, so that it can map all entries directly to a YAML file itself.
* we used to have a config.yml file in the "resources" folder, but that is no longer necessary.
*/
LinkedHashMap<String, Object> internalConfigContents = new LinkedHashMap<>(); // map holding all file entries
for(ConfigurationEntry entry : ConfigurationEntry.values())
{
internalConfigContents.put(entry.getPath(), entry.getDefaultValue());
}
if(internalConfigContents.isEmpty())
2022-11-21 20:19:35 +01:00
{
2023-01-15 02:05:23 +01:00
LOGGER.error("Error reading internal configuration!");
HidekoBot.shutdown();
return;
2022-11-21 20:19:35 +01:00
}
// check if config files exists in filesystem
File fsConfigFile = new File(configFilePath);
if(!fsConfigFile.exists())
2022-11-21 20:19:35 +01:00
{
// try to create config file
2023-01-15 05:00:44 +01:00
try {
if(!fsConfigFile.createNewFile())
{
LOGGER.error("We tried creating a file that already exists!");
HidekoBot.shutdown();
return;
}
}
catch (IOException e) {
2023-01-15 02:05:23 +01:00
LOGGER.error("Error creating configuration file!", e);
HidekoBot.shutdown();
return;
}
}
// load the YAML file from the filesystem
Yaml fsConfigYaml = new Yaml(new SafeConstructor());
LinkedHashMap<String, Object> fsConfigContents = null; // map holding all file entries
try (InputStream fsConfigStream = new FileInputStream(fsConfigFile))
{ fsConfigContents = fsConfigYaml.load(fsConfigStream); }
2023-01-15 02:05:23 +01:00
catch (IOException e) { LOGGER.error(e.getMessage()); }
2022-11-21 20:19:35 +01:00
if(fsConfigContents == null) // if file contents are empty or corrupted...
{
// "clean" them (this effectively forces a config file reset)
fsConfigContents = new LinkedHashMap<>();
2022-11-21 20:19:35 +01:00
}
// check for missing keys
boolean missingKeys = false;
for(String key : internalConfigContents.keySet())
{
// if key is missing
if(!fsConfigContents.containsKey(key))
{
// quit and flag it, as we need to complete the file with the missing ones
missingKeys = true;
break;
}
}
// if keys are missing
if(missingKeys)
{
// create a new mixed map that will take existing values from the non-missing keys
// and fill everything else with the default values
LinkedHashMap<String, Object> filledEntries = new LinkedHashMap<>();
for(Map.Entry<String, Object> entry : internalConfigContents.entrySet())
{
String key = entry.getKey();
if(fsConfigContents.containsKey(key))
{
// if the key already exists, copy the original value
filledEntries.put(key, fsConfigContents.get(key));
} else {
// else, copy the value from the example config file
filledEntries.put(key, entry.getValue());
}
}
try {
// new writer to actually write the contents to the file
PrintWriter missingKeysWriter = new PrintWriter(fsConfigFile);
// set yaml options to make the output prettier
DumperOptions dumperOptions = new DumperOptions();
dumperOptions.setIndent(2);
dumperOptions.setPrettyFlow(true);
dumperOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
// create the yaml object and dump the values to filesystem
Yaml yaml = new Yaml(dumperOptions);
yaml.dump(filledEntries, missingKeysWriter);
} catch (FileNotFoundException e) {
2023-01-15 02:05:23 +01:00
LOGGER.error(e.getMessage());
HidekoBot.shutdown();
return;
}
2022-11-21 23:36:42 +01:00
// finally, dump all entries to cache.
loadConfig(filledEntries);
} else {
// if no key is missing, just cache all entries and values from filesystem.
loadConfig(fsConfigContents);
}
2022-11-21 23:36:42 +01:00
}
2022-11-21 20:19:35 +01:00
2022-11-21 23:36:42 +01:00
private void loadConfig(LinkedHashMap<String, Object> configurationEntries)
{
this.configurationEntries.putAll(configurationEntries);
2022-11-21 23:36:42 +01:00
}
public Object getConfigValue(ConfigurationEntry key)
2022-11-21 23:36:42 +01:00
{
return configurationEntries.get(key.getPath());
2022-11-21 20:19:35 +01:00
}
}