diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/ChestCommands.java b/Plugin/src/main/java/me/filoghost/chestcommands/ChestCommands.java
index 5e1bc40..4fc019f 100644
--- a/Plugin/src/main/java/me/filoghost/chestcommands/ChestCommands.java
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/ChestCommands.java
@@ -17,12 +17,11 @@ package me.filoghost.chestcommands;
import me.filoghost.chestcommands.api.internal.BackendAPI;
import me.filoghost.chestcommands.command.CommandHandler;
import me.filoghost.chestcommands.command.framework.CommandFramework;
-import me.filoghost.chestcommands.config.ConfigLoader;
+import me.filoghost.chestcommands.config.framework.ConfigLoader;
import me.filoghost.chestcommands.config.ConfigManager;
-import me.filoghost.chestcommands.config.files.CustomPlaceholders;
-import me.filoghost.chestcommands.config.files.Lang;
-import me.filoghost.chestcommands.parsing.menu.LoadedMenu;
-import me.filoghost.chestcommands.config.files.Settings;
+import me.filoghost.chestcommands.config.CustomPlaceholders;
+import me.filoghost.chestcommands.config.Lang;
+import me.filoghost.chestcommands.config.Settings;
import me.filoghost.chestcommands.hook.BarAPIHook;
import me.filoghost.chestcommands.hook.BungeeCordHook;
import me.filoghost.chestcommands.hook.PlaceholderAPIHook;
@@ -34,10 +33,11 @@ import me.filoghost.chestcommands.listener.InventoryListener;
import me.filoghost.chestcommands.listener.JoinListener;
import me.filoghost.chestcommands.listener.SignListener;
import me.filoghost.chestcommands.menu.MenuManager;
+import me.filoghost.chestcommands.parsing.menu.LoadedMenu;
import me.filoghost.chestcommands.task.RefreshMenusTask;
+import me.filoghost.chestcommands.util.Log;
import me.filoghost.chestcommands.util.Utils;
import me.filoghost.chestcommands.util.collection.ErrorCollector;
-import me.filoghost.chestcommands.util.Log;
import me.filoghost.updatechecker.UpdateChecker;
import org.bstats.bukkit.MetricsLite;
import org.bukkit.Bukkit;
@@ -152,9 +152,9 @@ public class ChestCommands extends JavaPlugin {
public ErrorCollector load() {
ErrorCollector errors = new ErrorCollector();
menuManager.clear();
- boolean isFreshInstall = !Files.isDirectory(configManager.getBaseDataPath());
+ boolean isFreshInstall = !Files.isDirectory(configManager.getRootDataFolder());
try {
- Files.createDirectories(configManager.getBaseDataPath());
+ Files.createDirectories(configManager.getRootDataFolder());
} catch (IOException e) {
errors.addError("Plugin failed to load, couldn't create data folder.");
return errors;
@@ -172,7 +172,7 @@ public class ChestCommands extends JavaPlugin {
// Create the menu folder with the example menu
if (!Files.isDirectory(configManager.getMenusFolder())) {
- ConfigLoader exampleMenuLoader = new ConfigLoader(configManager.getMenusFolder().resolve("example.yml"));
+ ConfigLoader exampleMenuLoader = configManager.getConfigLoader(configManager.getMenusFolder().resolve("example.yml"));
configManager.tryCreateDefault(exampleMenuLoader);
}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/ConfigLoader.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/ConfigLoader.java
deleted file mode 100644
index 7c8cd2b..0000000
--- a/Plugin/src/main/java/me/filoghost/chestcommands/config/ConfigLoader.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package me.filoghost.chestcommands.config;
-
-import me.filoghost.chestcommands.util.Preconditions;
-import org.bukkit.configuration.InvalidConfigurationException;
-import org.bukkit.configuration.file.YamlConfiguration;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.net.URLConnection;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.stream.Collectors;
-import java.util.stream.StreamSupport;
-
-public class ConfigLoader {
-
- private final Path path;
-
- public ConfigLoader(Path path) {
- this.path = path;
- }
-
- public Path getPath() {
- return path;
- }
-
- public void createDefault(Path baseDataPath) throws IOException {
- if (!path.startsWith(baseDataPath)) {
- throw new IOException("Config file " + path + " must be inside " + baseDataPath);
- }
-
- if (Files.exists(path)) {
- return;
- }
-
- if (path.getParent() != null) {
- Files.createDirectories(path.getParent());
- }
-
- Path absoluteDataPath = baseDataPath.toAbsolutePath();
- Path absoluteConfigPath = path.toAbsolutePath();
-
- if (absoluteConfigPath.startsWith(absoluteDataPath)) {
- Path relativeConfigPath = absoluteDataPath.relativize(absoluteConfigPath);
- String internalJarPath = toInternalJarPath(relativeConfigPath);
-
- try (InputStream defaultFile = getResource(internalJarPath)) {
- if (defaultFile != null) {
- Files.copy(defaultFile, path);
- return;
- }
- }
- }
-
- Files.createFile(path);
- }
-
- private String toInternalJarPath(Path path) {
- return StreamSupport.stream(path.spliterator(), false)
- .map(Path::toString)
- .collect(Collectors.joining("/", "/", ""));
- }
-
-
- private InputStream getResource(String internalJarPath) throws IOException {
- Preconditions.notNull(internalJarPath, "internalJarPath");
-
- URL resourceURL = getClass().getResource(internalJarPath);
- if (resourceURL == null) {
- return null;
- }
-
- URLConnection connection = resourceURL.openConnection();
- connection.setUseCaches(false);
- return connection.getInputStream();
- }
-
-
- public Config load() throws IOException, InvalidConfigurationException {
- YamlConfiguration yaml = new YamlConfiguration();
-
- try (BufferedReader reader = Files.newBufferedReader(path)) {
- yaml.load(reader);
- }
-
- return new Config(yaml, path);
- }
-
- public Config loadEmpty() {
- return new Config(new YamlConfiguration(), path);
- }
-
- public void save(Config config) throws IOException {
- if (path.getParent() != null) {
- Files.createDirectories(path.getParent());
- }
-
- String data = config.saveToString();
-
- try (BufferedWriter writer = Files.newBufferedWriter(path)) {
- writer.write(data);
- }
- }
-
- public String getFileName() {
- return path.getFileName().toString();
- }
-
-}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/ConfigManager.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/ConfigManager.java
index 5b70d7b..fe0339e 100644
--- a/Plugin/src/main/java/me/filoghost/chestcommands/config/ConfigManager.java
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/ConfigManager.java
@@ -14,14 +14,17 @@
*/
package me.filoghost.chestcommands.config;
-import me.filoghost.chestcommands.config.files.CustomPlaceholders;
-import me.filoghost.chestcommands.config.files.Lang;
+import me.filoghost.chestcommands.config.framework.BaseConfigManager;
+import me.filoghost.chestcommands.config.framework.Config;
+import me.filoghost.chestcommands.config.framework.ConfigLoader;
+import me.filoghost.chestcommands.config.framework.exception.ConfigException;
+import me.filoghost.chestcommands.config.framework.exception.ConfigSyntaxException;
+import me.filoghost.chestcommands.config.framework.mapped.MappedConfigLoader;
import me.filoghost.chestcommands.parsing.menu.LoadedMenu;
-import me.filoghost.chestcommands.config.files.Settings;
import me.filoghost.chestcommands.parsing.menu.MenuParser;
-import me.filoghost.chestcommands.util.collection.ErrorCollector;
import me.filoghost.chestcommands.util.Log;
-import org.bukkit.configuration.InvalidConfigurationException;
+import me.filoghost.chestcommands.util.Preconditions;
+import me.filoghost.chestcommands.util.collection.ErrorCollector;
import java.io.IOException;
import java.nio.file.FileVisitOption;
@@ -33,55 +36,46 @@ import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-public class ConfigManager {
+public class ConfigManager extends BaseConfigManager {
- private final Path baseDataPath;
- private final ConfigLoader settingsConfigLoader;
+ private final MappedConfigLoader settingsConfigLoader;
private final ConfigLoader placeholdersConfigLoader;
- private final ConfigLoader langConfigLoader;
+ private final MappedConfigLoader langConfigLoader;
- public ConfigManager(Path baseDataPath) {
- this.baseDataPath = baseDataPath;
- settingsConfigLoader = new ConfigLoader(baseDataPath.resolve("config.yml"));
- placeholdersConfigLoader = new ConfigLoader(baseDataPath.resolve("custom-placeholders.yml"));
- langConfigLoader = new ConfigLoader(baseDataPath.resolve("lang.yml"));
+ public ConfigManager(Path rootDataFolder) {
+ super(rootDataFolder);
+
+ settingsConfigLoader = getMappedConfigLoader("config.yml", Settings::new);
+ placeholdersConfigLoader = getConfigLoader("custom-placeholders.yml");
+ langConfigLoader = getMappedConfigLoader("lang.yml", Lang::new);
}
public Settings tryLoadSettings() {
- Settings settings = new Settings();
-
try {
- settingsConfigLoader.createDefault(baseDataPath);
- settings.load(settingsConfigLoader);
- } catch (Throwable t) {
- logConfigLoadException(settingsConfigLoader, t);
+ return settingsConfigLoader.init();
+ } catch (ConfigException e) {
+ logConfigInitException(settingsConfigLoader.getFileName(), e);
+ return new Settings();
}
-
- return settings;
}
public Lang tryLoadLang() {
- Lang lang = new Lang();
-
try {
- langConfigLoader.createDefault(baseDataPath);
- lang.load(langConfigLoader);
- } catch (Throwable t) {
- logConfigLoadException(langConfigLoader, t);
+ return langConfigLoader.init();
+ } catch (ConfigException e) {
+ logConfigInitException(langConfigLoader.getFileName(), e);
+ return new Lang();
}
-
- return lang;
}
public CustomPlaceholders tryLoadCustomPlaceholders(ErrorCollector errorCollector) {
CustomPlaceholders placeholders = new CustomPlaceholders();
try {
- placeholdersConfigLoader.createDefault(baseDataPath);
- Config placeholdersConfig = placeholdersConfigLoader.load();
+ Config placeholdersConfig = placeholdersConfigLoader.init();
placeholders.load(placeholdersConfig, errorCollector);
- } catch (Throwable t) {
- logConfigLoadException(placeholdersConfigLoader, t);
+ } catch (ConfigException t) {
+ logConfigInitException(placeholdersConfigLoader.getFileName(), t);
}
return placeholders;
@@ -89,20 +83,22 @@ public class ConfigManager {
public void tryCreateDefault(ConfigLoader configLoader) {
try {
- configLoader.createDefault(baseDataPath);
- } catch (Throwable t) {
- logConfigLoadException(configLoader, t);
+ configLoader.createDefault();
+ } catch (ConfigException e) {
+ logConfigInitException(configLoader.getFileName(), e);
}
}
public Path getMenusFolder() {
- return baseDataPath.resolve("menu");
+ return rootDataFolder.resolve("menu");
}
/**
* Returns a list of YML menu files.
*/
public List getMenuPaths() throws IOException {
+ Preconditions.checkState(Files.isDirectory(getMenusFolder()), "menus folder doesn't exist");
+
try (Stream paths = Files.walk(getMenusFolder(), FileVisitOption.FOLLOW_LINKS)) {
return paths.filter(Files::isRegularFile)
.filter(this::isYmlPath)
@@ -110,39 +106,15 @@ public class ConfigManager {
}
}
-
- private boolean isYmlPath(Path path) {
- return path.getFileName().toString().toLowerCase().endsWith(".yml");
- }
-
- private void logConfigLoadException(ConfigLoader configLoader, Throwable t) {
- t.printStackTrace();
-
- if (t instanceof IOException) {
- Log.warning("Error while reading the file \"" + configLoader.getFileName() + "\". Default values will be used.");
- } else if (t instanceof InvalidConfigurationException) {
- Log.warning("Invalid YAML syntax in the file \"" + configLoader.getFileName() + "\", please look at the error above. Default values will be used.");
+ private void logConfigInitException(String fileName, ConfigException e) {
+ if (e instanceof ConfigSyntaxException) {
+ Log.warning("Invalid YAML syntax in config file \"" + fileName + "\": " + e.getMessage());
} else {
- Log.warning("Unhandled error while parsing the file \"" + configLoader.getFileName() + "\". Please inform the developer.");
+ e.printStackTrace();
+ Log.warning("Error while reading config file \"" + fileName + "\": " + e.getMessage());
}
}
- public Path getBaseDataPath() {
- return baseDataPath;
- }
-
- public ConfigLoader getSettingsConfigLoader() {
- return settingsConfigLoader;
- }
-
- public ConfigLoader getPlaceholdersConfigLoader() {
- return placeholdersConfigLoader;
- }
-
- public ConfigLoader getLangConfigLoader() {
- return langConfigLoader;
- }
-
public List tryLoadMenus(ErrorCollector errorCollector) {
List loadedMenus = new ArrayList<>();
List menuPaths;
@@ -155,16 +127,21 @@ public class ConfigManager {
}
for (Path menuFile : menuPaths) {
- ConfigLoader menuConfigLoader = new ConfigLoader(menuFile);
+ ConfigLoader menuConfigLoader = new ConfigLoader(rootDataFolder, menuFile);
try {
Config menuConfig = menuConfigLoader.load();
loadedMenus.add(MenuParser.loadMenu(menuConfig, errorCollector));
- } catch (Throwable t) {
- logConfigLoadException(menuConfigLoader, t);
+ } catch (ConfigException e) {
+ logConfigInitException(menuConfigLoader.getFileName(), e);
}
}
return loadedMenus;
}
+
+ private boolean isYmlPath(Path path) {
+ return path.getFileName().toString().toLowerCase().endsWith(".yml");
+ }
+
}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/ConfigValueException.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/ConfigValueException.java
deleted file mode 100644
index 61aa8b1..0000000
--- a/Plugin/src/main/java/me/filoghost/chestcommands/config/ConfigValueException.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package me.filoghost.chestcommands.config;
-
-public class ConfigValueException extends Exception {
-
- public ConfigValueException(String message) {
- super(message);
- }
-
-}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/files/CustomPlaceholders.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/CustomPlaceholders.java
similarity index 83%
rename from Plugin/src/main/java/me/filoghost/chestcommands/config/files/CustomPlaceholders.java
rename to Plugin/src/main/java/me/filoghost/chestcommands/config/CustomPlaceholders.java
index 5164727..b8b4beb 100644
--- a/Plugin/src/main/java/me/filoghost/chestcommands/config/files/CustomPlaceholders.java
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/CustomPlaceholders.java
@@ -12,12 +12,12 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-package me.filoghost.chestcommands.config.files;
+package me.filoghost.chestcommands.config;
-import me.filoghost.chestcommands.config.Config;
-import me.filoghost.chestcommands.util.collection.ErrorCollector;
+import me.filoghost.chestcommands.config.framework.Config;
import me.filoghost.chestcommands.util.Colors;
import me.filoghost.chestcommands.util.collection.CollectionUtils;
+import me.filoghost.chestcommands.util.collection.ErrorCollector;
import java.util.HashMap;
import java.util.List;
@@ -36,12 +36,12 @@ public class CustomPlaceholders {
String replacement = Colors.addColors(config.getString(key));
if (placeholder.length() == 0) {
- errorCollector.addError("Error in " + config.getFileName() + ": placeholder cannot be empty (skipped).");
+ errorCollector.addError("Error in " + config.getSourceFileName() + ": placeholder cannot be empty (skipped).");
continue;
}
if (placeholder.length() > 100) {
- errorCollector.addError("Error in " + config.getFileName() + ": placeholder cannot be longer than 100 character (" + placeholder + ").");
+ errorCollector.addError("Error in " + config.getSourceFileName() + ": placeholder cannot be longer than 100 character (" + placeholder + ").");
continue;
}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/files/Lang.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/Lang.java
similarity index 85%
rename from Plugin/src/main/java/me/filoghost/chestcommands/config/files/Lang.java
rename to Plugin/src/main/java/me/filoghost/chestcommands/config/Lang.java
index 53dc987..7108241 100644
--- a/Plugin/src/main/java/me/filoghost/chestcommands/config/files/Lang.java
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/Lang.java
@@ -12,11 +12,13 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-package me.filoghost.chestcommands.config.files;
+package me.filoghost.chestcommands.config;
-import me.filoghost.chestcommands.config.SpecialConfig;
+import me.filoghost.chestcommands.config.framework.mapped.MappedConfig;
+import me.filoghost.chestcommands.config.framework.mapped.modifier.ChatColors;
-public class Lang extends SpecialConfig {
+@ChatColors
+public class Lang extends MappedConfig {
public String no_open_permission = "&cYou don't have permission &e{permission} &cto use this menu.";
public String default_no_icon_permission = "&cYou don't have permission for this icon.";
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/files/Settings.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/Settings.java
similarity index 70%
rename from Plugin/src/main/java/me/filoghost/chestcommands/config/files/Settings.java
rename to Plugin/src/main/java/me/filoghost/chestcommands/config/Settings.java
index a8bd20c..d308eb4 100644
--- a/Plugin/src/main/java/me/filoghost/chestcommands/config/files/Settings.java
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/Settings.java
@@ -12,11 +12,13 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-package me.filoghost.chestcommands.config.files;
+package me.filoghost.chestcommands.config;
-import me.filoghost.chestcommands.config.SpecialConfig;
+import me.filoghost.chestcommands.config.framework.mapped.MappedConfig;
+import me.filoghost.chestcommands.config.framework.mapped.modifier.ChatColors;
-public class Settings extends SpecialConfig {
+@ChatColors
+public class Settings extends MappedConfig {
public String default_color__name = "&f";
public String default_color__lore = "&7";
@@ -25,8 +27,8 @@ public class Settings extends SpecialConfig {
public Settings() {
setHeader(
- "ChestCommands main configuration file.\n" +
- "Documentation: https://filoghost.me/docs/chest-commands\n");
+ "ChestCommands main configuration file.",
+ "Documentation: https://filoghost.me/docs/chest-commands");
}
}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/SpecialConfig.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/SpecialConfig.java
deleted file mode 100644
index d6a285f..0000000
--- a/Plugin/src/main/java/me/filoghost/chestcommands/config/SpecialConfig.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package me.filoghost.chestcommands.config;
-
-import me.filoghost.chestcommands.util.Colors;
-import me.filoghost.chestcommands.util.Log;
-import org.bukkit.configuration.InvalidConfigurationException;
-
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-
-/**
- * A special configuration wrapper that reads the values using reflection.
- * It will also save default values if not set.
- */
-public abstract class SpecialConfig {
-
- private transient String header;
- private transient Map defaultValuesMap;
-
- public void setHeader(String header) {
- this.header = header;
- }
-
- public void load(ConfigLoader loader) throws IOException, IllegalAccessException, InvalidConfigurationException {
- Config config = loader.load();
-
- // Check if the configuration was initialized
- if (defaultValuesMap == null) {
- defaultValuesMap = new HashMap<>();
-
- // Put the values in the default values map
- for (Field field : getClass().getDeclaredFields()) {
- if (skipField(field)) continue;
-
- field.setAccessible(true);
- String configKey = getConfigNode(field);
-
- try {
- Object defaultValue = field.get(this);
- if (defaultValue != null) {
- defaultValuesMap.put(configKey, defaultValue);
- } else {
- Log.warning("The field " + field.getName() + " was not provided with a default value, please inform the developer.");
- }
-
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- }
- }
-
- boolean needsSave = false;
-
- // Save default values not set
- for (Entry entry : defaultValuesMap.entrySet()) {
- if (!config.isSet(entry.getKey())) {
- needsSave = true;
- config.set(entry.getKey(), entry.getValue());
- }
- }
-
- if (needsSave) {
- config.setHeader(header);
- loader.save(config);
- }
-
- // Now read change the fields
- for (Field field : getClass().getDeclaredFields()) {
- if (skipField(field)) {
- continue;
- }
-
- field.setAccessible(true);
- String configNode = getConfigNode(field);
-
- if (config.isSet(configNode)) {
- Class> type = field.getType();
-
- if (type == boolean.class || type == Boolean.class) {
- field.set(this, config.getBoolean(configNode));
-
- } else if (type == int.class || type == Integer.class) {
- field.set(this, config.getInt(configNode));
-
- } else if (type == double.class || type == Double.class) {
- field.set(this, config.getDouble(configNode));
-
- } else if (type == String.class) {
- field.set(this, Colors.addColors(config.getString(configNode))); // Always add colors
-
- } else {
- Log.warning("Unknown field type: " + field.getType().getName() + " (" + field.getName() + "). Please inform the developer.");
- }
-
- } else {
- field.set(this, defaultValuesMap.get(configNode));
- }
- }
- }
-
-
- private boolean skipField(Field field) {
- int modifiers = field.getModifiers();
- return Modifier.isTransient(modifiers) || Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers);
- }
-
- private String getConfigNode(Field field) {
- return field.getName().replace("__", ".").replace("_", "-");
- }
-
-}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/BaseConfigManager.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/BaseConfigManager.java
new file mode 100644
index 0000000..00efc64
--- /dev/null
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/BaseConfigManager.java
@@ -0,0 +1,51 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package me.filoghost.chestcommands.config.framework;
+
+import me.filoghost.chestcommands.config.framework.mapped.MappedConfig;
+import me.filoghost.chestcommands.config.framework.mapped.MappedConfigLoader;
+
+import java.nio.file.Path;
+import java.util.function.Supplier;
+
+public class BaseConfigManager {
+
+ protected final Path rootDataFolder;
+
+ public BaseConfigManager(Path rootDataFolder) {
+ this.rootDataFolder = rootDataFolder;
+ }
+
+ public Path getRootDataFolder() {
+ return rootDataFolder;
+ }
+
+ public ConfigLoader getConfigLoader(String fileName) {
+ return getConfigLoader(rootDataFolder.resolve(fileName));
+ }
+
+ public ConfigLoader getConfigLoader(Path configPath) {
+ return new ConfigLoader(rootDataFolder, configPath);
+ }
+
+ public MappedConfigLoader getMappedConfigLoader(String fileName, Supplier mappedObjectConstructor) {
+ return getMappedConfigLoader(rootDataFolder.resolve(fileName), mappedObjectConstructor);
+ }
+
+ public MappedConfigLoader getMappedConfigLoader(Path configPath, Supplier mappedObjectConstructor) {
+ return new MappedConfigLoader<>(rootDataFolder, configPath, mappedObjectConstructor);
+ }
+
+}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/Config.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/Config.java
similarity index 73%
rename from Plugin/src/main/java/me/filoghost/chestcommands/config/Config.java
rename to Plugin/src/main/java/me/filoghost/chestcommands/config/framework/Config.java
index b8d43f7..8460851 100644
--- a/Plugin/src/main/java/me/filoghost/chestcommands/config/Config.java
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/Config.java
@@ -12,7 +12,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-package me.filoghost.chestcommands.config;
+package me.filoghost.chestcommands.config.framework;
import org.bukkit.configuration.file.YamlConfiguration;
@@ -21,16 +21,20 @@ import java.nio.file.Path;
public class Config extends ConfigSection {
private final YamlConfiguration yaml;
- private final Path filePath;
+ private final Path sourceFilePath;
- public Config(YamlConfiguration yaml, Path filePath) {
- super(yaml);
- this.yaml = yaml;
- this.filePath = filePath;
+ public Config(Path sourceFilePath) {
+ this(new YamlConfiguration(), sourceFilePath);
}
- public String getFileName() {
- return filePath.getFileName().toString();
+ public Config(YamlConfiguration yaml, Path sourceFilePath) {
+ super(yaml);
+ this.yaml = yaml;
+ this.sourceFilePath = sourceFilePath;
+ }
+
+ public String getSourceFileName() {
+ return sourceFilePath.getFileName().toString();
}
public String saveToString() {
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/ConfigLoader.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/ConfigLoader.java
new file mode 100644
index 0000000..66006a2
--- /dev/null
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/ConfigLoader.java
@@ -0,0 +1,143 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package me.filoghost.chestcommands.config.framework;
+
+import me.filoghost.chestcommands.config.framework.exception.ConfigLoadException;
+import me.filoghost.chestcommands.config.framework.exception.ConfigSaveException;
+import me.filoghost.chestcommands.config.framework.exception.ConfigSyntaxException;
+import me.filoghost.chestcommands.util.Preconditions;
+import org.bukkit.configuration.InvalidConfigurationException;
+import org.bukkit.configuration.file.YamlConfiguration;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+
+public class ConfigLoader {
+
+ private final Path rootDataFolder;
+ private final Path configPath;
+
+ public ConfigLoader(Path rootDataFolder, Path configPath) {
+ Preconditions.checkArgument(configPath.startsWith(rootDataFolder), "config file " + configPath + " cannot be outside " + rootDataFolder);
+
+ this.rootDataFolder = rootDataFolder;
+ this.configPath = configPath;
+ }
+
+ public Config init() throws ConfigSaveException, ConfigLoadException {
+ createDefault();
+ return load();
+ }
+
+ public void createDefault() throws ConfigSaveException {
+ if (fileExists()) {
+ return;
+ }
+
+ createParentDirectory();
+
+ Path relativeConfigPath = rootDataFolder.relativize(configPath);
+ String internalJarPath = toInternalJarPath(relativeConfigPath);
+
+ try (InputStream defaultFile = getInternalResource(internalJarPath)) {
+ if (defaultFile != null) {
+ Files.copy(defaultFile, configPath);
+ } else {
+ Files.createFile(configPath);
+ }
+ } catch (IOException e) {
+ throw new ConfigSaveException("couldn't create default config file " + configPath, e);
+ }
+ }
+
+ private String toInternalJarPath(Path path) {
+ return StreamSupport.stream(path.spliterator(), false)
+ .map(Path::toString)
+ .collect(Collectors.joining("/", "/", ""));
+ }
+
+
+ private InputStream getInternalResource(String internalJarPath) throws IOException {
+ Preconditions.notNull(internalJarPath, "internalJarPath");
+
+ URL resourceURL = getClass().getResource(internalJarPath);
+ if (resourceURL == null) {
+ return null;
+ }
+
+ URLConnection connection = resourceURL.openConnection();
+ connection.setUseCaches(false);
+ return connection.getInputStream();
+ }
+
+ public boolean fileExists() {
+ return (Files.isRegularFile(configPath));
+ }
+
+ public Config load() throws ConfigLoadException {
+ Preconditions.checkState(fileExists(), configPath.getFileName() + " doesn't exist or is not a regular file");
+
+ YamlConfiguration yaml = new YamlConfiguration();
+
+ try (BufferedReader reader = Files.newBufferedReader(configPath)) {
+ yaml.load(reader);
+ } catch (IOException e) {
+ throw new ConfigLoadException("couldn't read config file " + configPath, e);
+ } catch (InvalidConfigurationException e) {
+ throw new ConfigSyntaxException(e.getMessage(), e);
+ }
+
+ return new Config(yaml, configPath);
+ }
+
+ public void save(Config config) throws ConfigSaveException {
+ createParentDirectory();
+
+ String data = config.saveToString();
+
+ try (BufferedWriter writer = Files.newBufferedWriter(configPath)) {
+ writer.write(data);
+ } catch (IOException e) {
+ throw new ConfigSaveException("couldn't write config data to " + configPath, e);
+ }
+ }
+
+ private void createParentDirectory() throws ConfigSaveException {
+ if (configPath.getParent() != null) {
+ try {
+ Files.createDirectories(configPath.getParent());
+ } catch (IOException e) {
+ throw new ConfigSaveException("couldn't create directory " + configPath.getParent(), e);
+ }
+ }
+ }
+
+ public Path getConfigPath() {
+ return configPath;
+ }
+
+ public String getFileName() {
+ return configPath.getFileName().toString();
+ }
+
+}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/ConfigSection.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/ConfigSection.java
similarity index 91%
rename from Plugin/src/main/java/me/filoghost/chestcommands/config/ConfigSection.java
rename to Plugin/src/main/java/me/filoghost/chestcommands/config/framework/ConfigSection.java
index 1e6fe77..70e5ab0 100644
--- a/Plugin/src/main/java/me/filoghost/chestcommands/config/ConfigSection.java
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/ConfigSection.java
@@ -1,5 +1,6 @@
-package me.filoghost.chestcommands.config;
+package me.filoghost.chestcommands.config.framework;
+import me.filoghost.chestcommands.config.framework.exception.ConfigValueException;
import org.bukkit.configuration.ConfigurationSection;
import java.util.ArrayList;
@@ -75,10 +76,6 @@ public class ConfigSection {
return yamlSection.getKeys(deep);
}
- public boolean contains(String path) {
- return yamlSection.contains(path);
- }
-
public boolean isSet(String path) {
return yamlSection.isSet(path);
}
@@ -91,10 +88,6 @@ public class ConfigSection {
return yamlSection.getString(path);
}
- public String getString(String path, String def) {
- return yamlSection.getString(path, def);
- }
-
public int getInt(String path) {
return yamlSection.getInt(path);
}
@@ -107,10 +100,6 @@ public class ConfigSection {
return yamlSection.getDouble(path);
}
- public long getLong(String path) {
- return yamlSection.getLong(path);
- }
-
public List getStringList(String path) {
return yamlSection.getStringList(path);
}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/exception/ConfigException.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/exception/ConfigException.java
new file mode 100644
index 0000000..5dd6b05
--- /dev/null
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/exception/ConfigException.java
@@ -0,0 +1,13 @@
+package me.filoghost.chestcommands.config.framework.exception;
+
+public class ConfigException extends Exception {
+
+ public ConfigException(String message) {
+ super(message);
+ }
+
+ public ConfigException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/exception/ConfigLoadException.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/exception/ConfigLoadException.java
new file mode 100644
index 0000000..c145072
--- /dev/null
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/exception/ConfigLoadException.java
@@ -0,0 +1,9 @@
+package me.filoghost.chestcommands.config.framework.exception;
+
+public class ConfigLoadException extends ConfigException {
+
+ public ConfigLoadException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/exception/ConfigSaveException.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/exception/ConfigSaveException.java
new file mode 100644
index 0000000..de64ce1
--- /dev/null
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/exception/ConfigSaveException.java
@@ -0,0 +1,9 @@
+package me.filoghost.chestcommands.config.framework.exception;
+
+public class ConfigSaveException extends ConfigException {
+
+ public ConfigSaveException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/exception/ConfigSyntaxException.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/exception/ConfigSyntaxException.java
new file mode 100644
index 0000000..5f868c0
--- /dev/null
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/exception/ConfigSyntaxException.java
@@ -0,0 +1,11 @@
+package me.filoghost.chestcommands.config.framework.exception;
+
+import org.bukkit.configuration.InvalidConfigurationException;
+
+public class ConfigSyntaxException extends ConfigLoadException {
+
+ public ConfigSyntaxException(String message, InvalidConfigurationException cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/exception/ConfigValueException.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/exception/ConfigValueException.java
new file mode 100644
index 0000000..2a484b6
--- /dev/null
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/exception/ConfigValueException.java
@@ -0,0 +1,9 @@
+package me.filoghost.chestcommands.config.framework.exception;
+
+public class ConfigValueException extends ConfigException {
+
+ public ConfigValueException(String message) {
+ super(message);
+ }
+
+}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/ConfigMapper.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/ConfigMapper.java
new file mode 100644
index 0000000..686f35a
--- /dev/null
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/ConfigMapper.java
@@ -0,0 +1,157 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package me.filoghost.chestcommands.config.framework.mapped;
+
+import com.google.common.collect.ImmutableList;
+import me.filoghost.chestcommands.config.framework.ConfigSection;
+import me.filoghost.chestcommands.config.framework.mapped.converter.BooleanConverter;
+import me.filoghost.chestcommands.config.framework.mapped.converter.Converter;
+import me.filoghost.chestcommands.config.framework.mapped.converter.DoubleConverter;
+import me.filoghost.chestcommands.config.framework.mapped.converter.IntegerConverter;
+import me.filoghost.chestcommands.config.framework.mapped.converter.ListConverter;
+import me.filoghost.chestcommands.config.framework.mapped.converter.StringConverter;
+import me.filoghost.chestcommands.config.framework.mapped.modifier.ChatColorsModifier;
+import me.filoghost.chestcommands.config.framework.mapped.modifier.ValueModifier;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.stream.Collectors;
+
+public class ConfigMapper {
+
+ private static final List CONVERTERS = ImmutableList.of(
+ new DoubleConverter(),
+ new IntegerConverter(),
+ new BooleanConverter(),
+ new StringConverter(),
+ new ListConverter()
+ );
+
+ private static final List> VALUE_MODIFIERS = ImmutableList.of(
+ new ChatColorsModifier()
+ );
+
+ private final MappedConfig mappedObject;
+ private final ConfigSection config;
+ private final List mappedFields;
+
+ public ConfigMapper(MappedConfig mappedObject, ConfigSection config) throws ReflectiveOperationException {
+ this.mappedObject = mappedObject;
+ this.config = config;
+ this.mappedFields = getMappableFields(mappedObject.getClass());
+ }
+
+ private List getMappableFields(Class> type) throws ReflectiveOperationException {
+ Field[] declaredFields;
+
+ try {
+ declaredFields = type.getDeclaredFields();
+ } catch (Throwable t) {
+ throw new ReflectiveOperationException(t);
+ }
+
+ return Arrays.stream(declaredFields)
+ .filter(this::isMappable)
+ .map(MappedField::new)
+ .collect(Collectors.toList());
+ }
+
+ public Map getFieldValues() throws ReflectiveOperationException {
+ Map mappedFieldValues = new HashMap<>();
+
+ for (MappedField mappedField : mappedFields) {
+ Object defaultValue = mappedField.getFromObject(mappedObject);
+
+ if (defaultValue == null) {
+ throw new IllegalArgumentException("mapped field \"" + mappedField.getFieldName() + "\" cannot be null by default");
+ }
+
+ mappedFieldValues.put(mappedField, defaultValue);
+ }
+
+ return mappedFieldValues;
+ }
+
+ public boolean addMissingConfigValues(Map defaultValues) {
+ boolean modified = false;
+
+ // Add missing values from defaults
+ for (Entry entry : defaultValues.entrySet()) {
+ MappedField mappedField = entry.getKey();
+ Object defaultValue = entry.getValue();
+
+ if (!config.isSet(mappedField.getConfigPath())) {
+ modified = true;
+ Converter converter = findConverter(mappedField.getFieldType());
+ converter.setConfigValue(config, mappedField.getConfigPath(), defaultValue);
+ }
+ }
+
+ return modified;
+ }
+
+ public void injectObjectFields() throws ReflectiveOperationException {
+ for (MappedField mappedField : mappedFields) {
+ injectObjectField(mappedField);
+ }
+ }
+
+ private void injectObjectField(MappedField mappedField) throws ReflectiveOperationException {
+ Type[] genericTypes = mappedField.getGenericTypes();
+ Converter converter = findConverter(mappedField.getFieldType());
+
+ Object fieldValue = converter.getFieldValue(config, mappedField.getConfigPath(), genericTypes);
+
+ for (Annotation annotation : mappedField.getAnnotations()) {
+ fieldValue = applyValueModifiers(fieldValue, annotation);
+ }
+
+ mappedField.setToObject(mappedObject, fieldValue);
+ }
+
+ private Object applyValueModifiers(Object fieldValue, Annotation annotation) {
+ for (ValueModifier, ?> modifier : VALUE_MODIFIERS) {
+ if (modifier.isApplicable(annotation, fieldValue)) {
+ fieldValue = modifier.transform(annotation, fieldValue);
+ }
+ }
+ return fieldValue;
+ }
+
+ private Converter findConverter(Class> type) {
+ return CONVERTERS.stream()
+ .filter(converter -> converter.matches(type))
+ .findFirst()
+ .orElseThrow(() -> new IllegalStateException("cannot find converter for type " + type));
+ }
+
+ private boolean isMappable(Field field) {
+ int modifiers = field.getModifiers();
+ boolean includeStatic = field.isAnnotationPresent(IncludeStatic.class)
+ || field.getDeclaringClass().isAnnotationPresent(IncludeStatic.class);
+
+ return (!Modifier.isStatic(modifiers) || includeStatic)
+ || !Modifier.isTransient(modifiers)
+ || !Modifier.isFinal(modifiers);
+ }
+
+}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/IncludeStatic.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/IncludeStatic.java
new file mode 100644
index 0000000..c90b557
--- /dev/null
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/IncludeStatic.java
@@ -0,0 +1,26 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package me.filoghost.chestcommands.config.framework.mapped;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD, ElementType.TYPE})
+public @interface IncludeStatic {
+
+}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/MappedConfig.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/MappedConfig.java
new file mode 100644
index 0000000..e97b425
--- /dev/null
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/MappedConfig.java
@@ -0,0 +1,33 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package me.filoghost.chestcommands.config.framework.mapped;
+
+import me.filoghost.chestcommands.config.framework.exception.ConfigLoadException;
+
+public class MappedConfig {
+
+ private String header;
+
+ protected void setHeader(String... header) {
+ this.header = String.join("\n", header) + "\n";
+ }
+
+ public String getHeader() {
+ return header;
+ }
+
+ public void postLoad() throws ConfigLoadException {}
+
+}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/MappedConfigLoader.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/MappedConfigLoader.java
new file mode 100644
index 0000000..fd3208f
--- /dev/null
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/MappedConfigLoader.java
@@ -0,0 +1,78 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package me.filoghost.chestcommands.config.framework.mapped;
+
+import me.filoghost.chestcommands.config.framework.Config;
+import me.filoghost.chestcommands.config.framework.ConfigLoader;
+import me.filoghost.chestcommands.config.framework.exception.ConfigLoadException;
+import me.filoghost.chestcommands.config.framework.exception.ConfigSaveException;
+
+import java.nio.file.Path;
+import java.util.Map;
+import java.util.function.Supplier;
+
+public class MappedConfigLoader {
+
+ private final ConfigLoader configLoader;
+ private final Supplier mappedObjectConstructor;
+ private Map defaultValues;
+
+ public MappedConfigLoader(Path rootDataFolder, Path configPath, Supplier mappedObjectConstructor) {
+ this.configLoader = new ConfigLoader(rootDataFolder, configPath);
+ this.mappedObjectConstructor = mappedObjectConstructor;
+ }
+
+ public T init() throws ConfigLoadException, ConfigSaveException {
+ Config config = configLoader.init();
+ T mappedObject = mappedObjectConstructor.get();
+
+ ConfigMapper mapper;
+ try {
+ mapper = new ConfigMapper(mappedObject, config);
+ } catch (ReflectiveOperationException e) {
+ throw new ConfigLoadException("couldn't initialize config mapper for class " + mappedObject.getClass(), e);
+ }
+
+ // Extract default values from fields
+ if (defaultValues == null) {
+ try {
+ defaultValues = mapper.getFieldValues();
+ } catch (ReflectiveOperationException e) {
+ throw new ConfigLoadException("couldn't read field values in class " + mappedObject.getClass(), e);
+ }
+ }
+
+ // Add missing values and save if necessary
+ boolean modified = mapper.addMissingConfigValues(defaultValues);
+ if (modified) {
+ config.setHeader(mappedObject.getHeader());
+ configLoader.save(config);
+ }
+
+ // Update the mapped object with the contents from the config
+ try {
+ mapper.injectObjectFields();
+ } catch (ReflectiveOperationException e) {
+ throw new ConfigLoadException("couldn't inject fields values in class " + mappedObject.getClass(), e);
+ }
+ mappedObject.postLoad();
+ return mappedObject;
+ }
+
+ public String getFileName() {
+ return configLoader.getFileName();
+ }
+
+}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/MappedField.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/MappedField.java
new file mode 100644
index 0000000..d9370dc
--- /dev/null
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/MappedField.java
@@ -0,0 +1,88 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package me.filoghost.chestcommands.config.framework.mapped;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class MappedField {
+
+ private final Field field;
+ private final String configPath;
+
+ public MappedField(Field field) {
+ this.field = field;
+
+ this.configPath = field.getName()
+ .replace("__", ".")
+ .replace("_", "-");
+ }
+
+ public Object getFromObject(MappedConfig mappedObject) throws ReflectiveOperationException {
+ try {
+ field.setAccessible(true);
+ return field.get(mappedObject);
+ } catch (Throwable t) {
+ throw new ReflectiveOperationException(t);
+ }
+ }
+
+ public void setToObject(MappedConfig mappedObject, Object fieldValue) throws ReflectiveOperationException {
+ try {
+ field.setAccessible(true);
+ field.set(mappedObject, fieldValue);
+ } catch (Throwable t) {
+ throw new ReflectiveOperationException(t);
+ }
+ }
+
+ public Type[] getGenericTypes() throws ReflectiveOperationException {
+ try {
+ Type genericType = field.getGenericType();
+ if (genericType instanceof ParameterizedType) {
+ return ((ParameterizedType) genericType).getActualTypeArguments();
+ } else {
+ return null;
+ }
+ } catch (Throwable t) {
+ throw new ReflectiveOperationException(t);
+ }
+ }
+
+ public List getAnnotations() {
+ return Stream.concat(
+ Arrays.stream(field.getDeclaredAnnotations()),
+ Arrays.stream(field.getDeclaringClass().getDeclaredAnnotations()))
+ .collect(Collectors.toList());
+ }
+
+ public String getFieldName() {
+ return field.getName();
+ }
+
+ public Class> getFieldType() {
+ return field.getType();
+ }
+
+ public String getConfigPath() {
+ return configPath;
+ }
+}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/converter/BooleanConverter.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/converter/BooleanConverter.java
new file mode 100644
index 0000000..2960496
--- /dev/null
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/converter/BooleanConverter.java
@@ -0,0 +1,38 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package me.filoghost.chestcommands.config.framework.mapped.converter;
+
+import me.filoghost.chestcommands.config.framework.ConfigSection;
+
+import java.lang.reflect.Type;
+
+public class BooleanConverter implements Converter {
+
+ @Override
+ public void setConfigValue(ConfigSection config, String path, Object value) {
+ config.set(path, value);
+ }
+
+ @Override
+ public Boolean getFieldValue(ConfigSection config, String path, Type[] parameterizedTypes) {
+ return config.getBoolean(path);
+ }
+
+ @Override
+ public boolean matches(Class> type) {
+ return type == Boolean.class || type == boolean.class;
+ }
+
+}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/converter/Converter.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/converter/Converter.java
new file mode 100644
index 0000000..df0e921
--- /dev/null
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/converter/Converter.java
@@ -0,0 +1,29 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package me.filoghost.chestcommands.config.framework.mapped.converter;
+
+import me.filoghost.chestcommands.config.framework.ConfigSection;
+
+import java.lang.reflect.Type;
+
+public interface Converter {
+
+ void setConfigValue(ConfigSection config, String path, Object value);
+
+ Object getFieldValue(ConfigSection config, String path, Type[] genericTypes);
+
+ boolean matches(Class> type);
+
+}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/converter/DoubleConverter.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/converter/DoubleConverter.java
new file mode 100644
index 0000000..e6c9ffc
--- /dev/null
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/converter/DoubleConverter.java
@@ -0,0 +1,38 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package me.filoghost.chestcommands.config.framework.mapped.converter;
+
+import me.filoghost.chestcommands.config.framework.ConfigSection;
+
+import java.lang.reflect.Type;
+
+public class DoubleConverter implements Converter {
+
+ @Override
+ public void setConfigValue(ConfigSection config, String path, Object value) {
+ config.set(path, value);
+ }
+
+ @Override
+ public Double getFieldValue(ConfigSection config, String path, Type[] parameterizedTypes) {
+ return config.getDouble(path);
+ }
+
+ @Override
+ public boolean matches(Class> type) {
+ return type == Double.class || type == double.class;
+ }
+
+}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/converter/IntegerConverter.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/converter/IntegerConverter.java
new file mode 100644
index 0000000..47ac621
--- /dev/null
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/converter/IntegerConverter.java
@@ -0,0 +1,38 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package me.filoghost.chestcommands.config.framework.mapped.converter;
+
+import me.filoghost.chestcommands.config.framework.ConfigSection;
+
+import java.lang.reflect.Type;
+
+public class IntegerConverter implements Converter {
+
+ @Override
+ public void setConfigValue(ConfigSection config, String path, Object value) {
+ config.set(path, value);
+ }
+
+ @Override
+ public Integer getFieldValue(ConfigSection config, String path, Type[] parameterizedTypes) {
+ return config.getInt(path);
+ }
+
+ @Override
+ public boolean matches(Class> type) {
+ return type == Integer.class || type == int.class;
+ }
+
+}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/converter/ListConverter.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/converter/ListConverter.java
new file mode 100644
index 0000000..99ca844
--- /dev/null
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/converter/ListConverter.java
@@ -0,0 +1,51 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package me.filoghost.chestcommands.config.framework.mapped.converter;
+
+import me.filoghost.chestcommands.config.framework.ConfigSection;
+import me.filoghost.chestcommands.util.Preconditions;
+
+import java.lang.reflect.Type;
+import java.util.List;
+
+public class ListConverter implements Converter {
+
+ @Override
+ public void setConfigValue(ConfigSection config, String path, Object value) {
+ config.set(path, value);
+ }
+
+ @Override
+ public List> getFieldValue(ConfigSection config, String path, Type[] genericTypes) {
+ Preconditions.notNull(genericTypes, "genericTypes");
+ Preconditions.checkArgument(genericTypes.length == 1, "genericTypes length must be 1");
+
+ Type listType = genericTypes[0];
+
+ if (listType == Integer.class) {
+ return config.getIntegerList(path);
+ } else if (listType == String.class) {
+ return config.getStringList(path);
+ } else {
+ throw new IllegalArgumentException("unsupported list type: " + listType);
+ }
+ }
+
+ @Override
+ public boolean matches(Class> type) {
+ return type == List.class;
+ }
+
+}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/converter/StringConverter.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/converter/StringConverter.java
new file mode 100644
index 0000000..422dcbd
--- /dev/null
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/converter/StringConverter.java
@@ -0,0 +1,38 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package me.filoghost.chestcommands.config.framework.mapped.converter;
+
+import me.filoghost.chestcommands.config.framework.ConfigSection;
+
+import java.lang.reflect.Type;
+
+public class StringConverter implements Converter {
+
+ @Override
+ public void setConfigValue(ConfigSection config, String path, Object value) {
+ config.set(path, value);
+ }
+
+ @Override
+ public String getFieldValue(ConfigSection config, String path, Type[] parameterizedTypes) {
+ return config.getString(path);
+ }
+
+ @Override
+ public boolean matches(Class> type) {
+ return type == String.class;
+ }
+
+}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/modifier/ChatColors.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/modifier/ChatColors.java
new file mode 100644
index 0000000..7a8034e
--- /dev/null
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/modifier/ChatColors.java
@@ -0,0 +1,26 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package me.filoghost.chestcommands.config.framework.mapped.modifier;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD, ElementType.TYPE})
+public @interface ChatColors {
+
+}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/modifier/ChatColorsModifier.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/modifier/ChatColorsModifier.java
new file mode 100644
index 0000000..18f65cd
--- /dev/null
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/modifier/ChatColorsModifier.java
@@ -0,0 +1,36 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package me.filoghost.chestcommands.config.framework.mapped.modifier;
+
+import me.filoghost.chestcommands.util.Colors;
+
+public class ChatColorsModifier implements ValueModifier {
+
+ @Override
+ public String transformChecked(ChatColors annotation, String value) {
+ return Colors.addColors(value);
+ }
+
+ @Override
+ public Class getAnnotationType() {
+ return ChatColors.class;
+ }
+
+ @Override
+ public Class getValueType() {
+ return String.class;
+ }
+
+}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/modifier/ValueModifier.java b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/modifier/ValueModifier.java
new file mode 100644
index 0000000..1925f7a
--- /dev/null
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/config/framework/mapped/modifier/ValueModifier.java
@@ -0,0 +1,38 @@
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package me.filoghost.chestcommands.config.framework.mapped.modifier;
+
+import me.filoghost.chestcommands.util.Preconditions;
+
+import java.lang.annotation.Annotation;
+
+public interface ValueModifier {
+
+ V transformChecked(A annotation, V value);
+
+ Class getAnnotationType();
+
+ Class getValueType();
+
+ default boolean isApplicable(Annotation annotation, Object value) {
+ return getAnnotationType().isInstance(annotation) && getValueType().isInstance(value);
+ }
+
+ default Object transform(Annotation annotation, Object fieldValue) {
+ Preconditions.checkArgument(isApplicable(annotation, fieldValue), "modifier doesn't match given types");
+
+ return transformChecked(getAnnotationType().cast(annotation), getValueType().cast(fieldValue));
+ }
+}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/legacy/Upgrade.java b/Plugin/src/main/java/me/filoghost/chestcommands/legacy/Upgrade.java
index dad391f..ee45a69 100644
--- a/Plugin/src/main/java/me/filoghost/chestcommands/legacy/Upgrade.java
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/legacy/Upgrade.java
@@ -14,10 +14,9 @@
*/
package me.filoghost.chestcommands.legacy;
-import me.filoghost.chestcommands.config.Config;
-import me.filoghost.chestcommands.config.ConfigLoader;
+import me.filoghost.chestcommands.config.framework.exception.ConfigLoadException;
+import me.filoghost.chestcommands.config.framework.exception.ConfigSaveException;
import me.filoghost.chestcommands.util.Preconditions;
-import org.bukkit.configuration.InvalidConfigurationException;
import java.io.IOException;
import java.nio.file.Files;
@@ -40,7 +39,11 @@ public abstract class Upgrade {
Preconditions.checkState(!hasRun, "Upgrade can only be run once");
hasRun = true;
- computeChanges();
+ try {
+ computeChanges();
+ } catch (ConfigLoadException e) {
+ throw new UpgradeException("couldn't load file to upgrade \"" + getOriginalFile().getFileName() + "\"", e);
+ }
if (modified) {
try {
@@ -51,7 +54,7 @@ public abstract class Upgrade {
try {
saveChanges();
- } catch (IOException e) {
+ } catch (ConfigSaveException e) {
throw new UpgradeException("couldn't save upgraded file \"" + getUpgradedFile().getFileName() + "\"", e);
}
}
@@ -59,16 +62,6 @@ public abstract class Upgrade {
return modified;
}
- protected Config loadConfig(ConfigLoader configLoader) throws UpgradeException {
- try {
- return configLoader.load();
- } catch (IOException e) {
- throw new UpgradeException("couldn't read configuration file \"" + configLoader.getFileName() + "\"", e);
- } catch (InvalidConfigurationException e) {
- throw new UpgradeException("couldn't parse YAML syntax of file \"" + configLoader.getFileName() + "\"", e);
- }
- }
-
private void createBackupFile(Path path) throws IOException {
String date = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy.MM.dd-HH.mm"));
String backupName = path.getFileName() + "_" + date + ".backup";
@@ -80,8 +73,8 @@ public abstract class Upgrade {
public abstract Path getUpgradedFile();
- protected abstract void computeChanges() throws UpgradeException;
+ protected abstract void computeChanges() throws ConfigLoadException;
- protected abstract void saveChanges() throws IOException;
+ protected abstract void saveChanges() throws ConfigSaveException;
}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/legacy/UpgradesExecutor.java b/Plugin/src/main/java/me/filoghost/chestcommands/legacy/UpgradesExecutor.java
index f49d0fa..f2a54bd 100644
--- a/Plugin/src/main/java/me/filoghost/chestcommands/legacy/UpgradesExecutor.java
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/legacy/UpgradesExecutor.java
@@ -15,7 +15,7 @@
package me.filoghost.chestcommands.legacy;
import me.filoghost.chestcommands.config.ConfigManager;
-import me.filoghost.chestcommands.config.ConfigLoader;
+import me.filoghost.chestcommands.config.framework.ConfigLoader;
import me.filoghost.chestcommands.legacy.UpgradesDoneRegistry.UpgradeID;
import me.filoghost.chestcommands.legacy.upgrades.MenuUpgrade;
import me.filoghost.chestcommands.legacy.upgrades.PlaceholdersUpgrade;
@@ -42,7 +42,7 @@ public class UpgradesExecutor {
public void run(boolean isFreshInstall) throws UpgradeExecutorException {
this.failedUpgrades = new ArrayList<>();
- Path upgradesDoneFile = configManager.getBaseDataPath().resolve(".upgrades-done");
+ Path upgradesDoneFile = configManager.getRootDataFolder().resolve(".upgrades-done");
try {
upgradesDoneRegistry = new UpgradesDoneRegistry(upgradesDoneFile);
@@ -56,18 +56,23 @@ public class UpgradesExecutor {
upgradesDoneRegistry.setAllDone();
} else {
- String legacyCommandSeparator = readLegacyCommandSeparator();
+ String legacyCommandSeparator;
+ if (!upgradesDoneRegistry.isDone(UpgradeID.V4_MENUS)) {
+ legacyCommandSeparator = readLegacyCommandSeparator();
+ } else {
+ legacyCommandSeparator = null;
+ }
- SettingsUpgrade settingsUpgrade = new SettingsUpgrade(configManager.getSettingsConfigLoader());
+ SettingsUpgrade settingsUpgrade = new SettingsUpgrade(configManager);
runIfNecessary(UpgradeID.V4_CONFIG, settingsUpgrade);
- PlaceholdersUpgrade placeholdersUpgrade = new PlaceholdersUpgrade(configManager.getPlaceholdersConfigLoader(), configManager.getBaseDataPath());
+ PlaceholdersUpgrade placeholdersUpgrade = new PlaceholdersUpgrade(configManager);
runIfNecessary(UpgradeID.V4_PLACEHOLDERS, placeholdersUpgrade);
try {
List menuUpgrades = CollectionUtils.transform(
configManager.getMenuPaths(),
- menuPath -> new MenuUpgrade(new ConfigLoader(menuPath), legacyCommandSeparator));
+ menuPath -> new MenuUpgrade(configManager.getConfigLoader(menuPath), legacyCommandSeparator));
runIfNecessary(UpgradeID.V4_MENUS, menuUpgrades);
} catch (IOException e) {
failedUpgrades.add(configManager.getMenusFolder());
@@ -91,18 +96,18 @@ public class UpgradesExecutor {
}
private String readLegacyCommandSeparator() {
- String legacyCommandSeparator;
- ConfigLoader settingsConfigLoader = configManager.getSettingsConfigLoader();
+ ConfigLoader settingsConfigLoader = configManager.getConfigLoader("config.yml");
- try {
- legacyCommandSeparator = settingsConfigLoader.load().getString("multiple-commands-separator", ";");
- } catch (Exception e) {
- legacyCommandSeparator = ";";
- Log.severe("Failed to load " + settingsConfigLoader.getFileName()
- + ", assuming default command separator \"" + legacyCommandSeparator + "\".");
+ if (!settingsConfigLoader.fileExists()) {
+ return null;
}
- return legacyCommandSeparator;
+ try {
+ return settingsConfigLoader.load().getString("multiple-commands-separator");
+ } catch (Throwable t) {
+ Log.severe("Failed to load " + settingsConfigLoader.getFileName() + ", assuming default command separator \";\".");
+ return null;
+ }
}
@@ -143,8 +148,7 @@ public class UpgradesExecutor {
private void logUpgradeException(Upgrade upgrade, UpgradeException upgradeException) {
Log.severe(
- "Error while trying to automatically upgrade "
- + upgrade.getOriginalFile() + ": " + upgradeException.getMessage(),
+ "Error while trying to automatically upgrade " + upgrade.getOriginalFile() + ": " + upgradeException.getMessage(),
upgradeException.getCause());
}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/legacy/upgrades/MenuUpgrade.java b/Plugin/src/main/java/me/filoghost/chestcommands/legacy/upgrades/MenuUpgrade.java
index 14e3f97..e37f38d 100644
--- a/Plugin/src/main/java/me/filoghost/chestcommands/legacy/upgrades/MenuUpgrade.java
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/legacy/upgrades/MenuUpgrade.java
@@ -14,16 +14,16 @@
*/
package me.filoghost.chestcommands.legacy.upgrades;
-import me.filoghost.chestcommands.config.Config;
-import me.filoghost.chestcommands.config.ConfigLoader;
-import me.filoghost.chestcommands.config.ConfigSection;
+import me.filoghost.chestcommands.config.framework.Config;
+import me.filoghost.chestcommands.config.framework.ConfigLoader;
+import me.filoghost.chestcommands.config.framework.ConfigSection;
+import me.filoghost.chestcommands.config.framework.exception.ConfigLoadException;
+import me.filoghost.chestcommands.config.framework.exception.ConfigSaveException;
import me.filoghost.chestcommands.legacy.Upgrade;
-import me.filoghost.chestcommands.legacy.UpgradeException;
-import me.filoghost.chestcommands.parsing.menu.MenuSettingsNode;
import me.filoghost.chestcommands.parsing.icon.IconSettingsNode;
+import me.filoghost.chestcommands.parsing.menu.MenuSettingsNode;
import me.filoghost.chestcommands.util.Strings;
-import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
@@ -43,17 +43,17 @@ public class MenuUpgrade extends Upgrade {
@Override
public Path getOriginalFile() {
- return menuConfigLoader.getPath();
+ return menuConfigLoader.getConfigPath();
}
@Override
public Path getUpgradedFile() {
- return menuConfigLoader.getPath();
+ return menuConfigLoader.getConfigPath();
}
@Override
- protected void computeChanges() throws UpgradeException {
- Config menuConfig = loadConfig(menuConfigLoader);
+ protected void computeChanges() throws ConfigLoadException {
+ Config menuConfig = menuConfigLoader.load();
menuConfig.setHeader(null);
for (String key : menuConfig.getKeys(true)) {
@@ -74,7 +74,7 @@ public class MenuUpgrade extends Upgrade {
}
@Override
- protected void saveChanges() throws IOException {
+ protected void saveChanges() throws ConfigSaveException {
menuConfigLoader.save(updatedConfig);
}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/legacy/upgrades/PlaceholdersUpgrade.java b/Plugin/src/main/java/me/filoghost/chestcommands/legacy/upgrades/PlaceholdersUpgrade.java
index 1d5abbc..9f0142e 100644
--- a/Plugin/src/main/java/me/filoghost/chestcommands/legacy/upgrades/PlaceholdersUpgrade.java
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/legacy/upgrades/PlaceholdersUpgrade.java
@@ -14,10 +14,12 @@
*/
package me.filoghost.chestcommands.legacy.upgrades;
-import me.filoghost.chestcommands.config.Config;
-import me.filoghost.chestcommands.config.ConfigLoader;
+import me.filoghost.chestcommands.config.ConfigManager;
+import me.filoghost.chestcommands.config.framework.Config;
+import me.filoghost.chestcommands.config.framework.ConfigLoader;
+import me.filoghost.chestcommands.config.framework.exception.ConfigLoadException;
+import me.filoghost.chestcommands.config.framework.exception.ConfigSaveException;
import me.filoghost.chestcommands.legacy.Upgrade;
-import me.filoghost.chestcommands.legacy.UpgradeException;
import me.filoghost.chestcommands.util.Strings;
import org.apache.commons.lang.StringEscapeUtils;
@@ -28,13 +30,13 @@ import java.util.List;
public class PlaceholdersUpgrade extends Upgrade {
- private final ConfigLoader newPlaceholdersConfigLoader;
private final Path oldPlaceholdersFile;
+ private final ConfigLoader newPlaceholdersConfigLoader;
private Config updatedConfig;
- public PlaceholdersUpgrade(ConfigLoader placeholdersConfigLoader, Path dataPath) {
- this.newPlaceholdersConfigLoader = placeholdersConfigLoader;
- this.oldPlaceholdersFile = dataPath.resolve("placeholders.yml");
+ public PlaceholdersUpgrade(ConfigManager configManager) {
+ this.oldPlaceholdersFile = configManager.getRootDataFolder().resolve("placeholders.yml");
+ this.newPlaceholdersConfigLoader = configManager.getConfigLoader("custom-placeholders.yml");
}
@Override
@@ -44,22 +46,22 @@ public class PlaceholdersUpgrade extends Upgrade {
@Override
public Path getUpgradedFile() {
- return newPlaceholdersConfigLoader.getPath();
+ return newPlaceholdersConfigLoader.getConfigPath();
}
@Override
- protected void computeChanges() throws UpgradeException {
+ protected void computeChanges() throws ConfigLoadException {
if (!Files.isRegularFile(oldPlaceholdersFile)) {
return;
}
// Do NOT load the new placeholder configuration from disk, as it should only contain placeholders imported from the old file
- Config newPlaceholdersConfig = newPlaceholdersConfigLoader.loadEmpty();
+ Config newPlaceholdersConfig = new Config(newPlaceholdersConfigLoader.getConfigPath());
List lines;
try {
lines = Files.readAllLines(oldPlaceholdersFile);
} catch (IOException e) {
- throw new UpgradeException("couldn't read file \"" + oldPlaceholdersFile.getFileName() + "\"", e);
+ throw new ConfigLoadException("couldn't read file \"" + oldPlaceholdersFile.getFileName() + "\"", e);
}
for (String line : lines) {
@@ -85,7 +87,7 @@ public class PlaceholdersUpgrade extends Upgrade {
}
@Override
- protected void saveChanges() throws IOException {
+ protected void saveChanges() throws ConfigSaveException {
try {
Files.deleteIfExists(oldPlaceholdersFile);
} catch (IOException ignored) {}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/legacy/upgrades/SettingsUpgrade.java b/Plugin/src/main/java/me/filoghost/chestcommands/legacy/upgrades/SettingsUpgrade.java
index b70596a..c3dc2bf 100644
--- a/Plugin/src/main/java/me/filoghost/chestcommands/legacy/upgrades/SettingsUpgrade.java
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/legacy/upgrades/SettingsUpgrade.java
@@ -14,12 +14,13 @@
*/
package me.filoghost.chestcommands.legacy.upgrades;
-import me.filoghost.chestcommands.config.Config;
-import me.filoghost.chestcommands.config.ConfigLoader;
+import me.filoghost.chestcommands.config.ConfigManager;
+import me.filoghost.chestcommands.config.framework.Config;
+import me.filoghost.chestcommands.config.framework.ConfigLoader;
+import me.filoghost.chestcommands.config.framework.exception.ConfigLoadException;
+import me.filoghost.chestcommands.config.framework.exception.ConfigSaveException;
import me.filoghost.chestcommands.legacy.Upgrade;
-import me.filoghost.chestcommands.legacy.UpgradeException;
-import java.io.IOException;
import java.nio.file.Path;
public class SettingsUpgrade extends Upgrade {
@@ -27,23 +28,23 @@ public class SettingsUpgrade extends Upgrade {
private final ConfigLoader settingsConfigLoader;
private Config updatedConfig;
- public SettingsUpgrade(ConfigLoader settingsConfigLoader) {
- this.settingsConfigLoader = settingsConfigLoader;
+ public SettingsUpgrade(ConfigManager configManager) {
+ this.settingsConfigLoader = configManager.getConfigLoader("config.yml");
}
@Override
public Path getOriginalFile() {
- return settingsConfigLoader.getPath();
+ return settingsConfigLoader.getConfigPath();
}
@Override
public Path getUpgradedFile() {
- return settingsConfigLoader.getPath();
+ return settingsConfigLoader.getConfigPath();
}
@Override
- protected void computeChanges() throws UpgradeException {
- Config settingsConfig = loadConfig(settingsConfigLoader);
+ protected void computeChanges() throws ConfigLoadException {
+ Config settingsConfig = settingsConfigLoader.load();
removeNode(settingsConfig, "use-only-commands-without-args");
removeNode(settingsConfig, "use-console-colors");
@@ -61,7 +62,7 @@ public class SettingsUpgrade extends Upgrade {
@Override
- protected void saveChanges() throws IOException {
+ protected void saveChanges() throws ConfigSaveException {
settingsConfigLoader.save(updatedConfig);
}
}
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/parsing/ErrorFormat.java b/Plugin/src/main/java/me/filoghost/chestcommands/parsing/ErrorFormat.java
index ccdfac8..7e3c86c 100644
--- a/Plugin/src/main/java/me/filoghost/chestcommands/parsing/ErrorFormat.java
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/parsing/ErrorFormat.java
@@ -1,19 +1,20 @@
package me.filoghost.chestcommands.parsing;
+import me.filoghost.chestcommands.config.framework.Config;
import me.filoghost.chestcommands.parsing.icon.IconSettings;
public class ErrorFormat {
- public static String invalidMenuSetting(String menuName, String invalidSetting, String errorMessage) {
- return menuError(menuName, "has an invalid menu setting \"" + invalidSetting + "\": " + errorMessage);
+ public static String invalidMenuSetting(Config menuConfig, String invalidSetting, String errorMessage) {
+ return menuError(menuConfig, "has an invalid menu setting \"" + invalidSetting + "\": " + errorMessage);
}
- public static String missingMenuSetting(String menuName, String missingSetting) {
- return menuError(menuName, "is missing the menu setting \"" + missingSetting + "\"");
+ public static String missingMenuSetting(Config menuConfig, String missingSetting) {
+ return menuError(menuConfig, "is missing the menu setting \"" + missingSetting + "\"");
}
- private static String menuError(String menuName, String errorMessage) {
- return "The menu \"" + menuName + "\" " + errorMessage + ".";
+ private static String menuError(Config menuConfig, String errorMessage) {
+ return "The menu \"" + menuConfig.getSourceFileName() + "\" " + errorMessage + ".";
}
public static String invalidAttribute(IconSettings iconSettings, String attributeName, String errorMessage) {
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/parsing/icon/IconSettings.java b/Plugin/src/main/java/me/filoghost/chestcommands/parsing/icon/IconSettings.java
index de7ef59..2d41e82 100644
--- a/Plugin/src/main/java/me/filoghost/chestcommands/parsing/icon/IconSettings.java
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/parsing/icon/IconSettings.java
@@ -14,8 +14,8 @@
*/
package me.filoghost.chestcommands.parsing.icon;
-import me.filoghost.chestcommands.config.ConfigSection;
-import me.filoghost.chestcommands.config.ConfigValueException;
+import me.filoghost.chestcommands.config.framework.ConfigSection;
+import me.filoghost.chestcommands.config.framework.exception.ConfigValueException;
import me.filoghost.chestcommands.icon.InternalConfigurableIcon;
import me.filoghost.chestcommands.parsing.ParseException;
import me.filoghost.chestcommands.parsing.icon.attributes.ActionsAttribute;
diff --git a/Plugin/src/main/java/me/filoghost/chestcommands/parsing/menu/MenuParser.java b/Plugin/src/main/java/me/filoghost/chestcommands/parsing/menu/MenuParser.java
index c868437..7a25b4b 100644
--- a/Plugin/src/main/java/me/filoghost/chestcommands/parsing/menu/MenuParser.java
+++ b/Plugin/src/main/java/me/filoghost/chestcommands/parsing/menu/MenuParser.java
@@ -15,11 +15,11 @@
package me.filoghost.chestcommands.parsing.menu;
import me.filoghost.chestcommands.action.Action;
-import me.filoghost.chestcommands.config.Config;
-import me.filoghost.chestcommands.config.ConfigSection;
-import me.filoghost.chestcommands.config.ConfigValueException;
-import me.filoghost.chestcommands.menu.InternalIconMenu;
+import me.filoghost.chestcommands.config.framework.Config;
+import me.filoghost.chestcommands.config.framework.ConfigSection;
+import me.filoghost.chestcommands.config.framework.exception.ConfigValueException;
import me.filoghost.chestcommands.icon.InternalConfigurableIcon;
+import me.filoghost.chestcommands.menu.InternalIconMenu;
import me.filoghost.chestcommands.parsing.ActionParser;
import me.filoghost.chestcommands.parsing.ErrorFormat;
import me.filoghost.chestcommands.parsing.ItemStackParser;
@@ -41,7 +41,7 @@ public class MenuParser {
MenuSettings menuSettings = loadMenuSettings(menuConfig, errorCollector);
List iconSettingsList = loadIconSettingsList(menuConfig, errorCollector);
- InternalIconMenu iconMenu = new InternalIconMenu(menuSettings.getTitle(), menuSettings.getRows(), menuConfig.getFileName());
+ InternalIconMenu iconMenu = new InternalIconMenu(menuSettings.getTitle(), menuSettings.getRows(), menuConfig.getSourceFileName());
for (IconSettings iconSettings : iconSettingsList) {
try {
@@ -54,7 +54,7 @@ public class MenuParser {
iconMenu.setRefreshTicks(menuSettings.getRefreshTicks());
iconMenu.setOpenActions(menuSettings.getOpenActions());
- return new LoadedMenu(iconMenu, menuConfig.getFileName(), menuSettings.getCommands(), menuSettings.getOpenTrigger());
+ return new LoadedMenu(iconMenu, menuConfig.getSourceFileName(), menuSettings.getCommands(), menuSettings.getOpenTrigger());
}
@@ -105,7 +105,7 @@ public class MenuParser {
}
} catch (ConfigValueException e) {
title = ChatColor.DARK_RED + "No name set";
- errorCollector.addError(ErrorFormat.missingMenuSetting(config.getFileName(), MenuSettingsNode.NAME));
+ errorCollector.addError(ErrorFormat.missingMenuSetting(config, MenuSettingsNode.NAME));
}
int rows;
@@ -116,7 +116,7 @@ public class MenuParser {
}
} catch (ConfigValueException e) {
rows = 6; // Defaults to 6 rows
- errorCollector.addError(ErrorFormat.missingMenuSetting(config.getFileName(), MenuSettingsNode.ROWS));
+ errorCollector.addError(ErrorFormat.missingMenuSetting(config, MenuSettingsNode.ROWS));
}
MenuSettings menuSettings = new MenuSettings(title, rows);
@@ -157,7 +157,7 @@ public class MenuParser {
menuSettings.setOpenTrigger(openTrigger);
} catch (ParseException e) {
- errorCollector.addError(ErrorFormat.invalidMenuSetting(config.getFileName(), MenuSettingsNode.OPEN_ITEM_MATERIAL, e.getMessage()));
+ errorCollector.addError(ErrorFormat.invalidMenuSetting(config, MenuSettingsNode.OPEN_ITEM_MATERIAL, e.getMessage()));
}
}
}
@@ -183,7 +183,7 @@ public class MenuParser {
}
ConfigSection iconSection = config.getConfigSection(iconSectionName);
- IconSettings iconSettings = new IconSettings(config.getFileName(), iconSectionName);
+ IconSettings iconSettings = new IconSettings(config.getSourceFileName(), iconSectionName);
iconSettings.loadFrom(iconSection, errorCollector);
iconSettingsList.add(iconSettings);
}
diff --git a/Utils/src/main/java/me/filoghost/chestcommands/util/Preconditions.java b/Utils/src/main/java/me/filoghost/chestcommands/util/Preconditions.java
index 473c164..ead530c 100644
--- a/Utils/src/main/java/me/filoghost/chestcommands/util/Preconditions.java
+++ b/Utils/src/main/java/me/filoghost/chestcommands/util/Preconditions.java
@@ -14,10 +14,10 @@
*/
package me.filoghost.chestcommands.util;
-import java.util.Collection;
-
import org.bukkit.Material;
+import java.util.Collection;
+
public final class Preconditions {
private Preconditions() {}