diff --git a/Core/src/main/java/com/songoda/core/configuration/ConfigEntry.java b/Core/src/main/java/com/songoda/core/configuration/ConfigEntry.java new file mode 100644 index 00000000..52cc914f --- /dev/null +++ b/Core/src/main/java/com/songoda/core/configuration/ConfigEntry.java @@ -0,0 +1,186 @@ +package com.songoda.core.configuration; + +import com.songoda.core.compatibility.CompatibleMaterial; +import com.songoda.core.utils.Pair; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.function.Supplier; + +public interface ConfigEntry { + @NotNull String getKey(); + + @NotNull IConfiguration getConfig(); + + default boolean has() { + return getConfig().has(getKey()); + } + + void set(@Nullable Object value); + + default @Nullable Object get() { + return getConfig().get(getKey()); + } + + default @Nullable Object getOr(@Nullable Object fallbackValue) { + return getConfig().getOr(getKey(), fallbackValue); + } + + @Nullable Object getDefaultValue(); + + void setDefaultValue(@Nullable Object defaultValue); + + /** + * @see #withComment(Supplier) + */ + @Contract("_ -> this") + default ConfigEntry withComment(String comment) { + return this.withComment(() -> comment); + } + + /** + * @see NodeCommentable#setNodeComment(String, Supplier) + */ + @Contract("_ -> this") + ConfigEntry withComment(Supplier comment); + + /** + * @return <configVersion, Pair<keyInGivenVersion, valueConverter>> + */ + @Nullable Map>> getUpgradeSteps(); + + /** + * @see #withUpgradeStep(int, String, Function) + */ + @Contract("_, _ -> this") + default ConfigEntry withUpgradeStep(int version, @NotNull String keyInGivenVersion) { + return withUpgradeStep(version, keyInGivenVersion, null); + } + + /** + * @param version The version to upgrade from (e.g. 1 for the upgrade from 1 to 2) + * @param keyInGivenVersion The old key in the given version or null if it didn't change + * @param valueConverter A function that converts the old version's value to a new one, or null if it didn't change + */ + @Contract("_, null, null -> fail; _, _, _ -> this") + ConfigEntry withUpgradeStep(int version, @Nullable String keyInGivenVersion, @Nullable Function valueConverter); + + default @Nullable String getString() { + return getStringOr(null); + } + + @Contract("!null -> !null") + default @Nullable String getStringOr(String fallbackValue) { + Object value = get(); + + return value == null ? fallbackValue : value.toString(); + } + + /** + * @see #getIntOr(int) + */ + default int getInt() { + return getIntOr(0); + } + + /** + * Returns the values parsed as an integer.
+ * If it is a floating point number, it will be rounded down. + * + * @see Double#valueOf(String) + */ + default int getIntOr(int fallbackValue) { + String value = getString(); + + if (value == null) { + return fallbackValue; + } + + return Double.valueOf(value).intValue(); + } + + /** + * @see #getDoubleOr(double) + */ + default double getDouble() { + return getDoubleOr(0); + } + + /** + * Returns the values parsed as a double. + * + * @see Double#parseDouble(String) + */ + default double getDoubleOr(double fallbackValue) { + String value = getString(); + + if (value == null) { + return fallbackValue; + } + + return Double.parseDouble(value); + } + + /** + * @see #getBooleanOr(boolean) + */ + default boolean getBoolean() { + return getBooleanOr(false); + } + + /** + * Returns the values parsed as a boolean. + * + * @see Boolean#parseBoolean(String) + */ + default boolean getBooleanOr(boolean fallbackValue) { + String value = getString(); + + if (value == null) { + return fallbackValue; + } + + return Boolean.parseBoolean(value); + } + + default @Nullable List getStringList() { + return getStringListOr(null); + } + + @Contract("!null -> !null") + default @Nullable List getStringListOr(List fallbackValue) { + Object value = get(); + + if (value instanceof List) { + //noinspection unchecked + return (List) value; + } + + return fallbackValue; + } + + /** + * @see #getMaterialOr(CompatibleMaterial) + */ + default CompatibleMaterial getMaterial() { + return getMaterialOr(null); + } + + /** + * @see CompatibleMaterial#getMaterial(String) + */ + @Contract("!null -> !null") + default @Nullable CompatibleMaterial getMaterialOr(@Nullable CompatibleMaterial defaultValue) { + String value = getString(); + + if (value == null) { + return defaultValue; + } + + return CompatibleMaterial.getMaterial(value); + } +} diff --git a/Core/src/main/java/com/songoda/core/configuration/ReadOnlyConfigEntry.java b/Core/src/main/java/com/songoda/core/configuration/ReadOnlyConfigEntry.java new file mode 100644 index 00000000..59cfc50b --- /dev/null +++ b/Core/src/main/java/com/songoda/core/configuration/ReadOnlyConfigEntry.java @@ -0,0 +1,66 @@ +package com.songoda.core.configuration; + +import com.songoda.core.utils.Pair; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.function.Function; +import java.util.function.Supplier; + +public class ReadOnlyConfigEntry implements ConfigEntry { + protected final @NotNull IConfiguration config; + protected final @NotNull String key; + + public ReadOnlyConfigEntry(@NotNull IConfiguration config, @NotNull String key) { + this.config = config; + this.key = key; + } + + @Override + public @NotNull String getKey() { + return this.key; + } + + @Override + public @NotNull IConfiguration getConfig() { + return this.config; + } + + @Override + @Contract(" -> null") + public @Nullable Object getDefaultValue() { + return null; + } + + @Override + @Contract("_ -> fail") + public void setDefaultValue(@Nullable Object defaultValue) { + throw new UnsupportedOperationException("Cannot set defaultValue on a read-only config entry"); + } + + @Override + @Contract("_ -> fail") + public ConfigEntry withComment(Supplier comment) { + throw new UnsupportedOperationException("Cannot set comment on a read-only config entry"); + } + + @Override + @Contract(" -> null") + public Map>> getUpgradeSteps() { + return null; + } + + @Override + @Contract("_, _, _ -> fail") + public ConfigEntry withUpgradeStep(int version, @Nullable String keyInGivenVersion, @Nullable Function valueConverter) { + throw new UnsupportedOperationException("Cannot set upgrade step on a read-only config entry"); + } + + @Override + @Contract("_ -> fail") + public void set(@Nullable Object value) { + throw new UnsupportedOperationException("Cannot set value on a read-only config entry"); + } +} diff --git a/Core/src/main/java/com/songoda/core/configuration/WriteableConfigEntry.java b/Core/src/main/java/com/songoda/core/configuration/WriteableConfigEntry.java new file mode 100644 index 00000000..f2610b21 --- /dev/null +++ b/Core/src/main/java/com/songoda/core/configuration/WriteableConfigEntry.java @@ -0,0 +1,19 @@ +package com.songoda.core.configuration; + +import org.jetbrains.annotations.Nullable; + +import java.util.function.Supplier; + +public interface WriteableConfigEntry extends ConfigEntry { + @Override + default void set(@Nullable Object value) { + getConfig().set(getKey(), value); + } + + @Override + default ConfigEntry withComment(Supplier comment) { + ((NodeCommentable) getConfig()).setNodeComment(getKey(), comment); + + return this; + } +} diff --git a/Core/src/main/java/com/songoda/core/configuration/songoda/ConfigEntry.java b/Core/src/main/java/com/songoda/core/configuration/songoda/ConfigEntry.java deleted file mode 100644 index 22053150..00000000 --- a/Core/src/main/java/com/songoda/core/configuration/songoda/ConfigEntry.java +++ /dev/null @@ -1,253 +0,0 @@ -package com.songoda.core.configuration.songoda; - -import com.songoda.core.compatibility.CompatibleMaterial; -import com.songoda.core.configuration.NodeCommentable; -import com.songoda.core.utils.Pair; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.function.Function; -import java.util.function.Supplier; - -public class ConfigEntry { - public final @NotNull SongodaYamlConfig config; - public final @NotNull String key; - protected @Nullable Object defaultValue; - - protected @Nullable Map>> upgradeStepsForVersion; - - public ConfigEntry(@NotNull SongodaYamlConfig config, @NotNull String key) { - this(config, key, null); - } - - public ConfigEntry(@NotNull SongodaYamlConfig config, @NotNull String key, @Nullable Object defaultValue) { - this.config = Objects.requireNonNull(config); - this.key = Objects.requireNonNull(key); - this.defaultValue = defaultValue; - - if (get() == null) { - set(this.defaultValue); - } - - this.config.registerConfigEntry(this); - } - - public @Nullable Object getDefaultValue() { - return this.defaultValue; - } - - public void setDefaultValue(@Nullable Object defaultValue) { - this.defaultValue = defaultValue; - } - - /** - * @see #withComment(Supplier) - */ - public ConfigEntry withComment(String comment) { - return this.withComment(() -> comment); - } - - /** - * @see NodeCommentable#setNodeComment(String, Supplier) - */ - public ConfigEntry withComment(Supplier comment) { - ((NodeCommentable) this.config).setNodeComment(this.key, comment); - - return this; - } - - /** - * @see #withUpgradeStep(int, String, Function) - */ - public ConfigEntry withUpgradeStep(int version, @NotNull String keyInGivenVersion) { - return withUpgradeStep(version, keyInGivenVersion, null); - } - - /** - * @param version The version to upgrade from (e.g. 1 for the upgrade from 1 to 2) - * @param keyInGivenVersion The old key in the given version or null if it didn't change - * @param valueConverter A function that converts the old version's value to a new one, or null if it didn't change - */ - @Contract("_, null, null -> fail") - public ConfigEntry withUpgradeStep(int version, @Nullable String keyInGivenVersion, @Nullable Function valueConverter) { - if (keyInGivenVersion == null && valueConverter == null) { - throw new IllegalArgumentException("You must provide either a key or a value converter"); - } - - if (this.upgradeStepsForVersion == null) { - this.upgradeStepsForVersion = new HashMap<>(1); - } - - this.upgradeStepsForVersion.put(version, new Pair<>(keyInGivenVersion, valueConverter)); - - return this; - } - - /** - * @see SongodaYamlConfig#has(String) - */ - public boolean has() { - return this.config.has(this.key); - } - - /** - * @see SongodaYamlConfig#set(String, Object) - */ - public Object set(@Nullable Object value) { - // TODO: Test what happens if the value is an enum (CompatibleMaterial) - return this.config.set(this.key, value); - } - - /** - * @see SongodaYamlConfig#get(String) - */ - public @Nullable Object get() { - return this.config.get(this.key); - } - - /** - * @see SongodaYamlConfig#getOr(String, Object) - */ - public @Nullable Object getOr(@Nullable Object fallbackValue) { - return this.config.getOr(this.key, fallbackValue); - } - - public @Nullable String getString() { - Object value = get(); - - return value != null ? value.toString() : null; - } - - @Contract("!null -> !null") - public @Nullable String getString(String fallbackValue) { - Object value = get(); - - return value == null ? fallbackValue : value.toString(); - } - - /** - * @see #getInt(int) - */ - public int getInt() { - return getInt(0); - } - - /** - * Returns the values parsed as an integer.
- * If it is a floating point number, it will be rounded down. - * - * @see Double#valueOf(String) - */ - public int getInt(int fallbackValue) { - String value = getString(); - - if (value == null) { - return fallbackValue; - } - - return Double.valueOf(value).intValue(); - } - - /** - * @see #getDouble(double) - */ - public double getDouble() { - return getDouble(0); - } - - /** - * Returns the values parsed as a double. - * - * @see Double#parseDouble(String) - */ - public double getDouble(double fallbackValue) { - String value = getString(); - - if (value == null) { - return fallbackValue; - } - - return Double.parseDouble(value); - } - - /** - * @see #getBoolean(boolean) - */ - public boolean getBoolean() { - return getBoolean(false); - } - - /** - * Returns the values parsed as a boolean. - * - * @see Boolean#parseBoolean(String) - */ - public boolean getBoolean(boolean fallbackValue) { - String value = getString(); - - if (value == null) { - return fallbackValue; - } - - return Boolean.parseBoolean(value); - } - - public @Nullable List getStringList() { - return getStringList(null); - } - - @Contract("!null -> !null") - public @Nullable List getStringList(List fallbackValue) { - Object value = get(); - - if (value instanceof List) { - //noinspection unchecked - return (List) value; - } - - return fallbackValue; - } - - /** - * @see #getMaterial(CompatibleMaterial) - */ - public CompatibleMaterial getMaterial() { - return getMaterial(null); - } - - /** - * @see CompatibleMaterial#getMaterial(String) - */ - public @Nullable CompatibleMaterial getMaterial(@Nullable CompatibleMaterial defaultValue) { - String value = getString(); - - if (value == null) { - return defaultValue; - } - - return CompatibleMaterial.getMaterial(value); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - ConfigEntry that = (ConfigEntry) o; - - return this.config.equals(that.config) && - this.key.equals(that.key) && - Objects.equals(this.defaultValue, that.defaultValue) && - Objects.equals(this.upgradeStepsForVersion, that.upgradeStepsForVersion); - } - - @Override - public int hashCode() { - return Objects.hash(this.config, this.key, this.defaultValue, this.upgradeStepsForVersion); - } -} diff --git a/Core/src/main/java/com/songoda/core/configuration/songoda/SongodaYamlConfig.java b/Core/src/main/java/com/songoda/core/configuration/songoda/SongodaYamlConfig.java index 96cfe758..d09bf4b4 100644 --- a/Core/src/main/java/com/songoda/core/configuration/songoda/SongodaYamlConfig.java +++ b/Core/src/main/java/com/songoda/core/configuration/songoda/SongodaYamlConfig.java @@ -1,5 +1,8 @@ package com.songoda.core.configuration.songoda; +import com.songoda.core.configuration.ConfigEntry; +import com.songoda.core.configuration.ReadOnlyConfigEntry; +import com.songoda.core.configuration.yaml.YamlConfigEntry; import com.songoda.core.configuration.yaml.YamlConfiguration; import com.songoda.core.utils.Pair; import org.bukkit.plugin.java.JavaPlugin; @@ -24,6 +27,7 @@ import java.util.function.Supplier; import java.util.logging.Level; import java.util.logging.Logger; +// TODO: replace all config related exceptions with custom exceptions // TODO: Allow registering load-Listeners // TODO: Provide method to only save if changed public class SongodaYamlConfig extends YamlConfiguration { @@ -82,20 +86,26 @@ public class SongodaYamlConfig extends YamlConfiguration { return false; } - public ConfigEntry getAsEntry(String key) { - return new ConfigEntry(this, key); + public ReadOnlyConfigEntry getReadEntry(@NotNull String key) { + return new ReadOnlyConfigEntry(this, key); } - protected void registerConfigEntry(ConfigEntry entry) { - this.configEntries.put(entry.key, entry); + public ConfigEntry createEntry(@NotNull String key) { + return createEntry(key, null); } - public void unregisterConfigEntry(ConfigEntry entry) { - unregisterConfigEntry(entry.key); - } + public ConfigEntry createEntry(@NotNull String key, @Nullable Object defaultValue) { + ConfigEntry entry = new YamlConfigEntry(this, key, defaultValue); - public void unregisterConfigEntry(String key) { - this.configEntries.remove(key); + if (this.configEntries.putIfAbsent(key, entry) != null) { + throw new IllegalArgumentException("Entry already exists for key: " + key); + } + + if (entry.get() == null) { + entry.set(defaultValue); + } + + return entry; } public SongodaYamlConfig withVersion(int version) { @@ -113,7 +123,7 @@ public class SongodaYamlConfig extends YamlConfiguration { this.targetVersion = version; - this.versionEntry = new ConfigEntry(this, key, 0); + this.versionEntry = new YamlConfigEntry(this, key, 0); this.versionEntry.withComment(comment); this.versionEntry.set(this.targetVersion); @@ -196,18 +206,18 @@ public class SongodaYamlConfig extends YamlConfiguration { } for (ConfigEntry entry : this.configEntries.values()) { - if (entry.upgradeStepsForVersion == null) { + if (entry.getUpgradeSteps() == null) { continue; } - Pair<@Nullable String, @Nullable Function> upgradeStep = entry.upgradeStepsForVersion.get(currentVersion); + Pair<@Nullable String, @Nullable Function> upgradeStep = entry.getUpgradeSteps().get(currentVersion); if (upgradeStep == null) { continue; } String oldEntryKey = upgradeStep.getFirst(); if (oldEntryKey == null) { - oldEntryKey = entry.key; + oldEntryKey = entry.getKey(); } Object newValue = get(oldEntryKey); diff --git a/Core/src/main/java/com/songoda/core/configuration/yaml/YamlConfigEntry.java b/Core/src/main/java/com/songoda/core/configuration/yaml/YamlConfigEntry.java new file mode 100644 index 00000000..dc075188 --- /dev/null +++ b/Core/src/main/java/com/songoda/core/configuration/yaml/YamlConfigEntry.java @@ -0,0 +1,84 @@ +package com.songoda.core.configuration.yaml; + +import com.songoda.core.configuration.ConfigEntry; +import com.songoda.core.configuration.IConfiguration; +import com.songoda.core.configuration.WriteableConfigEntry; +import com.songoda.core.utils.Pair; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; + +public class YamlConfigEntry implements WriteableConfigEntry { + protected final @NotNull YamlConfiguration config; + protected final @NotNull String key; + protected @Nullable Object defaultValue; + + protected @Nullable Map>> upgradeSteps; + + public YamlConfigEntry(@NotNull YamlConfiguration config, @NotNull String key, @Nullable Object defaultValue) { + this.config = config; + this.key = key; + this.defaultValue = defaultValue; + } + + @Override + public @NotNull String getKey() { + return this.key; + } + + @Override + public @NotNull IConfiguration getConfig() { + return this.config; + } + + @Override + public @Nullable Object getDefaultValue() { + return this.defaultValue; + } + + @Override + public @Nullable Map>> getUpgradeSteps() { + return this.upgradeSteps; + } + + @Override + public void setDefaultValue(@Nullable Object defaultValue) { + this.defaultValue = defaultValue; + } + + @Override + public ConfigEntry withUpgradeStep(int version, @Nullable String keyInGivenVersion, @Nullable Function valueConverter) { + if (keyInGivenVersion == null && valueConverter == null) { + throw new IllegalArgumentException("You must provide either a key or a value converter"); + } + + if (this.upgradeSteps == null) { + this.upgradeSteps = new HashMap<>(1); + } + + this.upgradeSteps.put(version, new Pair<>(keyInGivenVersion, valueConverter)); + + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + YamlConfigEntry that = (YamlConfigEntry) o; + return this.config.equals(that.config) && + this.key.equals(that.key) && + Objects.equals(this.defaultValue, that.defaultValue) && + Objects.equals(this.upgradeSteps, that.upgradeSteps); + } + + @Override + public int hashCode() { + return Objects.hash(this.config, this.key, this.defaultValue, this.upgradeSteps); + } +} diff --git a/Core/src/main/java/com/songoda/core/configuration/yaml/YamlConfiguration.java b/Core/src/main/java/com/songoda/core/configuration/yaml/YamlConfiguration.java index d50c97ce..86f2bf58 100644 --- a/Core/src/main/java/com/songoda/core/configuration/yaml/YamlConfiguration.java +++ b/Core/src/main/java/com/songoda/core/configuration/yaml/YamlConfiguration.java @@ -87,10 +87,10 @@ public class YamlConfiguration implements IConfiguration, HeaderCommentable, Nod @Override @Contract(pure = true, value = "null,_ -> param2") - public @Nullable Object getOr(String key, @Nullable Object defaultValue) { + public @Nullable Object getOr(String key, @Nullable Object fallbackValue) { Object value = get(key); - return value == null ? defaultValue : value; + return value == null ? fallbackValue : value; } public @NotNull Set getKeys(String key) { @@ -187,7 +187,7 @@ public class YamlConfiguration implements IConfiguration, HeaderCommentable, Nod } @Override - public void load(Reader reader) { + public void load(Reader reader) throws IOException { Object yamlData = this.yaml.load(reader); if (yamlData == null) { yamlData = Collections.emptyMap(); diff --git a/Core/src/main/java/com/songoda/core/gui/CustomizableGui.java b/Core/src/main/java/com/songoda/core/gui/CustomizableGui.java index 4fe1870d..b5a664d6 100644 --- a/Core/src/main/java/com/songoda/core/gui/CustomizableGui.java +++ b/Core/src/main/java/com/songoda/core/gui/CustomizableGui.java @@ -2,7 +2,7 @@ package com.songoda.core.gui; import com.songoda.core.compatibility.CompatibleMaterial; import com.songoda.core.compatibility.ServerVersion; -import com.songoda.core.configuration.songoda.ConfigEntry; +import com.songoda.core.configuration.ConfigEntry; import com.songoda.core.configuration.songoda.SongodaYamlConfig; import com.songoda.core.gui.methods.Clickable; import com.songoda.core.utils.TextUtils; @@ -58,14 +58,14 @@ public class CustomizableGui extends Gui { "https://wiki.songoda.com/Gui"); config.setNodeComment("overrides.example", "This is just an example and does not override to any items in this GUI."); - new ConfigEntry(config, "overrides.example.item", CompatibleMaterial.STONE) + config.createEntry("overrides.example.item", CompatibleMaterial.STONE) .withComment("This is the icon material you would like to replace\n" + "the current material with."); - new ConfigEntry(config, "overrides.example.position", 5) + config.createEntry("overrides.example.position", 5) .withComment("This is the current position of the icon you would like to move.\n" + "The number represents the cell the icon currently resides in."); - ConfigEntry disabledGuis = new ConfigEntry(config, "disabled", Arrays.asList("example3", "example4", "example5")) + ConfigEntry disabledGuis = config.createEntry("disabled", Arrays.asList("example3", "example4", "example5")) .withComment("All keys on this list will be disabled. You can add any items key here\n" + "if you no longer want that item in the GUI."); @@ -80,7 +80,7 @@ public class CustomizableGui extends Gui { loadedGuis.put(guiKey, customContent); this.customContent = customContent; - int rows = config.getAsEntry("overrides.__ROWS__").getInt(-1); + int rows = config.getReadEntry("overrides.__ROWS__").getIntOr(-1); if (rows != -1) { customContent.setRows(rows); } @@ -88,39 +88,39 @@ public class CustomizableGui extends Gui { for (String overrideKey : config.getKeys("overrides")) { String keyPrefix = "overrides." + overrideKey; - ConfigEntry title = config.getAsEntry(keyPrefix + ".title"); + ConfigEntry title = config.getReadEntry(keyPrefix + ".title"); - ConfigEntry position = config.getAsEntry(keyPrefix + ".position"); + ConfigEntry position = config.getReadEntry(keyPrefix + ".position"); - ConfigEntry row = config.getAsEntry(keyPrefix + ".row"); - ConfigEntry col = config.getAsEntry(keyPrefix + ".col"); + ConfigEntry row = config.getReadEntry(keyPrefix + ".row"); + ConfigEntry col = config.getReadEntry(keyPrefix + ".col"); - ConfigEntry mirrorRow = config.getAsEntry(keyPrefix + ".mirrorrow"); - ConfigEntry mirrorCol = config.getAsEntry(keyPrefix + ".mirrorcol"); + ConfigEntry mirrorRow = config.getReadEntry(keyPrefix + ".mirrorrow"); + ConfigEntry mirrorCol = config.getReadEntry(keyPrefix + ".mirrorcol"); - ConfigEntry item = config.getAsEntry(keyPrefix + ".item"); - ConfigEntry lore = config.getAsEntry(keyPrefix + ".lore"); + ConfigEntry item = config.getReadEntry(keyPrefix + ".item"); + ConfigEntry lore = config.getReadEntry(keyPrefix + ".lore"); boolean configHasRowOrColSet = row.has() || col.has(); boolean configHasMirrorRowOrColSet = mirrorRow.has() || mirrorCol.has(); if (configHasMirrorRowOrColSet) { customContent.addButton(overrideKey, - row.getInt(-1), - col.getInt(-1), + row.getIntOr(-1), + col.getIntOr(-1), mirrorRow.getBoolean(), mirrorCol.getBoolean(), item.getMaterial()); } else if (configHasRowOrColSet) { customContent.addButton(overrideKey, - row.getInt(-1), - col.getInt(-1), + row.getIntOr(-1), + col.getIntOr(-1), title.getString(), lore.getStringList(), item.getMaterial()); } else { customContent.addButton(overrideKey, - position.getString("-1"), + position.getStringOr("-1"), title.getString(), lore.getStringList(), item.getMaterial()); @@ -128,7 +128,7 @@ public class CustomizableGui extends Gui { } } - for (String disabled : disabledGuis.getStringList(Collections.emptyList())) { + for (String disabled : disabledGuis.getStringListOr(Collections.emptyList())) { customContent.disableButton(disabled); } } else { diff --git a/Core/src/test/java/com/songoda/core/configuration/ReadOnlyConfigEntryTest.java b/Core/src/test/java/com/songoda/core/configuration/ReadOnlyConfigEntryTest.java new file mode 100644 index 00000000..059e43c3 --- /dev/null +++ b/Core/src/test/java/com/songoda/core/configuration/ReadOnlyConfigEntryTest.java @@ -0,0 +1,31 @@ +package com.songoda.core.configuration; + +import com.songoda.core.configuration.yaml.YamlConfiguration; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +public class ReadOnlyConfigEntryTest { + @Test + void testGetKey() { + ConfigEntry entry = new ReadOnlyConfigEntry(new YamlConfiguration(), "key-1"); + + assertEquals("key-1", entry.getKey()); + } + + @Test + void testGetConfig() { + IConfiguration config = new YamlConfiguration(); + ConfigEntry entry = new ReadOnlyConfigEntry(config, "key"); + + assertSame(config, entry.getConfig()); + } + + @Test + void testNullGetters() { + ConfigEntry entry = new ReadOnlyConfigEntry(new YamlConfiguration(), "key-null"); + + assertNull(entry.getDefaultValue()); + assertNull(entry.getUpgradeSteps()); + } +} diff --git a/Core/src/test/java/com/songoda/core/configuration/songoda/SongodaYamlConfigRoundtripTest.java b/Core/src/test/java/com/songoda/core/configuration/songoda/SongodaYamlConfigRoundtripTest.java index f2b08089..6914061b 100644 --- a/Core/src/test/java/com/songoda/core/configuration/songoda/SongodaYamlConfigRoundtripTest.java +++ b/Core/src/test/java/com/songoda/core/configuration/songoda/SongodaYamlConfigRoundtripTest.java @@ -1,5 +1,6 @@ package com.songoda.core.configuration.songoda; +import com.songoda.core.configuration.ConfigEntry; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -9,9 +10,7 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; class SongodaYamlConfigRoundtripTest { Path cfg; @@ -42,10 +41,10 @@ class SongodaYamlConfigRoundtripTest { SongodaYamlConfig cfg = new SongodaYamlConfig(this.cfg.toFile()) .withVersion(3); - ConfigEntry cmdFooSuccess = new ConfigEntry(cfg, "command.foo.success", "Default success value") + ConfigEntry cmdFooSuccess = cfg.createEntry("command.foo.success", "Default success value") .withComment("This message is shown when the 'foo' command succeeds.") .withUpgradeStep(1, "messages.fooSuccess"); - ConfigEntry range = new ConfigEntry(cfg, "range") + ConfigEntry range = cfg.createEntry("range") .withComment("This is the range of the 'foo' command") .withUpgradeStep(1, null, o -> { if (o == null) { @@ -55,7 +54,7 @@ class SongodaYamlConfigRoundtripTest { return o; }) .withUpgradeStep(2, null, o -> o + " blocks"); - ConfigEntry incrementer = new ConfigEntry(cfg, "incrementer", 0) + ConfigEntry incrementer = cfg.createEntry("incrementer", 0) .withComment("This is the incrementer of the 'foo' command") .withUpgradeStep(1, null, o -> { if (o == null) { @@ -65,6 +64,8 @@ class SongodaYamlConfigRoundtripTest { return (int) o + 1; }) .withUpgradeStep(3, null, (o) -> "text"); + ConfigEntry entryWithoutUpgradeStep = cfg.createEntry("entryWithoutUpgradeStep", "Default value") + .withComment("This is the entry without an upgrade step"); assertTrue(cfg.init()); @@ -79,6 +80,9 @@ class SongodaYamlConfigRoundtripTest { assertTrue(incrementer.has()); assertEquals(cfg.get("incrementer"), incrementer.get()); + assertTrue(entryWithoutUpgradeStep.has()); + assertEquals(cfg.get("entryWithoutUpgradeStep"), entryWithoutUpgradeStep.get()); + assertEquals("# Don't touch this – it's used to track the version of the config.\n" + "version: 3\n" + "command:\n" + @@ -88,6 +92,8 @@ class SongodaYamlConfigRoundtripTest { "# This is the range of the 'foo' command\n" + "range: 10 blocks\n" + "# This is the incrementer of the 'foo' command\n" + - "incrementer: 0\n", new String(Files.readAllBytes(this.cfg))); + "incrementer: 0\n" + + "# This is the entry without an upgrade step\n" + + "entryWithoutUpgradeStep: Default value\n", new String(Files.readAllBytes(this.cfg))); } } diff --git a/Core/src/test/java/com/songoda/core/configuration/songoda/SongodaYamlConfigTest.java b/Core/src/test/java/com/songoda/core/configuration/songoda/SongodaYamlConfigTest.java index 3f93514b..eb224b4b 100644 --- a/Core/src/test/java/com/songoda/core/configuration/songoda/SongodaYamlConfigTest.java +++ b/Core/src/test/java/com/songoda/core/configuration/songoda/SongodaYamlConfigTest.java @@ -1,7 +1,7 @@ package com.songoda.core.configuration.songoda; +import com.songoda.core.configuration.ConfigEntry; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -13,9 +13,7 @@ import java.nio.file.Path; import java.util.Comparator; import java.util.stream.Stream; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.*; class SongodaYamlConfigTest { Path tmpDir; @@ -97,15 +95,15 @@ class SongodaYamlConfigTest { @Test void testWithNegativeVersion() { SongodaYamlConfig cfg = new SongodaYamlConfig(this.cfg.toFile()); - Assertions.assertThrows(IllegalArgumentException.class, () -> cfg.withVersion("version-key", -1, null)); + assertThrows(IllegalArgumentException.class, () -> cfg.withVersion("version-key", -1, null)); } @Test - void testWithTooNewVersion() { + void testLoadWithTooNewVersion() { SongodaYamlConfig cfg = new SongodaYamlConfig(this.cfg.toFile()) .withVersion(1); - Assertions.assertThrows(IllegalStateException.class, () -> cfg.load(new StringReader("version: 10\n"))); + assertThrows(IllegalStateException.class, () -> cfg.load(new StringReader("version: 10\n"))); } @Test @@ -116,6 +114,14 @@ class SongodaYamlConfigTest { assertFalse(cfg.upgradeOldConfigVersion()); } + @Test + void testWithNewerVersion() { + SongodaYamlConfig cfg = new SongodaYamlConfig(this.cfg.toFile()) + .withVersion(5); + + assertThrows(IllegalStateException.class, cfg::upgradeOldConfigVersionByOne); + } + @Test void testWithKeyWithoutConfigEntry() throws IOException { SongodaYamlConfig cfg = new SongodaYamlConfig(this.cfg.toFile()); @@ -136,12 +142,46 @@ class SongodaYamlConfigTest { } @Test - void testDefaultValueAppliedAfterLoadNullValue() { + void testCreateEntryAppliesDefaultValueForNullValue() { SongodaYamlConfig cfg = new SongodaYamlConfig(this.cfg.toFile()); - ConfigEntry entry = new ConfigEntry(cfg, "key", "value"); + ConfigEntry entry = cfg.createEntry("key", "value"); cfg.init(); assertEquals("value", entry.get()); } + + @Test + void testCreateDuplicateEntry() { + SongodaYamlConfig cfg = new SongodaYamlConfig(this.cfg.toFile()); + ConfigEntry entry = cfg.createEntry("key", null); + + assertThrows(IllegalArgumentException.class, () -> cfg.createEntry("key", "other-value")); + + assertNull(entry.get()); + } + + @Test + void testReadOnlyEntry() { + SongodaYamlConfig cfg = new SongodaYamlConfig(this.cfg.toFile()); + ConfigEntry entry = cfg.createEntry("key", "default-value"); + ConfigEntry readOnlyConfigEntry = cfg.getReadEntry("key"); + + assertThrows(UnsupportedOperationException.class, () -> readOnlyConfigEntry.set("new-value")); + assertEquals("default-value", entry.get()); + + assertThrows(UnsupportedOperationException.class, () -> readOnlyConfigEntry.setDefaultValue("new-default-value")); + assertEquals("default-value", entry.get()); + + assertThrows(UnsupportedOperationException.class, () -> readOnlyConfigEntry.withComment("test-comment")); + assertThrows(UnsupportedOperationException.class, () -> readOnlyConfigEntry.withComment(() -> "test-comment")); + + assertThrows(UnsupportedOperationException.class, () -> readOnlyConfigEntry.withUpgradeStep(10, "new-key")); + assertThrows(UnsupportedOperationException.class, () -> readOnlyConfigEntry.withUpgradeStep(10, "new-key", (o) -> "new-value")); + + assertEquals("default-value", entry.get()); + + entry.set("new-value"); + assertEquals("new-value", readOnlyConfigEntry.get()); + } } diff --git a/Core/src/test/java/com/songoda/core/configuration/songoda/ConfigEntryTest.java b/Core/src/test/java/com/songoda/core/configuration/yaml/YamlConfigEntryTest.java similarity index 72% rename from Core/src/test/java/com/songoda/core/configuration/songoda/ConfigEntryTest.java rename to Core/src/test/java/com/songoda/core/configuration/yaml/YamlConfigEntryTest.java index 240b919b..f9e9dc81 100644 --- a/Core/src/test/java/com/songoda/core/configuration/songoda/ConfigEntryTest.java +++ b/Core/src/test/java/com/songoda/core/configuration/yaml/YamlConfigEntryTest.java @@ -1,6 +1,9 @@ -package com.songoda.core.configuration.songoda; +package com.songoda.core.configuration.yaml; import com.songoda.core.compatibility.CompatibleMaterial; +import com.songoda.core.configuration.ConfigEntry; +import com.songoda.core.configuration.songoda.SongodaYamlConfig; +import org.bukkit.Material; import org.junit.jupiter.api.Test; import java.io.File; @@ -16,11 +19,24 @@ import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -class ConfigEntryTest { +class YamlConfigEntryTest { + @Test + void testGetKey() { + ConfigEntry entry = new YamlConfigEntry(new YamlConfiguration(), "key-1", null); + assertEquals("key-1", entry.getKey()); + } + + @Test + void testGetConfig() { + YamlConfiguration config = new YamlConfiguration(); + ConfigEntry entry = new YamlConfigEntry(config, "key-1", null); + assertSame(config, entry.getConfig()); + } + @Test void testGetDefaultValue() { SongodaYamlConfig cfg = new SongodaYamlConfig(new File("ConfigEntryTest.yml")); - ConfigEntry entry = new ConfigEntry(cfg, "key", "value"); + ConfigEntry entry = cfg.createEntry("key", "value"); assertEquals("value", entry.getDefaultValue()); @@ -31,7 +47,7 @@ class ConfigEntryTest { @Test void testGetOr() { SongodaYamlConfig cfg = new SongodaYamlConfig(new File("ConfigEntryTest.yml")); - ConfigEntry entry = new ConfigEntry(cfg, "key", "value"); + ConfigEntry entry = cfg.createEntry("key", "value"); assertEquals("value", entry.getOr("invalid")); @@ -42,7 +58,7 @@ class ConfigEntryTest { @Test void testGetString() { SongodaYamlConfig cfg = new SongodaYamlConfig(new File("ConfigEntryTest.yml")); - ConfigEntry entry = new ConfigEntry(cfg, "key"); + ConfigEntry entry = cfg.createEntry("key", null); entry.set("value"); assertEquals("value", entry.getString()); @@ -52,8 +68,8 @@ class ConfigEntryTest { entry.set(null); assertNull(entry.getString()); - assertNull(entry.getString(null)); - assertEquals("12", entry.getString("12")); + assertNull(entry.getStringOr(null)); + assertEquals("12", entry.getStringOr("12")); entry.set(10.5); assertEquals("10.5", entry.getString()); @@ -68,7 +84,7 @@ class ConfigEntryTest { @Test void testGetInt() { SongodaYamlConfig cfg = new SongodaYamlConfig(new File("ConfigEntryTest.yml")); - ConfigEntry entry = new ConfigEntry(cfg, "key"); + ConfigEntry entry = cfg.createEntry("key", null); entry.set(1.0); assertEquals(1, entry.getInt()); @@ -84,13 +100,13 @@ class ConfigEntryTest { entry.set(null); assertEquals(0, entry.getInt()); - assertEquals(11, entry.getInt(11)); + assertEquals(11, entry.getIntOr(11)); } @Test void testGetDouble() { SongodaYamlConfig cfg = new SongodaYamlConfig(new File("ConfigEntryTest.yml")); - ConfigEntry entry = new ConfigEntry(cfg, "key"); + ConfigEntry entry = cfg.createEntry("key", null); entry.set(1.0); assertEquals(1.0, entry.getDouble()); @@ -106,13 +122,13 @@ class ConfigEntryTest { entry.set(null); assertEquals(0.0, entry.getDouble()); - assertEquals(11.5, entry.getDouble(11.5)); + assertEquals(11.5, entry.getDoubleOr(11.5)); } @Test void testGetBoolean() { SongodaYamlConfig cfg = new SongodaYamlConfig(new File("ConfigEntryTest.yml")); - ConfigEntry entry = new ConfigEntry(cfg, "key"); + ConfigEntry entry = cfg.createEntry("key", null); entry.set(false); assertFalse(entry.getBoolean()); @@ -134,19 +150,19 @@ class ConfigEntryTest { entry.set(null); assertFalse(entry.getBoolean()); - assertTrue(entry.getBoolean(true)); + assertTrue(entry.getBooleanOr(true)); } @Test void testGetStringList() { SongodaYamlConfig cfg = new SongodaYamlConfig(new File("ConfigEntryTest.yml")); - ConfigEntry entry = new ConfigEntry(cfg, "key"); + ConfigEntry entry = cfg.createEntry("key", null); final List fallbackValue = Collections.unmodifiableList(new LinkedList<>()); entry.set(null); assertNull(entry.getStringList()); - assertSame(fallbackValue, entry.getStringList(fallbackValue)); + assertSame(fallbackValue, entry.getStringListOr(fallbackValue)); entry.set(Collections.singletonList("value")); assertEquals(Collections.singletonList("value"), entry.getStringList()); @@ -161,7 +177,7 @@ class ConfigEntryTest { @Test void testGetMaterial() { SongodaYamlConfig cfg = new SongodaYamlConfig(new File("ConfigEntryTest.yml")); - ConfigEntry entry = new ConfigEntry(cfg, "key"); + ConfigEntry entry = cfg.createEntry("key", null); entry.set("LOG"); assertEquals(CompatibleMaterial.BIRCH_LOG, entry.getMaterial()); @@ -174,13 +190,19 @@ class ConfigEntryTest { entry.set(null); assertNull(entry.getMaterial()); - assertEquals(CompatibleMaterial.ACACIA_BOAT, entry.getMaterial(CompatibleMaterial.ACACIA_BOAT)); + assertEquals(CompatibleMaterial.ACACIA_BOAT, entry.getMaterialOr(CompatibleMaterial.ACACIA_BOAT)); + + entry.set(CompatibleMaterial.GRASS); + assertEquals(CompatibleMaterial.GRASS, entry.getMaterial()); + + entry.set(Material.GRASS); + assertEquals(CompatibleMaterial.GRASS, entry.getMaterial()); } @Test void testInvalidWithUpgradeNull() { SongodaYamlConfig cfg = new SongodaYamlConfig(new File("ConfigEntryTest.yml")); - ConfigEntry entry = new ConfigEntry(cfg, "key", "value"); + ConfigEntry entry = cfg.createEntry("key", "value"); assertThrows(IllegalArgumentException.class, () -> entry.withUpgradeStep(1, null, null)); } @@ -188,28 +210,29 @@ class ConfigEntryTest { @Test void testEqualsAndHashCode() { SongodaYamlConfig cfg = new SongodaYamlConfig(new File("ConfigEntryTest.yml")); - ConfigEntry entry = new ConfigEntry(cfg, "key", "value"); + ConfigEntry entry = cfg.createEntry("key", "value"); assertEquals(entry, entry); assertEquals(entry.hashCode(), entry.hashCode()); - ConfigEntry other = new ConfigEntry(cfg, "key", "value"); + + ConfigEntry other = new YamlConfigEntry(cfg, "key", "value"); assertEquals(entry, other); assertEquals(entry.hashCode(), other.hashCode()); - other = new ConfigEntry(cfg, "key", "value2"); + other = new YamlConfigEntry(cfg, "key", "value2"); assertNotEquals(entry, other); assertNotEquals(entry.hashCode(), other.hashCode()); - other = new ConfigEntry(cfg, "key2", "value"); + other = new YamlConfigEntry(cfg, "key2", "value"); assertNotEquals(entry, other); assertNotEquals(entry.hashCode(), other.hashCode()); - other = new ConfigEntry(cfg, "key", "value2"); + other = new YamlConfigEntry(cfg, "key", "value2"); assertNotEquals(entry, other); assertNotEquals(entry.hashCode(), other.hashCode()); - other = new ConfigEntry(cfg, "key2", "value2"); + other = new YamlConfigEntry(cfg, "key2", "value2"); assertNotEquals(entry, other); assertNotEquals(entry.hashCode(), other.hashCode()); } diff --git a/Core/src/test/java/com/songoda/core/configuration/yaml/YamlConfigurationTest.java b/Core/src/test/java/com/songoda/core/configuration/yaml/YamlConfigurationTest.java index e1d5faf5..de14d931 100644 --- a/Core/src/test/java/com/songoda/core/configuration/yaml/YamlConfigurationTest.java +++ b/Core/src/test/java/com/songoda/core/configuration/yaml/YamlConfigurationTest.java @@ -15,15 +15,7 @@ import java.util.List; import java.util.Map; import java.util.function.Supplier; -import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrowsExactly; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; class YamlConfigurationTest { static final String inputYaml = "foo: bar\n" + @@ -73,7 +65,7 @@ class YamlConfigurationTest { " - 3\n"; @Test - void testYamlParser() { + void testYamlParser() throws IOException { final YamlConfiguration cfg = new YamlConfiguration(); cfg.load(new StringReader(inputYaml)); @@ -104,7 +96,7 @@ class YamlConfigurationTest { } @Test - void testYamlParserWithEmptyFile() { + void testYamlParserWithEmptyFile() throws IOException { final YamlConfiguration cfg = new YamlConfiguration(); cfg.load(new StringReader("")); assertTrue(cfg.getKeys("").isEmpty()); @@ -263,7 +255,7 @@ class YamlConfigurationTest { } @Test - void testGetNonExistingNestedKey() { + void testGetNonExistingNestedKey() throws IOException { final YamlConfiguration cfg = new YamlConfiguration(); cfg.load(new StringReader(inputYaml)); @@ -271,7 +263,7 @@ class YamlConfigurationTest { } @Test - void testGetOrDefault() { + void testGetOrDefault() throws IOException { final YamlConfiguration cfg = new YamlConfiguration(); cfg.load(new StringReader(inputYaml)); @@ -293,7 +285,7 @@ class YamlConfigurationTest { } @Test - void testGetKeys() { + void testGetKeys() throws IOException { final YamlConfiguration cfg = new YamlConfiguration(); cfg.load(new StringReader(inputYaml)); @@ -485,7 +477,7 @@ class YamlConfigurationTest { } @Test - void testReset() { + void testReset() throws IOException { final YamlConfiguration cfg = new YamlConfiguration(); cfg.load(new StringReader(inputYaml)); @@ -501,7 +493,7 @@ class YamlConfigurationTest { } @Test - void testUnset() { + void testUnset() throws IOException { final YamlConfiguration cfg = new YamlConfiguration(); cfg.load(new StringReader(inputYaml)); @@ -533,7 +525,7 @@ class YamlConfigurationTest { } @Test - void testToString() { + void testToString() throws IOException { final YamlConfiguration cfg = new YamlConfiguration(); String firstToString = cfg.toString();