mirror of
https://github.com/Multiverse/Multiverse-Core.git
synced 2025-01-10 18:28:28 +01:00
refactor: Abstract handle class and improve node handling
This commit is contained in:
parent
9bbf42f993
commit
90a3388728
@ -2,6 +2,7 @@ package com.onarandombox.MultiverseCore.api;
|
||||
|
||||
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
|
||||
import com.onarandombox.MultiverseCore.placeholders.MultiverseCorePlaceholders;
|
||||
import io.vavr.control.Try;
|
||||
import org.jvnet.hk2.annotations.Contract;
|
||||
|
||||
@Contract
|
||||
@ -37,7 +38,7 @@ public interface MVConfig {
|
||||
* @param name The name of the property.
|
||||
* @return The value of the property.
|
||||
*/
|
||||
Object getProperty(String name);
|
||||
Try<Object> getProperty(String name);
|
||||
|
||||
/**
|
||||
* Sets a property in the config.
|
||||
@ -46,7 +47,7 @@ public interface MVConfig {
|
||||
* @param value The value of the property.
|
||||
* @return True if the property was set successfully.
|
||||
*/
|
||||
boolean setProperty(String name, Object value);
|
||||
Try<Boolean> setProperty(String name, Object value);
|
||||
|
||||
/**
|
||||
* Sets world access permissions should be enforced.
|
||||
|
@ -14,6 +14,7 @@ import com.onarandombox.MultiverseCore.commandtools.MVCommandManager;
|
||||
import com.onarandombox.MultiverseCore.commandtools.MultiverseCommand;
|
||||
import com.onarandombox.MultiverseCore.commandtools.context.MVConfigValue;
|
||||
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
|
||||
import io.vavr.control.Try;
|
||||
import jakarta.inject.Inject;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
@ -55,20 +56,21 @@ public class ConfigCommand extends MultiverseCommand {
|
||||
}
|
||||
|
||||
private void showConfigValue(BukkitCommandIssuer issuer, String name) {
|
||||
Object currentValue = config.getProperty(name);
|
||||
if (currentValue == null) {
|
||||
issuer.sendMessage("No such config option: " + name);
|
||||
return;
|
||||
}
|
||||
issuer.sendMessage(name + "is currently set to " + config.getProperty(name));
|
||||
config.getProperty(name)
|
||||
.onSuccess(value -> issuer.sendMessage(name + "is currently set to " + value))
|
||||
.onFailure(throwable -> issuer.sendMessage("Unable to get " + name + ": " + throwable.getMessage()));
|
||||
}
|
||||
|
||||
private void updateConfigValue(BukkitCommandIssuer issuer, String name, Object value) {
|
||||
if (!config.setProperty(name, value)) {
|
||||
issuer.sendMessage("Unable to set " + name + " to " + value);
|
||||
return;
|
||||
}
|
||||
config.setProperty(name, value)
|
||||
.onSuccess(success -> {
|
||||
if (success) {
|
||||
config.save();
|
||||
issuer.sendMessage("Successfully set " + name + " to " + value);
|
||||
} else {
|
||||
issuer.sendMessage("Unable to set " + name + " to " + value);
|
||||
}
|
||||
})
|
||||
.onFailure(throwable -> issuer.sendMessage("Unable to set " + name + " to " + value + ": " + throwable.getMessage()));
|
||||
}
|
||||
}
|
||||
|
@ -15,14 +15,14 @@ import com.onarandombox.MultiverseCore.api.MVWorldManager;
|
||||
import com.onarandombox.MultiverseCore.commandtools.context.GameRuleValue;
|
||||
import com.onarandombox.MultiverseCore.commandtools.context.MVConfigValue;
|
||||
import com.onarandombox.MultiverseCore.config.MVCoreConfig;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.Node;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.ValueNode;
|
||||
import com.onarandombox.MultiverseCore.destination.DestinationsProvider;
|
||||
import com.onarandombox.MultiverseCore.destination.ParsedDestination;
|
||||
import com.onarandombox.MultiverseCore.display.filters.ContentFilter;
|
||||
import com.onarandombox.MultiverseCore.display.filters.DefaultContentFilter;
|
||||
import com.onarandombox.MultiverseCore.display.filters.RegexContentFilter;
|
||||
import com.onarandombox.MultiverseCore.utils.PlayerFinder;
|
||||
import io.github.townyadvanced.commentedconfiguration.setting.CommentedNode;
|
||||
import io.github.townyadvanced.commentedconfiguration.setting.TypedValueNode;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.GameRule;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -123,7 +123,7 @@ public class MVCommandContexts extends PaperCommandContexts {
|
||||
if (Strings.isNullOrEmpty(configName)) {
|
||||
throw new InvalidCommandArgument("No config name specified.");
|
||||
}
|
||||
Optional<CommentedNode> node = config.getNodes().findNode(configName);
|
||||
Optional<Node> node = config.getNodes().findNode(configName);
|
||||
if (node.isEmpty()) {
|
||||
throw new InvalidCommandArgument("The config " + configName + " is not valid.");
|
||||
}
|
||||
@ -133,12 +133,12 @@ public class MVCommandContexts extends PaperCommandContexts {
|
||||
throw new InvalidCommandArgument("No config value specified.");
|
||||
}
|
||||
|
||||
if (!(node.get() instanceof TypedValueNode)) {
|
||||
if (!(node.get() instanceof ValueNode)) {
|
||||
context.popFirstArg();
|
||||
return new MVConfigValue(valueString);
|
||||
}
|
||||
|
||||
ContextResolver<?, BukkitCommandExecutionContext> resolver = getResolver(((TypedValueNode<?>) node.get()).getType());
|
||||
ContextResolver<?, BukkitCommandExecutionContext> resolver = getResolver(((ValueNode<?>) node.get()).getType());
|
||||
if (resolver == null) {
|
||||
context.popFirstArg();
|
||||
return new MVConfigValue(valueString);
|
||||
|
@ -7,7 +7,7 @@ import java.nio.file.Path;
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.MultiverseCore;
|
||||
import com.onarandombox.MultiverseCore.api.MVConfig;
|
||||
import com.onarandombox.MultiverseCore.configuration.ConfigHandle;
|
||||
import com.onarandombox.MultiverseCore.configuration.handle.CommentedYamlConfigHandle;
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.BooleanMigratorAction;
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.ConfigMigrator;
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.IntegerMigratorAction;
|
||||
@ -15,6 +15,7 @@ import com.onarandombox.MultiverseCore.configuration.migration.InvertBoolMigrato
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.MoveMigratorAction;
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.VersionMigrator;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
|
||||
import io.vavr.control.Try;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -27,15 +28,14 @@ public class MVCoreConfig implements MVConfig {
|
||||
|
||||
private final Path configPath;
|
||||
private final MVCoreConfigNodes configNodes;
|
||||
private final ConfigHandle configHandle;
|
||||
private final CommentedYamlConfigHandle configHandle;
|
||||
|
||||
@Inject
|
||||
MVCoreConfig(@NotNull MultiverseCore core, @NotNull PluginManager pluginManager) {
|
||||
this.configPath = Path.of(core.getDataFolder().getPath(), CONFIG_FILENAME);
|
||||
this.configNodes = new MVCoreConfigNodes(pluginManager);
|
||||
this.configHandle = ConfigHandle.builder(configPath)
|
||||
this.configHandle = CommentedYamlConfigHandle.builder(configPath, configNodes.getNodes())
|
||||
.logger(Logging.getLogger())
|
||||
.nodes(configNodes.getNodes())
|
||||
.migrator(ConfigMigrator.builder(configNodes.VERSION)
|
||||
.addVersionMigrator(VersionMigrator.builder(5.0)
|
||||
.addAction(MoveMigratorAction.of("multiverse-configuration.enforceaccess", "world.enforce-access"))
|
||||
@ -110,12 +110,12 @@ public class MVCoreConfig implements MVConfig {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getProperty(String name) {
|
||||
public Try<Object> getProperty(String name) {
|
||||
return configHandle.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setProperty(String name, Object value) {
|
||||
public Try<Boolean> setProperty(String name, Object value) {
|
||||
return configHandle.set(name, value);
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,13 @@
|
||||
package com.onarandombox.MultiverseCore.config;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.MVCommentedNode;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.MVValueNode;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.ConfigHeaderNode;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.ConfigNode;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.Node;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
|
||||
import com.onarandombox.MultiverseCore.event.MVDebugModeEvent;
|
||||
import io.github.townyadvanced.commentedconfiguration.setting.CommentedNode;
|
||||
import jakarta.inject.Inject;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.jvnet.hk2.annotations.Service;
|
||||
|
||||
class MVCoreConfigNodes {
|
||||
|
||||
@ -23,12 +22,12 @@ class MVCoreConfigNodes {
|
||||
return nodes;
|
||||
}
|
||||
|
||||
private <N extends CommentedNode> N node(N node) {
|
||||
private <N extends Node> N node(N node) {
|
||||
nodes.add(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
private final MVCommentedNode HEADER = node(MVCommentedNode.builder("world") // TODO hacky way to get the header to the top of the file
|
||||
private final ConfigHeaderNode HEADER = node(ConfigHeaderNode.builder("world") // TODO hacky way to get the header to the top of the file
|
||||
.comment("####################################################################################################")
|
||||
.comment("# #")
|
||||
.comment("# █▀▄▀█ █░█ █░░ ▀█▀ █ █░█ █▀▀ █▀█ █▀ █▀▀ █▀▀ █▀█ █▀█ █▀▀ #")
|
||||
@ -52,12 +51,12 @@ class MVCoreConfigNodes {
|
||||
.comment("")
|
||||
.build());
|
||||
|
||||
// private final MVCommentedNode WORLD_HEADER = node(MVCommentedNode.builder("world")
|
||||
// private final ConfigHeaderNode WORLD_HEADER = node(ConfigHeaderNode.builder("world")
|
||||
// .comment("")
|
||||
// .comment("")
|
||||
// .build());
|
||||
|
||||
public final MVValueNode<Boolean> ENFORCE_ACCESS = node(MVValueNode.builder("world.enforce-access", Boolean.class)
|
||||
public final ConfigNode<Boolean> ENFORCE_ACCESS = node(ConfigNode.builder("world.enforce-access", Boolean.class)
|
||||
.comment("This setting will prevent players from entering worlds they don't have access to.")
|
||||
.comment("If this is set to false, players will be able to enter any world they want.")
|
||||
.comment("If this is set to true, players will only be able to enter worlds they have")
|
||||
@ -66,7 +65,7 @@ class MVCoreConfigNodes {
|
||||
.name("enforce-access")
|
||||
.build());
|
||||
|
||||
public final MVValueNode<Boolean> ENFORCE_GAMEMODE = node(MVValueNode.builder("world.enforce-gamemode", Boolean.class)
|
||||
public final ConfigNode<Boolean> ENFORCE_GAMEMODE = node(ConfigNode.builder("world.enforce-gamemode", Boolean.class)
|
||||
.comment("")
|
||||
.comment("Sets whether Multiverse will should enforce gamemode on world change.")
|
||||
.comment("If enabled, players will be forced into the gamemode of the world they are entering, unless they have")
|
||||
@ -75,14 +74,14 @@ class MVCoreConfigNodes {
|
||||
.name("enforce-gamemode")
|
||||
.build());
|
||||
|
||||
public final MVValueNode<Boolean> AUTO_PURGE_ENTITIES = node(MVValueNode.builder("world.auto-purge-entities", Boolean.class)
|
||||
public final ConfigNode<Boolean> AUTO_PURGE_ENTITIES = node(ConfigNode.builder("world.auto-purge-entities", Boolean.class)
|
||||
.comment("")
|
||||
.comment("Sets whether Multiverse will purge mobs and entities with be automatically.")
|
||||
.defaultValue(false)
|
||||
.name("auto-purge-entities")
|
||||
.build());
|
||||
|
||||
public final MVValueNode<Boolean> TELEPORT_INTERCEPT = node(MVValueNode.builder("world.teleport-intercept", Boolean.class)
|
||||
public final ConfigNode<Boolean> TELEPORT_INTERCEPT = node(ConfigNode.builder("world.teleport-intercept", Boolean.class)
|
||||
.comment("")
|
||||
.comment("If this is set to true, Multiverse will enforce access permissions for all teleportation,")
|
||||
.comment("including teleportation from other plugins.")
|
||||
@ -90,12 +89,12 @@ class MVCoreConfigNodes {
|
||||
.name("teleport-intercept")
|
||||
.build());
|
||||
|
||||
private final MVCommentedNode SPAWN_HEADER = node(MVCommentedNode.builder("spawn")
|
||||
private final ConfigHeaderNode SPAWN_HEADER = node(ConfigHeaderNode.builder("spawn")
|
||||
.comment("")
|
||||
.comment("")
|
||||
.build());
|
||||
|
||||
public final MVValueNode<Boolean> FIRST_SPAWN_OVERRIDE = node(MVValueNode.builder("spawn.first-spawn-override", Boolean.class)
|
||||
public final ConfigNode<Boolean> FIRST_SPAWN_OVERRIDE = node(ConfigNode.builder("spawn.first-spawn-override", Boolean.class)
|
||||
.comment("Sets whether Multiverse will override the first spawn location of a world.")
|
||||
.comment("If enabled, Multiverse will set the first spawn location of a world to the spawn location of the world.")
|
||||
.comment("If disabled, it will default to server.properties settings.")
|
||||
@ -103,7 +102,7 @@ class MVCoreConfigNodes {
|
||||
.name("first-spawn-override")
|
||||
.build());
|
||||
|
||||
public final MVValueNode<String> FIRST_SPAWN_LOCATION = node(MVValueNode.builder("spawn.first-spawn-location", String.class)
|
||||
public final ConfigNode<String> FIRST_SPAWN_LOCATION = node(ConfigNode.builder("spawn.first-spawn-location", String.class)
|
||||
.comment("")
|
||||
.comment("Sets the world that Multiverse will use as the location for players that first join the server.")
|
||||
.comment("This only applies if first-spawn-override is set to true.")
|
||||
@ -111,19 +110,19 @@ class MVCoreConfigNodes {
|
||||
.name("first-spawn-location")
|
||||
.build());
|
||||
|
||||
private final MVCommentedNode PORTAL_HEADER = node(MVCommentedNode.builder("portal")
|
||||
private final ConfigHeaderNode PORTAL_HEADER = node(ConfigHeaderNode.builder("portal")
|
||||
.comment("")
|
||||
.comment("")
|
||||
.build());
|
||||
|
||||
public final MVValueNode<Boolean> USE_CUSTOM_PORTAL_SEARCH = node(MVValueNode.builder("portal.use-custom-portal-search", Boolean.class)
|
||||
public final ConfigNode<Boolean> USE_CUSTOM_PORTAL_SEARCH = node(ConfigNode.builder("portal.use-custom-portal-search", Boolean.class)
|
||||
.comment("This config option defines whether or not Multiverse should interfere with's Bukkit's default portal search radius.")
|
||||
.comment("Setting it to false would mean you want to simply let Bukkit decides the search radius itself.")
|
||||
.defaultValue(false)
|
||||
.name("use-custom-portal-search")
|
||||
.build());
|
||||
|
||||
public final MVValueNode<Integer> CUSTOM_PORTAL_SEARCH_RADIUS = node(MVValueNode.builder("portal.custom-portal-search-radius", Integer.class)
|
||||
public final ConfigNode<Integer> CUSTOM_PORTAL_SEARCH_RADIUS = node(ConfigNode.builder("portal.custom-portal-search-radius", Integer.class)
|
||||
.comment("")
|
||||
.comment("This config option defines the search radius Multiverse should use when searching for a portal.")
|
||||
.comment("This only applies if use-custom-portal-search is set to true.")
|
||||
@ -132,19 +131,19 @@ class MVCoreConfigNodes {
|
||||
.validator(value -> value >= 0)
|
||||
.build());
|
||||
|
||||
private final MVCommentedNode MESSAGING_HEADER = node(MVCommentedNode.builder("messaging")
|
||||
private final ConfigHeaderNode MESSAGING_HEADER = node(ConfigHeaderNode.builder("messaging")
|
||||
.comment("")
|
||||
.comment("")
|
||||
.build());
|
||||
|
||||
public final MVValueNode<Boolean> ENABLE_CHAT_PREFIX = node(MVValueNode.builder("messaging.enable-chat-prefix", Boolean.class)
|
||||
public final ConfigNode<Boolean> ENABLE_CHAT_PREFIX = node(ConfigNode.builder("messaging.enable-chat-prefix", Boolean.class)
|
||||
.comment("This config option defines whether or not Multiverse should prefix the chat with the world name.")
|
||||
.comment("This only applies if use-custom-portal-search is set to true.")
|
||||
.defaultValue(false)
|
||||
.name("enable-chat-prefix")
|
||||
.build());
|
||||
|
||||
public final MVValueNode<String> CHAT_PREFIX_FORMAT = node(MVValueNode.builder("messaging.chat-prefix-format", String.class)
|
||||
public final ConfigNode<String> CHAT_PREFIX_FORMAT = node(ConfigNode.builder("messaging.chat-prefix-format", String.class)
|
||||
.comment("")
|
||||
.comment("This config option defines the format Multiverse should use when prefixing the chat with the world name.")
|
||||
.comment("This only applies if enable-chat-prefix is set to true.")
|
||||
@ -152,7 +151,7 @@ class MVCoreConfigNodes {
|
||||
.name("chat-prefix-format")
|
||||
.build());
|
||||
|
||||
public final MVValueNode<Boolean> REGISTER_PAPI_HOOK = node(MVValueNode.builder("messaging.register-papi-hook", Boolean.class)
|
||||
public final ConfigNode<Boolean> REGISTER_PAPI_HOOK = node(ConfigNode.builder("messaging.register-papi-hook", Boolean.class)
|
||||
.comment("")
|
||||
.comment("This config option defines whether or not Multiverse should register the PlaceholderAPI hook.")
|
||||
.comment("This only applies if PlaceholderAPI is installed.")
|
||||
@ -160,12 +159,12 @@ class MVCoreConfigNodes {
|
||||
.name("register-papi-hook")
|
||||
.build());
|
||||
|
||||
private final MVCommentedNode MISC_HEADER = node(MVCommentedNode.builder("misc")
|
||||
private final ConfigHeaderNode MISC_HEADER = node(ConfigHeaderNode.builder("misc")
|
||||
.comment("")
|
||||
.comment("")
|
||||
.build());
|
||||
|
||||
public final MVValueNode<Integer> GLOBAL_DEBUG = node(MVValueNode.builder("misc.global-debug", Integer.class)
|
||||
public final ConfigNode<Integer> GLOBAL_DEBUG = node(ConfigNode.builder("misc.global-debug", Integer.class)
|
||||
.comment("This is our debug flag to help identify issues with Multiverse.")
|
||||
.comment("If you are having issues with Multiverse, please set this to 3 and then post your log to pastebin.com")
|
||||
.comment("Otherwise, there's no need to touch this. If not instructed by a wiki page or developer.")
|
||||
@ -185,7 +184,7 @@ class MVCoreConfigNodes {
|
||||
})
|
||||
.build());
|
||||
|
||||
public final MVValueNode<Boolean> SILENT_START = node(MVValueNode.builder("misc.silent-start", Boolean.class)
|
||||
public final ConfigNode<Boolean> SILENT_START = node(ConfigNode.builder("misc.silent-start", Boolean.class)
|
||||
.comment("")
|
||||
.comment("If true, the startup console messages will no longer show.")
|
||||
.defaultValue(false)
|
||||
@ -193,14 +192,14 @@ class MVCoreConfigNodes {
|
||||
.onSetValue((oldValue, newValue) -> Logging.setShowingConfig(!newValue))
|
||||
.build());
|
||||
|
||||
public final MVValueNode<Boolean> SHOW_DONATION_MESSAGE = node(MVValueNode.builder("misc.show-donation-message", Boolean.class)
|
||||
public final ConfigNode<Boolean> SHOW_DONATION_MESSAGE = node(ConfigNode.builder("misc.show-donation-message", Boolean.class)
|
||||
.comment("")
|
||||
.comment("If you don't want to donate, you can set this to false and Multiverse will stop nagging you.")
|
||||
.defaultValue(true)
|
||||
.name("show-donation-message")
|
||||
.build());
|
||||
|
||||
public final MVValueNode<Double> VERSION = node(MVValueNode.builder("version", Double.class)
|
||||
public final ConfigNode<Double> VERSION = node(ConfigNode.builder("version", Double.class)
|
||||
.comment("")
|
||||
.comment("")
|
||||
.comment("This just signifies the version number so we can see what version of config you have.")
|
||||
|
@ -1,360 +0,0 @@
|
||||
package com.onarandombox.MultiverseCore.configuration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.ConfigMigrator;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.EnhancedValueNode;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
|
||||
import io.github.townyadvanced.commentedconfiguration.CommentedConfiguration;
|
||||
import io.github.townyadvanced.commentedconfiguration.setting.CommentedNode;
|
||||
import io.github.townyadvanced.commentedconfiguration.setting.TypedValueNode;
|
||||
import io.github.townyadvanced.commentedconfiguration.setting.ValueNode;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* A class that makes use of CommentedConfiguration to provide a simple way to load and save with node objects.
|
||||
*/
|
||||
public class ConfigHandle {
|
||||
|
||||
/**
|
||||
* A builder class for creating a ConfigHandle.
|
||||
*
|
||||
* @param configPath The path to the configuration file in string.
|
||||
* @return A new Builder instance.
|
||||
*/
|
||||
public static Builder builder(String configPath) {
|
||||
return new Builder(configPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder class for creating a ConfigHandle.
|
||||
*
|
||||
* @param configPath The path to the configuration file.
|
||||
* @return A new Builder instance.
|
||||
*/
|
||||
public static Builder builder(Path configPath) {
|
||||
return new Builder(configPath);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected final Path configPath;
|
||||
@Nullable
|
||||
protected final Logger logger;
|
||||
@NotNull
|
||||
protected final NodeGroup nodes;
|
||||
|
||||
protected final ConfigMigrator migrator;
|
||||
|
||||
protected CommentedConfiguration config;
|
||||
|
||||
/**
|
||||
* Creates a new MVSettings instance that makes use of CommentedConfiguration.
|
||||
*
|
||||
* @param configPath The path to the configuration file.
|
||||
* @param logger The Logger to use for error messages.
|
||||
* @param nodes All the node path and values for the configuration.
|
||||
* @param migrator The migrator to use for migrating the configuration.
|
||||
*/
|
||||
protected ConfigHandle(@NotNull Path configPath, @Nullable Logger logger, @NotNull NodeGroup nodes, ConfigMigrator migrator) {
|
||||
this.configPath = configPath;
|
||||
this.nodes = nodes;
|
||||
this.logger = logger;
|
||||
this.migrator = migrator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the configuration.
|
||||
*
|
||||
* @return True if the configuration was loaded successfully, false otherwise.
|
||||
*/
|
||||
public boolean load() {
|
||||
if (!createConfigFile()) {
|
||||
return false;
|
||||
}
|
||||
this.config = new CommentedConfiguration(configPath, logger);
|
||||
if (!config.load()) {
|
||||
return false;
|
||||
}
|
||||
migrateConfig();
|
||||
parseAllNodes();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new config file if file does not exist
|
||||
*
|
||||
* @return True if file exist or created successfully, otherwise false.
|
||||
*/
|
||||
protected boolean createConfigFile() {
|
||||
File configFile = configPath.toFile();
|
||||
if (configFile.exists()) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
if (!configFile.createNewFile()) {
|
||||
return false;
|
||||
}
|
||||
Logging.info("Created new config file: %s", configFile.getName());
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Migration of the configuration based on {@link ConfigMigrator}.
|
||||
*/
|
||||
protected void migrateConfig() {
|
||||
migrator.migrate(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds default node values to the configuration if they are not already present.
|
||||
*/
|
||||
protected void parseAllNodes() {
|
||||
CommentedConfiguration oldConfig = config;
|
||||
this.config = new CommentedConfiguration(configPath, logger);
|
||||
for (CommentedNode node : nodes) {
|
||||
if (node.getComments().length > 0) {
|
||||
config.addComment(node.getPath(), node.getComments());
|
||||
}
|
||||
if (node instanceof TypedValueNode typedNode) {
|
||||
if (!set(typedNode, oldConfig.getObject(node.getPath(), typedNode.getType(), typedNode.getDefaultValue()))) {
|
||||
Logging.warning("Invalid value for node: %s, resetting to default...", node.getPath());
|
||||
setDefault(typedNode);
|
||||
}
|
||||
} else if (node instanceof ValueNode valueNode) {
|
||||
if (!set(valueNode, oldConfig.get(node.getPath(), valueNode.getDefaultValue()))) {
|
||||
Logging.warning("Invalid value for node: %s, resetting to default...", node.getPath());
|
||||
setDefault(valueNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the configuration.
|
||||
*/
|
||||
public void save() {
|
||||
config.save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the configuration is loaded.
|
||||
*
|
||||
* @return True if the configuration is loaded, false otherwise.
|
||||
*/
|
||||
public boolean isLoaded() {
|
||||
return config != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of a node, if the node has a default value, it will be returned if the node is not found.
|
||||
*
|
||||
* @param node The node to get the value of.
|
||||
* @return The value of the node.
|
||||
*/
|
||||
public Object get(@NotNull ValueNode node) {
|
||||
return config.get(node.getPath(), node.getDefaultValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the node by name.
|
||||
*
|
||||
* @param name The name of the node to get the value of.
|
||||
* @return The value of the node.
|
||||
*/
|
||||
public Object get(@NotNull String name) {
|
||||
return nodes.findNode(name)
|
||||
.map(node -> (node instanceof ValueNode) ? get((ValueNode) node) : null)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of a node, if the node has a default value, it will be returned if the node is not found.
|
||||
*
|
||||
* @param node The node to get the value of.
|
||||
* @param type The type of the node value.
|
||||
* @param <T> The type of the node value.
|
||||
* @return The value of the node.
|
||||
*/
|
||||
public <T> T get(@NotNull ValueNode node, Class<T> type) {
|
||||
return config.getObject(node.getPath(), type, (T) node.getDefaultValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of a node, if the node has a default value, it will be returned if the node is not found.
|
||||
*
|
||||
* @param node The node to get the value of.
|
||||
* @param <T> The type of the node value.
|
||||
* @return The value of the node.
|
||||
*/
|
||||
public <T> T get(@NotNull TypedValueNode<T> node) {
|
||||
return config.getObject(node.getPath(), node.getType(), node.getDefaultValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of the node by name.
|
||||
*
|
||||
* @param name The name of the node to set the value of.
|
||||
* @param value The value to set.
|
||||
*/
|
||||
public boolean set(@NotNull String name, Object value) {
|
||||
return nodes.findNode(name)
|
||||
.map(node -> node instanceof ValueNode && set((ValueNode) node, value))
|
||||
.orElse(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of a node, if the validator is not null, it will be tested first.
|
||||
*
|
||||
* @param node The node to set the value of.
|
||||
* @param value The value to set.
|
||||
*/
|
||||
public boolean set(@NotNull ValueNode node, Object value) {
|
||||
if (node instanceof TypedValueNode typedValueNode) {
|
||||
return set(typedValueNode, value);
|
||||
}
|
||||
config.set(node.getPath(), value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of a node, if the validator is not null, it will be tested first.
|
||||
*
|
||||
* @param node The node to set the value of.
|
||||
* @param value The value to set.
|
||||
* @param <T> The type of the node value.
|
||||
*/
|
||||
public <T> boolean set(@NotNull TypedValueNode<T> node, T value) {
|
||||
if (node instanceof EnhancedValueNode<T> enhancedValueNode) {
|
||||
return set(enhancedValueNode, value);
|
||||
}
|
||||
config.set(node.getPath(), value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of a node, if the validator is not null, it will be tested first.
|
||||
*
|
||||
* @param node The node to set the value of.
|
||||
* @param value The value to set.
|
||||
* @return True if the value was set, false otherwise.
|
||||
* @param <T> The type of the node value.
|
||||
*/
|
||||
public <T> boolean set(@NotNull EnhancedValueNode<T> node, T value) {
|
||||
if (!node.isValid(value)) {
|
||||
return false;
|
||||
}
|
||||
T oldValue = get(node);
|
||||
config.set(node.getPath(), value);
|
||||
node.onSetValue(oldValue, get(node));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default value of a node.
|
||||
*
|
||||
* @param node The node to set the default value of.
|
||||
*/
|
||||
public void setDefault(@NotNull ValueNode node) {
|
||||
config.set(node.getPath(), node.getDefaultValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the inner configuration object.
|
||||
*
|
||||
* @return The configuration object.
|
||||
*/
|
||||
public @NotNull CommentedConfiguration getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the path of the configuration file.
|
||||
*/
|
||||
public static class Builder {
|
||||
|
||||
private final Path configPath;
|
||||
private Logger logger;
|
||||
private NodeGroup nodes;
|
||||
|
||||
private ConfigMigrator migrator;
|
||||
|
||||
/**
|
||||
* Creates a new builder.
|
||||
*
|
||||
* @param configPath The path of the configuration file.
|
||||
*/
|
||||
public Builder(String configPath) {
|
||||
this.configPath = Path.of(configPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new builder.
|
||||
*
|
||||
* @param configPath The path of the configuration file.
|
||||
*/
|
||||
public Builder(Path configPath) {
|
||||
this.configPath = configPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the logger to use.
|
||||
*
|
||||
* @param plugin The plugin to get the logger from.
|
||||
* @return The builder.
|
||||
*/
|
||||
public Builder logger(@NotNull Plugin plugin) {
|
||||
return logger(plugin.getLogger());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the logger to use.
|
||||
*
|
||||
* @param logger The logger to use.
|
||||
* @return The builder.
|
||||
*/
|
||||
public Builder logger(@Nullable Logger logger) {
|
||||
this.logger = logger;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the nodes to use.
|
||||
*
|
||||
* @param nodes The nodes to use.
|
||||
* @return The builder.
|
||||
*/
|
||||
public Builder nodes(@Nullable NodeGroup nodes) {
|
||||
this.nodes = nodes;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the migrator to use.
|
||||
*
|
||||
* @param migrator The migrator to use.
|
||||
* @return The builder.
|
||||
*/
|
||||
public Builder migrator(@Nullable ConfigMigrator migrator) {
|
||||
this.migrator = migrator;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the settings.
|
||||
*
|
||||
* @return The built settings.
|
||||
*/
|
||||
public ConfigHandle build() {
|
||||
return new ConfigHandle(configPath, logger, nodes, migrator);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package com.onarandombox.MultiverseCore.configuration.handle;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.ConfigMigrator;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.CommentedNode;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.ValueNode;
|
||||
import io.github.townyadvanced.commentedconfiguration.CommentedConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class CommentedYamlConfigHandle extends FileConfigHandle<CommentedConfiguration> {
|
||||
|
||||
public static @NotNull Builder builder(@NotNull Path configPath, @NotNull NodeGroup nodes) {
|
||||
return new Builder(configPath, nodes);
|
||||
}
|
||||
|
||||
protected CommentedYamlConfigHandle(@NotNull Path configPath, @Nullable Logger logger, @NotNull NodeGroup nodes, @Nullable ConfigMigrator migrator) {
|
||||
super(configPath, logger, nodes, migrator);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean loadConfigObject() {
|
||||
config = new CommentedConfiguration(configPath, logger);
|
||||
return config.load();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUpNodes() {
|
||||
CommentedConfiguration oldConfig = config;
|
||||
this.config = new CommentedConfiguration(configPath, logger);
|
||||
|
||||
nodes.forEach(node -> {
|
||||
if (node instanceof CommentedNode typedNode) {
|
||||
if (typedNode.getComments().length > 0) {
|
||||
config.addComment(typedNode.getPath(), typedNode.getComments());
|
||||
}
|
||||
}
|
||||
if (node instanceof ValueNode valueNode) {
|
||||
set(valueNode, oldConfig.getObject(valueNode.getPath(), valueNode.getType(), valueNode.getDefaultValue())).onFailure(e -> {
|
||||
Logging.warning("Failed to set node " + valueNode.getPath() + " to " + valueNode.getDefaultValue());
|
||||
setDefault(valueNode);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean save() {
|
||||
config.save();
|
||||
return true;
|
||||
}
|
||||
|
||||
public static class Builder extends FileConfigHandle.Builder<CommentedConfiguration, Builder> {
|
||||
|
||||
protected Builder(@NotNull Path configPath, @NotNull NodeGroup nodes) {
|
||||
super(configPath, nodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull CommentedYamlConfigHandle build() {
|
||||
return new CommentedYamlConfigHandle(configPath, logger, nodes, migrator);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,208 @@
|
||||
package com.onarandombox.MultiverseCore.configuration.handle;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.ConfigMigrator;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.ValueNode;
|
||||
import io.vavr.control.Try;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
abstract class FileConfigHandle<C extends FileConfiguration> {
|
||||
|
||||
protected final @NotNull Path configPath;
|
||||
protected final @NotNull File configFile;
|
||||
protected final @Nullable Logger logger;
|
||||
protected final @NotNull NodeGroup nodes;
|
||||
protected final @Nullable ConfigMigrator migrator;
|
||||
|
||||
protected C config;
|
||||
|
||||
protected FileConfigHandle(@NotNull Path configPath, @Nullable Logger logger, @NotNull NodeGroup nodes, @Nullable ConfigMigrator migrator) {
|
||||
this.configPath = configPath;
|
||||
this.configFile = configPath.toFile();
|
||||
this.logger = logger;
|
||||
this.nodes = nodes;
|
||||
this.migrator = migrator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the configuration.
|
||||
*
|
||||
* @return True if the configuration was loaded successfully, false otherwise.
|
||||
*/
|
||||
public boolean load() {
|
||||
if (!createConfigFile()) {
|
||||
Logging.severe("Failed to create config file: %s", configFile.getName());
|
||||
return false;
|
||||
}
|
||||
if (!loadConfigObject()) {
|
||||
Logging.severe("Failed to load config file: %s", configFile.getName());
|
||||
return false;
|
||||
}
|
||||
migrateConfig();
|
||||
setUpNodes();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new config file if file does not exist
|
||||
*
|
||||
* @return True if file exist or created successfully, otherwise false.
|
||||
*/
|
||||
protected boolean createConfigFile() {
|
||||
if (configFile.exists()) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
if (!configFile.createNewFile()) {
|
||||
return false;
|
||||
}
|
||||
Logging.info("Created new config file: %s", configFile.getName());
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected abstract boolean loadConfigObject();
|
||||
|
||||
protected void migrateConfig() {
|
||||
if (migrator != null) {
|
||||
migrator.migrate(config);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void setUpNodes();
|
||||
|
||||
/**
|
||||
* Saves the configuration.
|
||||
*/
|
||||
public abstract boolean save();
|
||||
|
||||
/**
|
||||
* Checks if the configuration is loaded.
|
||||
*
|
||||
* @return True if the configuration is loaded, false otherwise.
|
||||
*/
|
||||
public boolean isLoaded() {
|
||||
return config != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the configuration.
|
||||
*
|
||||
* @return The configuration.
|
||||
*/
|
||||
public C getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public Try<Object> get(@Nullable String name) {
|
||||
return nodes.findNode(name, ValueNode.class)
|
||||
.map(node -> Try.of(() -> get(node)))
|
||||
.orElse(Try.failure(new Exception("Node not found")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of a node, if the node has a default value, it will be returned if the node is not found.
|
||||
*
|
||||
* @param node The node to get the value of.
|
||||
* @return The value of the node.
|
||||
*/
|
||||
public <T> T get(@NotNull ValueNode<T> node) {
|
||||
return config.getObject(node.getPath(), node.getType(), node.getDefaultValue());
|
||||
}
|
||||
|
||||
public Try<Boolean> set(@Nullable String name, Object value) {
|
||||
return nodes.findNode(name, ValueNode.class)
|
||||
.map(node -> (Try<Boolean>) set(node, value))
|
||||
.orElse(Try.failure(new Exception("Node not found")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of a node, if the validator is not null, it will be tested first.
|
||||
*
|
||||
* @param node The node to set the value of.
|
||||
* @param value The value to set.
|
||||
* @return True if the value was set, false otherwise.
|
||||
* @param <T> The type of the node value.
|
||||
*/
|
||||
public <T> Try<Boolean> set(@NotNull ValueNode<T> node, T value) {
|
||||
if (!node.validate(value)) {
|
||||
return Try.failure(new Exception("Validation failed"));
|
||||
}
|
||||
T oldValue = get(node);
|
||||
config.set(node.getPath(), value);
|
||||
node.onSetValue(oldValue, get(node));
|
||||
return Try.success(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default value of a node.
|
||||
*
|
||||
* @param node The node to set the default value of.
|
||||
*/
|
||||
public void setDefault(@NotNull ValueNode node) {
|
||||
config.set(node.getPath(), node.getDefaultValue());
|
||||
}
|
||||
|
||||
public static abstract class Builder<C extends FileConfiguration, B extends Builder<C, B>> {
|
||||
|
||||
protected @NotNull Path configPath;
|
||||
protected @Nullable Logger logger;
|
||||
protected @NotNull NodeGroup nodes;
|
||||
protected @Nullable ConfigMigrator migrator;
|
||||
|
||||
protected Builder(@NotNull Path configPath, @NotNull NodeGroup nodes) {
|
||||
this.configPath = configPath;
|
||||
this.nodes = nodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the logger.
|
||||
*
|
||||
* @param logger The logger.
|
||||
* @return The builder.
|
||||
*/
|
||||
public B logger(@Nullable Logger logger) {
|
||||
this.logger = logger;
|
||||
return self();
|
||||
}
|
||||
|
||||
public B logger(Plugin plugin) {
|
||||
this.logger = plugin.getLogger();
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the migrator.
|
||||
*
|
||||
* @param migrator The migrator.
|
||||
* @return The builder.
|
||||
*/
|
||||
public B migrator(@Nullable ConfigMigrator migrator) {
|
||||
this.migrator = migrator;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the configuration handle.
|
||||
*
|
||||
* @return The configuration handle.
|
||||
*/
|
||||
public abstract @NotNull FileConfigHandle<C> build();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected B self() {
|
||||
return (B) this;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package com.onarandombox.MultiverseCore.configuration.handle;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.onarandombox.MultiverseCore.configuration.migration.ConfigMigrator;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.NodeGroup;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.ValueNode;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class YamlConfigHandle extends FileConfigHandle<YamlConfiguration> {
|
||||
|
||||
public static @NotNull Builder<? extends Builder> builder(@NotNull Path configPath, @NotNull NodeGroup nodes) {
|
||||
return new Builder<>(configPath, nodes);
|
||||
}
|
||||
|
||||
protected YamlConfigHandle(@NotNull Path configPath, @Nullable Logger logger, @NotNull NodeGroup nodes, @Nullable ConfigMigrator migrator) {
|
||||
super(configPath, logger, nodes, migrator);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean loadConfigObject() {
|
||||
config = new YamlConfiguration();
|
||||
try {
|
||||
config.load(configFile);
|
||||
} catch (IOException | InvalidConfigurationException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUpNodes() {
|
||||
YamlConfiguration oldConfig = config;
|
||||
config = new YamlConfiguration();
|
||||
nodes.forEach(node -> {
|
||||
if (node instanceof ValueNode valueNode) {
|
||||
set(valueNode, oldConfig.getObject(valueNode.getPath(), valueNode.getType(), valueNode.getDefaultValue()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean save() {
|
||||
try {
|
||||
config.save(configFile);
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static class Builder<B extends Builder<B>> extends FileConfigHandle.Builder<YamlConfiguration, B> {
|
||||
|
||||
protected Builder(@NotNull Path configPath, @NotNull NodeGroup nodes) {
|
||||
super(configPath, nodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull YamlConfigHandle build() {
|
||||
return new YamlConfigHandle(configPath, logger, nodes, migrator);
|
||||
}
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@ package com.onarandombox.MultiverseCore.configuration.migration;
|
||||
|
||||
import co.aikar.commands.ACFUtil;
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.configuration.ConfigHandle;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
/**
|
||||
* Single migrator action that converts a string value to a boolean.
|
||||
@ -20,9 +20,9 @@ public class BooleanMigratorAction implements MigratorAction {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(ConfigHandle settings) {
|
||||
settings.getConfig().set(path, ACFUtil.isTruthy(settings.getConfig().getString(path, "")));
|
||||
Logging.info("Converted %s to boolean %s", path, settings.getConfig().getBoolean(path));
|
||||
public void migrate(FileConfiguration config) {
|
||||
config.set(path, ACFUtil.isTruthy(config.getString(path, "")));
|
||||
Logging.info("Converted %s to boolean %s", path, config.getBoolean(path));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,8 +4,9 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.configuration.ConfigHandle;
|
||||
import com.onarandombox.MultiverseCore.configuration.node.ValueNode;
|
||||
import io.github.townyadvanced.commentedconfiguration.setting.TypedValueNode;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
/**
|
||||
* Helper class for migrating configs to the latest config version.
|
||||
@ -19,14 +20,14 @@ public class ConfigMigrator {
|
||||
* Default value should be the current latest version number.
|
||||
* @return The builder instance.
|
||||
*/
|
||||
public static Builder builder(TypedValueNode<Double> versionNode) {
|
||||
public static Builder builder(ValueNode<Double> versionNode) {
|
||||
return new Builder(versionNode);
|
||||
}
|
||||
|
||||
private final TypedValueNode<Double> versionNode;
|
||||
private final ValueNode<Double> versionNode;
|
||||
private final List<VersionMigrator> versionMigrators;
|
||||
|
||||
protected ConfigMigrator(TypedValueNode<Double> versionNode, List<VersionMigrator> versionMigrators) {
|
||||
protected ConfigMigrator(ValueNode<Double> versionNode, List<VersionMigrator> versionMigrators) {
|
||||
this.versionNode = versionNode;
|
||||
this.versionMigrators = versionMigrators;
|
||||
}
|
||||
@ -34,25 +35,25 @@ public class ConfigMigrator {
|
||||
/**
|
||||
* Migrates the config to the latest version if necessary.
|
||||
*
|
||||
* @param settings The target settings instance to migrate.
|
||||
* @param config The target settings instance to migrate.
|
||||
*/
|
||||
public void migrate(ConfigHandle settings) {
|
||||
double versionNumber = settings.getConfig().getDouble(versionNode.getPath());
|
||||
public void migrate(FileConfiguration config) {
|
||||
double versionNumber = config.getDouble(versionNode.getPath());
|
||||
for (VersionMigrator versionMigrator : versionMigrators) {
|
||||
if (versionNumber < versionMigrator.getVersion()) {
|
||||
Logging.info("Migrating config from version %s to %s...", versionNumber, versionMigrator.getVersion());
|
||||
versionMigrator.migrate(settings);
|
||||
versionMigrator.migrate(config);
|
||||
}
|
||||
}
|
||||
// Set the version number to the latest version number
|
||||
settings.setDefault(versionNode);
|
||||
config.set(versionNode.getPath(), versionNode.getDefaultValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder for a ConfigMigrator.
|
||||
*/
|
||||
public static class Builder {
|
||||
private final TypedValueNode<Double> versionNode;
|
||||
private final ValueNode<Double> versionNode;
|
||||
private final List<VersionMigrator> versionMigrators;
|
||||
|
||||
/**
|
||||
@ -61,7 +62,7 @@ public class ConfigMigrator {
|
||||
* @param versionNode The node that stores the version number of the config.
|
||||
* Default value should be the current latest version number.
|
||||
*/
|
||||
public Builder(TypedValueNode<Double> versionNode) {
|
||||
public Builder(ValueNode<Double> versionNode) {
|
||||
this.versionNode = versionNode;
|
||||
this.versionMigrators = new ArrayList<>();
|
||||
}
|
||||
|
@ -2,8 +2,7 @@ package com.onarandombox.MultiverseCore.configuration.migration;
|
||||
|
||||
import co.aikar.commands.ACFUtil;
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.configuration.ConfigHandle;
|
||||
import org.bukkit.util.NumberConversions;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
/**
|
||||
* Single migrator action that converts a string value to an integer.
|
||||
@ -21,8 +20,8 @@ public class IntegerMigratorAction implements MigratorAction {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(ConfigHandle settings) {
|
||||
settings.getConfig().set(path, ACFUtil.parseInt(settings.getConfig().getString(path)));
|
||||
Logging.info("Converted %s to integer %s", path, settings.getConfig().getInt(path));
|
||||
public void migrate(FileConfiguration config) {
|
||||
config.set(path, ACFUtil.parseInt(config.getString(path)));
|
||||
Logging.info("Converted %s to integer %s", path, config.getInt(path));
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.onarandombox.MultiverseCore.configuration.migration;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.configuration.ConfigHandle;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
/**
|
||||
* Single migrator action that inverts a boolean value for a given path.
|
||||
@ -28,9 +28,9 @@ public class InvertBoolMigratorAction implements MigratorAction {
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void migrate(ConfigHandle settings) {
|
||||
boolean boolValue = !settings.getConfig().getBoolean(path);
|
||||
settings.getConfig().set(path, boolValue);
|
||||
public void migrate(FileConfiguration config) {
|
||||
boolean boolValue = !config.getBoolean(path);
|
||||
config.set(path, boolValue);
|
||||
Logging.info("Inverted %s to boolean %s", path, boolValue);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package com.onarandombox.MultiverseCore.configuration.migration;
|
||||
|
||||
import com.onarandombox.MultiverseCore.configuration.ConfigHandle;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
/**
|
||||
* A migrator action is a single action that is performed when migrating a config.
|
||||
@ -10,7 +10,7 @@ public interface MigratorAction {
|
||||
/**
|
||||
* Performs the migration action.
|
||||
*
|
||||
* @param settings The target settings instance to migrate.
|
||||
* @param config The target settings instance to migrate.
|
||||
*/
|
||||
void migrate(ConfigHandle settings);
|
||||
void migrate(FileConfiguration config);
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package com.onarandombox.MultiverseCore.configuration.migration;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.dumptruckman.minecraft.util.Logging;
|
||||
import com.onarandombox.MultiverseCore.configuration.ConfigHandle;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
/**
|
||||
* Single migrator action that moves a value from one path to another.
|
||||
@ -33,11 +33,11 @@ public class MoveMigratorAction implements MigratorAction {
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void migrate(ConfigHandle settings) {
|
||||
Optional.ofNullable(settings.getConfig().get(fromPath))
|
||||
public void migrate(FileConfiguration config) {
|
||||
Optional.ofNullable(config.get(fromPath))
|
||||
.ifPresent(value -> {
|
||||
settings.getConfig().set(toPath, value);
|
||||
settings.getConfig().set(fromPath, null);
|
||||
config.set(toPath, value);
|
||||
config.set(fromPath, null);
|
||||
Logging.config("Moved path %s to %s", fromPath, toPath);
|
||||
});
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package com.onarandombox.MultiverseCore.configuration.migration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.onarandombox.MultiverseCore.configuration.ConfigHandle;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
/**
|
||||
* A version migrator is a collection of migrator actions that are performed when migrating a config to a specific version.
|
||||
@ -31,10 +31,10 @@ public class VersionMigrator {
|
||||
/**
|
||||
* Performs all the migrator actions.
|
||||
*
|
||||
* @param settings The target settings instance to migrate.
|
||||
* @param config The target settings instance to migrate.
|
||||
*/
|
||||
public void migrate(ConfigHandle settings) {
|
||||
actions.forEach(action -> action.migrate(settings));
|
||||
public void migrate(FileConfiguration config) {
|
||||
actions.forEach(action -> action.migrate(config));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,13 @@
|
||||
package com.onarandombox.MultiverseCore.configuration.node;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface CommentedNode extends Node {
|
||||
|
||||
/**
|
||||
* Gets the comment of the node.
|
||||
*
|
||||
* @return The comment of the node.
|
||||
*/
|
||||
@NotNull String[] getComments();
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
package com.onarandombox.MultiverseCore.configuration.node;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ConfigHeaderNode implements CommentedNode {
|
||||
|
||||
/**
|
||||
* Creates a new builder for a {@link ConfigHeaderNode}.
|
||||
*
|
||||
* @param path The path of the node.
|
||||
* @return The new builder.
|
||||
*/
|
||||
public static Builder<? extends Builder> builder(String path) {
|
||||
return new Builder<>(path);
|
||||
}
|
||||
|
||||
private final String path;
|
||||
private final String[] comments;
|
||||
|
||||
protected ConfigHeaderNode(String path, String[] comments) {
|
||||
this.path = path;
|
||||
this.comments = comments;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public @NotNull String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String[] getComments() {
|
||||
return comments;
|
||||
}
|
||||
|
||||
public static class Builder<B extends Builder<B>> {
|
||||
|
||||
protected final String path;
|
||||
protected final ArrayList<String> comments;
|
||||
|
||||
public Builder(String path) {
|
||||
this.path = path;
|
||||
this.comments = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a comment line to the node.
|
||||
*
|
||||
* @param comment The comment to add.
|
||||
* @return This builder.
|
||||
*/
|
||||
public B comment(String comment) {
|
||||
if (!Strings.isNullOrEmpty(comment) && !comment.startsWith("#")) {
|
||||
comment = "# " + comment;
|
||||
}
|
||||
comments.add(comment);
|
||||
return (B) this;
|
||||
}
|
||||
|
||||
public B comment(String... comments) {
|
||||
Collections.addAll(this.comments, comments);
|
||||
return (B) this;
|
||||
}
|
||||
|
||||
public B comment(Iterable<String> comments) {
|
||||
comments.forEach(this.comments::add);
|
||||
return (B) this;
|
||||
}
|
||||
|
||||
public ConfigHeaderNode build() {
|
||||
return new ConfigHeaderNode(path, comments.toArray(new String[0]));
|
||||
}
|
||||
}
|
||||
}
|
@ -7,39 +7,43 @@ import java.util.function.Function;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Implementation of {@link EnhancedValueNode}.
|
||||
* @param <T> The type of the value.
|
||||
*/
|
||||
public class MVValueNode<T> extends MVCommentedNode implements EnhancedValueNode<T> {
|
||||
public class ConfigNode<T> extends ConfigHeaderNode implements ValueNode<T> {
|
||||
|
||||
/**
|
||||
* Creates a new builder for a {@link MVValueNode}.
|
||||
* Creates a new builder for a {@link ConfigNode}.
|
||||
*
|
||||
* @param path The path of the node.
|
||||
* @param type The type of the value.
|
||||
* @return The new builder.
|
||||
* @param <T> The type of the value.
|
||||
*/
|
||||
public static <T> Builder<T, ? extends Builder> builder(String path, Class<T> type) {
|
||||
return new Builder<>(path, type);
|
||||
public static <T> ConfigNode.Builder<T, ? extends ConfigNode.Builder> builder(String path, Class<T> type) {
|
||||
return new ConfigNode.Builder<>(path, type);
|
||||
}
|
||||
|
||||
protected final String name;
|
||||
protected final Class<T> type;
|
||||
protected final T defaultValue;
|
||||
protected final String name;
|
||||
protected final Function<T, Boolean> validator;
|
||||
protected final BiConsumer<T, T> onSetValue;
|
||||
|
||||
protected MVValueNode(String path, String[] comments, Class<T> type, T defaultValue, String name, Function<T, Boolean> validator, BiConsumer<T, T> onSetValue) {
|
||||
protected ConfigNode(String path, String[] comments, String name, Class<T> type, T defaultValue, Function<T, Boolean> validator, BiConsumer<T, T> onSetValue) {
|
||||
super(path, comments);
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.defaultValue = defaultValue;
|
||||
this.name = name;
|
||||
this.validator = validator;
|
||||
this.onSetValue = onSetValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Optional<String> getName() {
|
||||
return Optional.ofNullable(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@ -60,15 +64,7 @@ public class MVValueNode<T> extends MVCommentedNode implements EnhancedValueNode
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Optional<String> getName() {
|
||||
return Optional.ofNullable(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean isValid(T value) {
|
||||
public boolean validate(T value) {
|
||||
if (validator != null) {
|
||||
return validator.apply(value);
|
||||
}
|
||||
@ -86,16 +82,16 @@ public class MVValueNode<T> extends MVCommentedNode implements EnhancedValueNode
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for {@link MVValueNode}.
|
||||
* Builder for {@link ConfigNode}.
|
||||
*
|
||||
* @param <T> The type of the value.
|
||||
* @param <B> The type of the builder.
|
||||
*/
|
||||
public static class Builder<T, B extends Builder<T, B>> extends MVCommentedNode.Builder<B> {
|
||||
public static class Builder<T, B extends ConfigNode.Builder<T, B>> extends ConfigHeaderNode.Builder<B> {
|
||||
|
||||
protected String name;
|
||||
protected final Class<T> type;
|
||||
protected T defaultValue;
|
||||
protected String name;
|
||||
protected Function<T, Boolean> validator;
|
||||
protected BiConsumer<T, T> onSetValue;
|
||||
|
||||
@ -107,8 +103,8 @@ public class MVValueNode<T> extends MVCommentedNode implements EnhancedValueNode
|
||||
*/
|
||||
protected Builder(@NotNull String path, @NotNull Class<T> type) {
|
||||
super(path);
|
||||
this.type = type;
|
||||
this.name = path;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -153,8 +149,8 @@ public class MVValueNode<T> extends MVCommentedNode implements EnhancedValueNode
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public MVValueNode<T> build() {
|
||||
return new MVValueNode<>(path, comments.toArray(new String[0]), type, defaultValue, name, validator, onSetValue);
|
||||
public ConfigNode<T> build() {
|
||||
return new ConfigNode<>(path, comments.toArray(new String[0]), name, type, defaultValue, validator, onSetValue);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package com.onarandombox.MultiverseCore.configuration.node;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import io.github.townyadvanced.commentedconfiguration.setting.TypedValueNode;
|
||||
|
||||
/**
|
||||
* A {@link TypedValueNode} that has a name, validation, and action to be performed when the value is set.
|
||||
*
|
||||
* @param <T> The type of the node's value.
|
||||
*/
|
||||
public interface EnhancedValueNode<T> extends TypedValueNode<T> {
|
||||
/**
|
||||
* Gets the name of this node. Used for identifying the node from user input.
|
||||
*
|
||||
* @return The name of this node.
|
||||
*/
|
||||
Optional<String> getName();
|
||||
|
||||
boolean isValid(T value);
|
||||
|
||||
/**
|
||||
* Called when the value of this node is set.
|
||||
*
|
||||
* @param oldValue The old value.
|
||||
* @param newValue The new value.
|
||||
*/
|
||||
void onSetValue(T oldValue, T newValue);
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
package com.onarandombox.MultiverseCore.configuration.node;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import io.github.townyadvanced.commentedconfiguration.setting.CommentedNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Implementation of {@link CommentedNode} that allows for comments to be added to the node.
|
||||
*/
|
||||
public class MVCommentedNode implements CommentedNode {
|
||||
|
||||
/**
|
||||
* Creates a new builder for a {@link MVCommentedNode}.
|
||||
*
|
||||
* @param path The path of the node.
|
||||
* @return The new builder.
|
||||
*/
|
||||
public static Builder<Builder> builder(String path) {
|
||||
return new Builder<>(path);
|
||||
}
|
||||
|
||||
protected final String path;
|
||||
protected final String[] comments;
|
||||
|
||||
protected MVCommentedNode(String path, String[] comments) {
|
||||
this.path = path;
|
||||
this.comments = comments;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public @NotNull String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public @NotNull String[] getComments() {
|
||||
return comments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for {@link MVCommentedNode}.
|
||||
*
|
||||
* @param <B> The type of the builder.
|
||||
*/
|
||||
public static class Builder<B extends Builder> {
|
||||
protected final String path;
|
||||
protected final List<String> comments;
|
||||
|
||||
/**
|
||||
* Creates a new builder for a {@link MVCommentedNode}.
|
||||
*
|
||||
* @param path The path of the node.
|
||||
*/
|
||||
protected Builder(String path) {
|
||||
this.path = path;
|
||||
this.comments = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a comment line to the node.
|
||||
*
|
||||
* @param comment The comment to add.
|
||||
* @return This builder.
|
||||
*/
|
||||
public B comment(@NotNull String comment) {
|
||||
if (!comment.isEmpty() && !comment.trim().startsWith("#")) {
|
||||
// Automatically add a comment prefix if the comment doesn't start with one.
|
||||
comment = "# " + comment;
|
||||
}
|
||||
this.comments.add(comment);
|
||||
return (B) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the node.
|
||||
*
|
||||
* @return The built node.
|
||||
*/
|
||||
public MVCommentedNode build() {
|
||||
return new MVCommentedNode(path, comments.toArray(new String[0]));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package com.onarandombox.MultiverseCore.configuration.node;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface Node {
|
||||
|
||||
/**
|
||||
* Gets the YAML path of the node.
|
||||
*
|
||||
* @return The YAML path of the node.
|
||||
*/
|
||||
@NotNull String getPath();
|
||||
}
|
@ -13,30 +13,30 @@ import org.jetbrains.annotations.NotNull;
|
||||
/**
|
||||
* A collection of {@link CommentedNode}s, with mappings to nodes by name.
|
||||
*/
|
||||
public class NodeGroup implements Collection<CommentedNode> {
|
||||
private final Collection<CommentedNode> nodes;
|
||||
private final Map<String, CommentedNode> nodesMap;
|
||||
public class NodeGroup implements Collection<Node> {
|
||||
private final Collection<Node> nodes;
|
||||
private final Map<String, Node> nodesMap;
|
||||
|
||||
public NodeGroup() {
|
||||
this.nodes = new ArrayList<>();
|
||||
this.nodesMap = new HashMap<>();
|
||||
}
|
||||
|
||||
public NodeGroup(Collection<CommentedNode> nodes) {
|
||||
public NodeGroup(Collection<Node> nodes) {
|
||||
this.nodes = nodes;
|
||||
this.nodesMap = new HashMap<>(nodes.size());
|
||||
nodes.forEach(this::addNodeIndex);
|
||||
}
|
||||
|
||||
private void addNodeIndex(CommentedNode node) {
|
||||
if (node instanceof EnhancedValueNode) {
|
||||
((EnhancedValueNode<?>) node).getName().ifPresent(name -> nodesMap.put(name, node));
|
||||
private void addNodeIndex(Node node) {
|
||||
if (node instanceof ValueNode) {
|
||||
((ValueNode<?>) node).getName().ifPresent(name -> nodesMap.put(name, node));
|
||||
}
|
||||
}
|
||||
|
||||
private void removeNodeIndex(CommentedNode node) {
|
||||
if (node instanceof EnhancedValueNode) {
|
||||
((EnhancedValueNode<?>) node).getName().ifPresent(nodesMap::remove);
|
||||
private void removeNodeIndex(Node node) {
|
||||
if (node instanceof ValueNode) {
|
||||
((ValueNode<?>) node).getName().ifPresent(nodesMap::remove);
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,14 +49,19 @@ public class NodeGroup implements Collection<CommentedNode> {
|
||||
return nodesMap.keySet();
|
||||
}
|
||||
|
||||
public Optional<Node> findNode(String name) {
|
||||
return Optional.ofNullable(nodesMap.get(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the node with the given name.
|
||||
*
|
||||
* @param name The name of the node to get.
|
||||
* @return The node with the given name, or {@link Optional#empty()} if no node with the given name exists.
|
||||
*/
|
||||
public Optional<CommentedNode> findNode(String name) {
|
||||
return Optional.ofNullable(nodesMap.get(name));
|
||||
public <T extends Node> Optional<T> findNode(String name, Class<T> type) {
|
||||
return Optional.ofNullable(nodesMap.get(name))
|
||||
.map(node -> type.isAssignableFrom(node.getClass()) ? (T) node : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -76,7 +81,7 @@ public class NodeGroup implements Collection<CommentedNode> {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterator<CommentedNode> iterator() {
|
||||
public Iterator<Node> iterator() {
|
||||
return nodes.iterator();
|
||||
}
|
||||
|
||||
@ -91,9 +96,9 @@ public class NodeGroup implements Collection<CommentedNode> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(CommentedNode commentedNode) {
|
||||
if (nodes.add(commentedNode)) {
|
||||
addNodeIndex(commentedNode);
|
||||
public boolean add(Node node) {
|
||||
if (nodes.add(node)) {
|
||||
addNodeIndex(node);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -102,7 +107,7 @@ public class NodeGroup implements Collection<CommentedNode> {
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
if (nodes.remove(o) && o instanceof CommentedNode) {
|
||||
removeNodeIndex((CommentedNode) o);
|
||||
removeNodeIndex((Node) o);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -114,7 +119,7 @@ public class NodeGroup implements Collection<CommentedNode> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(@NotNull Collection<? extends CommentedNode> collection) {
|
||||
public boolean addAll(@NotNull Collection<? extends Node> collection) {
|
||||
return nodes.addAll(collection);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,45 @@
|
||||
package com.onarandombox.MultiverseCore.configuration.node;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface ValueNode<T> extends Node {
|
||||
/**
|
||||
* Gets the name of this node. Used for identifying the node from user input.
|
||||
*
|
||||
* @return The name of this node.
|
||||
*/
|
||||
Optional<String> getName();
|
||||
|
||||
/**
|
||||
* Gets the class type {@link T} of the node value.
|
||||
*
|
||||
* @return The class type of the node value.
|
||||
*/
|
||||
@NotNull Class<T> getType();
|
||||
|
||||
/**
|
||||
* Gets the default value with type {@link T} of the node.
|
||||
*
|
||||
* @return The default value of the node.
|
||||
*/
|
||||
@Nullable T getDefaultValue();
|
||||
|
||||
/**
|
||||
* Validates the value of this node.
|
||||
*
|
||||
* @param value The value to validate.
|
||||
* @return True if the value is valid, false otherwise.
|
||||
*/
|
||||
boolean validate(T value);
|
||||
|
||||
/**
|
||||
* Called when the value of this node is set.
|
||||
*
|
||||
* @param oldValue The old value.
|
||||
* @param newValue The new value.
|
||||
*/
|
||||
void onSetValue(T oldValue, T newValue);
|
||||
}
|
@ -59,14 +59,14 @@ class ConfigTest : TestWithMockBukkit() {
|
||||
|
||||
@Test
|
||||
fun `Getting existing config property with getProperty returns expected value`() {
|
||||
assertEquals(false, config.getProperty("enforce-access"))
|
||||
assertEquals("world", config.getProperty("first-spawn-location"))
|
||||
assertEquals(false, config.getProperty("enforce-access").get())
|
||||
assertEquals("world", config.getProperty("first-spawn-location").get())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Getting non-existing config property with getProperty returns null`() {
|
||||
assertNull(config.getProperty("invalid-property"))
|
||||
assertNull(config.getProperty("version"))
|
||||
assertTrue(config.getProperty("invalid-property").isFailure)
|
||||
assertTrue(config.getProperty("version").isFailure)
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -77,19 +77,19 @@ class ConfigTest : TestWithMockBukkit() {
|
||||
|
||||
@Test
|
||||
fun `Updating an existing config property with setProperty reflects the changes in getProperty`() {
|
||||
assertTrue(config.setProperty("enforce-access", true))
|
||||
assertEquals(true, config.getProperty("enforce-access"))
|
||||
assertTrue(config.setProperty("enforce-access", true).get())
|
||||
assertEquals(true, config.getProperty("enforce-access").get())
|
||||
|
||||
assertTrue(config.setProperty("first-spawn-location", "world2"))
|
||||
assertEquals("world2", config.getProperty("first-spawn-location"))
|
||||
assertTrue(config.setProperty("first-spawn-location", "world2").get())
|
||||
assertEquals("world2", config.getProperty("first-spawn-location").get())
|
||||
|
||||
assertTrue(config.setProperty("global-debug", 1))
|
||||
assertEquals(1, config.getProperty("global-debug"))
|
||||
assertTrue(config.setProperty("global-debug", 1).get())
|
||||
assertEquals(1, config.getProperty("global-debug").get())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Updating a non-existing property with setProperty returns false`() {
|
||||
assertFalse(config.setProperty("invalid-property", false))
|
||||
assertFalse(config.setProperty("version", 1.1))
|
||||
assertTrue(config.setProperty("invalid-property", false).isFailure)
|
||||
assertTrue(config.setProperty("version", 1.1).isFailure)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user