From e2708366160e66f1d04eaabd13ee1082e18c4d88 Mon Sep 17 00:00:00 2001 From: James Date: Fri, 5 Mar 2021 11:40:04 +0000 Subject: [PATCH 01/22] Remove old files --- .../configuration/ConfigurationOptions.java | 95 -- .../configuration/ConfigurationSection.java | 765 --------------- .../InvalidConfigurationException.java | 50 - .../configuration/MemoryConfiguration.java | 93 -- .../MemoryConfigurationOptions.java | 37 - .../common/configuration/MemorySection.java | 882 ------------------ .../configuration/file/FileConfiguration.java | 231 ----- .../file/FileConfigurationOptions.java | 124 --- .../configuration/file/YamlConfiguration.java | 223 ----- .../file/YamlConfigurationOptions.java | 83 -- .../configuration/file/YamlConstructor.java | 40 - .../configuration/file/YamlRepresenter.java | 43 - .../configuration/file/package-info.java | 10 - .../ConfigurationSerializable.java | 39 - .../DelegateDeserialization.java | 27 - .../serialization/SerializableAs.java | 38 - .../serialization/package-info.java | 10 - 17 files changed, 2790 deletions(-) delete mode 100644 common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/ConfigurationOptions.java delete mode 100644 common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/ConfigurationSection.java delete mode 100644 common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/InvalidConfigurationException.java delete mode 100644 common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/MemoryConfiguration.java delete mode 100644 common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/MemoryConfigurationOptions.java delete mode 100644 common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/MemorySection.java delete mode 100644 common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/FileConfiguration.java delete mode 100644 common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/FileConfigurationOptions.java delete mode 100644 common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlConfiguration.java delete mode 100644 common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlConfigurationOptions.java delete mode 100644 common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlConstructor.java delete mode 100644 common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlRepresenter.java delete mode 100644 common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/package-info.java delete mode 100644 common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/ConfigurationSerializable.java delete mode 100644 common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/DelegateDeserialization.java delete mode 100644 common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/SerializableAs.java delete mode 100644 common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/package-info.java diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/ConfigurationOptions.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/ConfigurationOptions.java deleted file mode 100644 index f29e6471..00000000 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/ConfigurationOptions.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration; - -import org.jetbrains.annotations.NotNull; - -/** - * Various settings for controlling the input and output of a - * {@link Configuration} - */ -public class ConfigurationOptions { - private char pathSeparator = '.'; - private boolean copyDefaults = false; - private final Configuration configuration; - - protected ConfigurationOptions(@NotNull Configuration configuration) { - this.configuration = configuration; - } - - /** - * Returns the {@link Configuration} that this object is responsible for. - * - * @return Parent configuration - */ - @NotNull - public Configuration configuration() { - return configuration; - } - - /** - * Gets the char that will be used to separate {@link ConfigurationSection}s - *

- * This value does not affect how the {@link Configuration} is stored, only in - * how you access the data. The default value is '.'. - * - * @return Path separator - */ - public char pathSeparator() { - return pathSeparator; - } - - /** - * Sets the char that will be used to separate {@link ConfigurationSection}s - *

- * This value does not affect how the {@link Configuration} is stored, only in - * how you access the data. The default value is '.'. - * - * @param value Path separator - * @return This object, for chaining - */ - @NotNull - public ConfigurationOptions pathSeparator(char value) { - this.pathSeparator = value; - return this; - } - - /** - * Checks if the {@link Configuration} should copy values from its default - * {@link Configuration} directly. - *

- * If this is true, all values in the default Configuration will be directly - * copied, making it impossible to distinguish between values that were set and - * values that are provided by default. As a result, - * {@link ConfigurationSection#contains(java.lang.String)} will always return - * the same value as {@link ConfigurationSection#isSet(java.lang.String)}. The - * default value is false. - * - * @return Whether or not defaults are directly copied - */ - public boolean copyDefaults() { - return copyDefaults; - } - - /** - * Sets if the {@link Configuration} should copy values from its default - * {@link Configuration} directly. - *

- * If this is true, all values in the default Configuration will be directly - * copied, making it impossible to distinguish between values that were set and - * values that are provided by default. As a result, - * {@link ConfigurationSection#contains(java.lang.String)} will always return - * the same value as {@link ConfigurationSection#isSet(java.lang.String)}. The - * default value is false. - * - * @param value Whether or not defaults are directly copied - * @return This object, for chaining - */ - @NotNull - public ConfigurationOptions copyDefaults(boolean value) { - this.copyDefaults = value; - return this; - } -} diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/ConfigurationSection.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/ConfigurationSection.java deleted file mode 100644 index bde145e0..00000000 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/ConfigurationSection.java +++ /dev/null @@ -1,765 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -import com.dumbdogdiner.stickyapi.common.configuration.serialization.ConfigurationSerializable; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * Represents a section of a {@link Configuration} - */ -public interface ConfigurationSection { - /** - * Gets a set containing all keys in this section. - *

- * If deep is set to true, then this will contain all the keys within any child - * {@link ConfigurationSection}s (and their children, etc). These will be in a - * valid path notation for you to use. - *

- * If deep is set to false, then this will contain only the keys of any direct - * children, and not their own children. - * - * @param deep Whether or not to get a deep list, as opposed to a shallow list. - * @return Set of keys contained within this ConfigurationSection. - */ - @NotNull - public Set getKeys(boolean deep); - - /** - * Gets a Map containing all keys and their values for this section. - *

- * If deep is set to true, then this will contain all the keys and values within - * any child {@link ConfigurationSection}s (and their children, etc). These keys - * will be in a valid path notation for you to use. - *

- * If deep is set to false, then this will contain only the keys and values of - * any direct children, and not their own children. - * - * @param deep Whether or not to get a deep list, as opposed to a shallow list. - * @return Map of keys and values of this section. - */ - @NotNull - public Map getValues(boolean deep); - - /** - * Checks if this {@link ConfigurationSection} contains the given path. - *

- * If the value for the requested path does not exist but a default value has - * been specified, this will return true. - * - * @param path Path to check for existence. - * @return True if this section contains the requested path, either via default - * or being set. - * @throws IllegalArgumentException Thrown when path is null. - */ - public boolean contains(@NotNull String path); - - /** - * Checks if this {@link ConfigurationSection} contains the given path. - *

- * If the value for the requested path does not exist, the boolean parameter of - * true has been specified, a default value for the path exists, this will - * return true. - *

- * If a boolean parameter of false has been specified, true will only be - * returned if there is a set value for the specified path. - * - * @param path Path to check for existence. - * @param ignoreDefault Whether or not to ignore if a default value for the - * specified path exists. - * @return True if this section contains the requested path, or if a default - * value exist and the boolean parameter for this method is true. - * @throws IllegalArgumentException Thrown when path is null. - */ - public boolean contains(@NotNull String path, boolean ignoreDefault); - - /** - * Checks if this {@link ConfigurationSection} has a value set for the given - * path. - *

- * If the value for the requested path does not exist but a default value has - * been specified, this will still return false. - * - * @param path Path to check for existence. - * @return True if this section contains the requested path, regardless of - * having a default. - * @throws IllegalArgumentException Thrown when path is null. - */ - public boolean isSet(@NotNull String path); - - /** - * Gets the path of this {@link ConfigurationSection} from its root - * {@link Configuration} - *

- * For any {@link Configuration} themselves, this will return an empty string. - *

- * If the section is no longer contained within its root for any reason, such as - * being replaced with a different value, this may return null. - *

- * To retrieve the single name of this section, that is, the final part of the - * path returned by this method, you may use {@link #getName()}. - * - * @return Path of this section relative to its root - */ - @Nullable - public String getCurrentPath(); - - /** - * Gets the name of this individual {@link ConfigurationSection}, in the path. - *

- * This will always be the final part of {@link #getCurrentPath()}, unless the - * section is orphaned. - * - * @return Name of this section - */ - @NotNull - public String getName(); - - /** - * Gets the root {@link Configuration} that contains this - * {@link ConfigurationSection} - *

- * For any {@link Configuration} themselves, this will return its own object. - *

- * If the section is no longer contained within its root for any reason, such as - * being replaced with a different value, this may return null. - * - * @return Root configuration containing this section. - */ - @Nullable - public Configuration getRoot(); - - /** - * Gets the parent {@link ConfigurationSection} that directly contains this - * {@link ConfigurationSection}. - *

- * For any {@link Configuration} themselves, this will return null. - *

- * If the section is no longer contained within its parent for any reason, such - * as being replaced with a different value, this may return null. - * - * @return Parent section containing this section. - */ - @Nullable - public ConfigurationSection getParent(); - - /** - * Gets the requested Object by path. - *

- * If the Object does not exist but a default value has been specified, this - * will return the default value. If the Object does not exist and no default - * value was specified, this will return null. - * - * @param path Path of the Object to get. - * @return Requested Object. - */ - @Nullable - public Object get(@NotNull String path); - - /** - * Gets the requested Object by path, returning a default value if not found. - *

- * If the Object does not exist then the specified default value will returned - * regardless of if a default has been identified in the root - * {@link Configuration}. - * - * @param path Path of the Object to get. - * @param def The default value to return if the path is not found. - * @return Requested Object. - */ - @Nullable - public Object get(@NotNull String path, @Nullable Object def); - - /** - * Sets the specified path to the given value. - *

- * If value is null, the entry will be removed. Any existing entry will be - * replaced, regardless of what the new value is. - *

- * Some implementations may have limitations on what you may store. See their - * individual javadocs for details. No implementations should allow you to store - * {@link Configuration}s or {@link ConfigurationSection}s, please use - * {@link #createSection(java.lang.String)} for that. - * - * @param path Path of the object to set. - * @param value New value to set the path to. - */ - public void set(@NotNull String path, @Nullable Object value); - - /** - * Creates an empty {@link ConfigurationSection} at the specified path. - *

- * Any value that was previously set at this path will be overwritten. If the - * previous value was itself a {@link ConfigurationSection}, it will be - * orphaned. - * - * @param path Path to create the section at. - * @return Newly created section - */ - @NotNull - public ConfigurationSection createSection(@NotNull String path); - - /** - * Creates a {@link ConfigurationSection} at the specified path, with specified - * values. - *

- * Any value that was previously set at this path will be overwritten. If the - * previous value was itself a {@link ConfigurationSection}, it will be - * orphaned. - * - * @param path Path to create the section at. - * @param map The values to used. - * @return Newly created section - */ - @NotNull - public ConfigurationSection createSection(@NotNull String path, @NotNull Map map); - - // Primitives - /** - * Gets the requested String by path. - *

- * If the String does not exist but a default value has been specified, this - * will return the default value. If the String does not exist and no default - * value was specified, this will return null. - * - * @param path Path of the String to get. - * @return Requested String. - */ - @Nullable - public String getString(@NotNull String path); - - /** - * Gets the requested String by path, returning a default value if not found. - *

- * If the String does not exist then the specified default value will returned - * regardless of if a default has been identified in the root - * {@link Configuration}. - * - * @param path Path of the String to get. - * @param def The default value to return if the path is not found or is not a - * String. - * @return Requested String. - */ - @Nullable - public String getString(@NotNull String path, @Nullable String def); - - /** - * Checks if the specified path is a String. - *

- * If the path exists but is not a String, this will return false. If the path - * does not exist, this will return false. If the path does not exist but a - * default value has been specified, this will check if that default value is a - * String and return appropriately. - * - * @param path Path of the String to check. - * @return Whether or not the specified path is a String. - */ - public boolean isString(@NotNull String path); - - /** - * Gets the requested int by path. - *

- * If the int does not exist but a default value has been specified, this will - * return the default value. If the int does not exist and no default value was - * specified, this will return 0. - * - * @param path Path of the int to get. - * @return Requested int. - */ - public int getInt(@NotNull String path); - - /** - * Gets the requested int by path, returning a default value if not found. - *

- * If the int does not exist then the specified default value will returned - * regardless of if a default has been identified in the root - * {@link Configuration}. - * - * @param path Path of the int to get. - * @param def The default value to return if the path is not found or is not an - * int. - * @return Requested int. - */ - public int getInt(@NotNull String path, int def); - - /** - * Checks if the specified path is an int. - *

- * If the path exists but is not a int, this will return false. If the path does - * not exist, this will return false. If the path does not exist but a default - * value has been specified, this will check if that default value is a int and - * return appropriately. - * - * @param path Path of the int to check. - * @return Whether or not the specified path is an int. - */ - public boolean isInt(@NotNull String path); - - /** - * Gets the requested boolean by path. - *

- * If the boolean does not exist but a default value has been specified, this - * will return the default value. If the boolean does not exist and no default - * value was specified, this will return false. - * - * @param path Path of the boolean to get. - * @return Requested boolean. - */ - public boolean getBoolean(@NotNull String path); - - /** - * Gets the requested boolean by path, returning a default value if not found. - *

- * If the boolean does not exist then the specified default value will returned - * regardless of if a default has been identified in the root - * {@link Configuration}. - * - * @param path Path of the boolean to get. - * @param def The default value to return if the path is not found or is not a - * boolean. - * @return Requested boolean. - */ - public boolean getBoolean(@NotNull String path, boolean def); - - /** - * Checks if the specified path is a boolean. - *

- * If the path exists but is not a boolean, this will return false. If the path - * does not exist, this will return false. If the path does not exist but a - * default value has been specified, this will check if that default value is a - * boolean and return appropriately. - * - * @param path Path of the boolean to check. - * @return Whether or not the specified path is a boolean. - */ - public boolean isBoolean(@NotNull String path); - - /** - * Gets the requested double by path. - *

- * If the double does not exist but a default value has been specified, this - * will return the default value. If the double does not exist and no default - * value was specified, this will return 0. - * - * @param path Path of the double to get. - * @return Requested double. - */ - public double getDouble(@NotNull String path); - - /** - * Gets the requested double by path, returning a default value if not found. - *

- * If the double does not exist then the specified default value will returned - * regardless of if a default has been identified in the root - * {@link Configuration}. - * - * @param path Path of the double to get. - * @param def The default value to return if the path is not found or is not a - * double. - * @return Requested double. - */ - public double getDouble(@NotNull String path, double def); - - /** - * Checks if the specified path is a double. - *

- * If the path exists but is not a double, this will return false. If the path - * does not exist, this will return false. If the path does not exist but a - * default value has been specified, this will check if that default value is a - * double and return appropriately. - * - * @param path Path of the double to check. - * @return Whether or not the specified path is a double. - */ - public boolean isDouble(@NotNull String path); - - /** - * Gets the requested long by path. - *

- * If the long does not exist but a default value has been specified, this will - * return the default value. If the long does not exist and no default value was - * specified, this will return 0. - * - * @param path Path of the long to get. - * @return Requested long. - */ - public long getLong(@NotNull String path); - - /** - * Gets the requested long by path, returning a default value if not found. - *

- * If the long does not exist then the specified default value will returned - * regardless of if a default has been identified in the root - * {@link Configuration}. - * - * @param path Path of the long to get. - * @param def The default value to return if the path is not found or is not a - * long. - * @return Requested long. - */ - public long getLong(@NotNull String path, long def); - - /** - * Checks if the specified path is a long. - *

- * If the path exists but is not a long, this will return false. If the path - * does not exist, this will return false. If the path does not exist but a - * default value has been specified, this will check if that default value is a - * long and return appropriately. - * - * @param path Path of the long to check. - * @return Whether or not the specified path is a long. - */ - public boolean isLong(@NotNull String path); - - // Java - /** - * Gets the requested List by path. - *

- * If the List does not exist but a default value has been specified, this will - * return the default value. If the List does not exist and no default value was - * specified, this will return null. - * - * @param path Path of the List to get. - * @return Requested List. - */ - @Nullable - public List getList(@NotNull String path); - - /** - * Gets the requested List by path, returning a default value if not found. - *

- * If the List does not exist then the specified default value will returned - * regardless of if a default has been identified in the root - * {@link Configuration}. - * - * @param path Path of the List to get. - * @param def The default value to return if the path is not found or is not a - * List. - * @return Requested List. - */ - @Nullable - public List getList(@NotNull String path, @Nullable List def); - - /** - * Checks if the specified path is a List. - *

- * If the path exists but is not a List, this will return false. If the path - * does not exist, this will return false. If the path does not exist but a - * default value has been specified, this will check if that default value is a - * List and return appropriately. - * - * @param path Path of the List to check. - * @return Whether or not the specified path is a List. - */ - public boolean isList(@NotNull String path); - - /** - * Gets the requested List of String by path. - *

- * If the List does not exist but a default value has been specified, this will - * return the default value. If the List does not exist and no default value was - * specified, this will return an empty List. - *

- * This method will attempt to cast any values into a String if possible, but - * may miss any values out if they are not compatible. - * - * @param path Path of the List to get. - * @return Requested List of String. - */ - @NotNull - public List getStringList(@NotNull String path); - - /** - * Gets the requested List of Integer by path. - *

- * If the List does not exist but a default value has been specified, this will - * return the default value. If the List does not exist and no default value was - * specified, this will return an empty List. - *

- * This method will attempt to cast any values into a Integer if possible, but - * may miss any values out if they are not compatible. - * - * @param path Path of the List to get. - * @return Requested List of Integer. - */ - @NotNull - public List getIntegerList(@NotNull String path); - - /** - * Gets the requested List of Boolean by path. - *

- * If the List does not exist but a default value has been specified, this will - * return the default value. If the List does not exist and no default value was - * specified, this will return an empty List. - *

- * This method will attempt to cast any values into a Boolean if possible, but - * may miss any values out if they are not compatible. - * - * @param path Path of the List to get. - * @return Requested List of Boolean. - */ - @NotNull - public List getBooleanList(@NotNull String path); - - /** - * Gets the requested List of Double by path. - *

- * If the List does not exist but a default value has been specified, this will - * return the default value. If the List does not exist and no default value was - * specified, this will return an empty List. - *

- * This method will attempt to cast any values into a Double if possible, but - * may miss any values out if they are not compatible. - * - * @param path Path of the List to get. - * @return Requested List of Double. - */ - @NotNull - public List getDoubleList(@NotNull String path); - - /** - * Gets the requested List of Float by path. - *

- * If the List does not exist but a default value has been specified, this will - * return the default value. If the List does not exist and no default value was - * specified, this will return an empty List. - *

- * This method will attempt to cast any values into a Float if possible, but may - * miss any values out if they are not compatible. - * - * @param path Path of the List to get. - * @return Requested List of Float. - */ - @NotNull - public List getFloatList(@NotNull String path); - - /** - * Gets the requested List of Long by path. - *

- * If the List does not exist but a default value has been specified, this will - * return the default value. If the List does not exist and no default value was - * specified, this will return an empty List. - *

- * This method will attempt to cast any values into a Long if possible, but may - * miss any values out if they are not compatible. - * - * @param path Path of the List to get. - * @return Requested List of Long. - */ - @NotNull - public List getLongList(@NotNull String path); - - /** - * Gets the requested List of Byte by path. - *

- * If the List does not exist but a default value has been specified, this will - * return the default value. If the List does not exist and no default value was - * specified, this will return an empty List. - *

- * This method will attempt to cast any values into a Byte if possible, but may - * miss any values out if they are not compatible. - * - * @param path Path of the List to get. - * @return Requested List of Byte. - */ - @NotNull - public List getByteList(@NotNull String path); - - /** - * Gets the requested List of Character by path. - *

- * If the List does not exist but a default value has been specified, this will - * return the default value. If the List does not exist and no default value was - * specified, this will return an empty List. - *

- * This method will attempt to cast any values into a Character if possible, but - * may miss any values out if they are not compatible. - * - * @param path Path of the List to get. - * @return Requested List of Character. - */ - @NotNull - public List getCharacterList(@NotNull String path); - - /** - * Gets the requested List of Short by path. - *

- * If the List does not exist but a default value has been specified, this will - * return the default value. If the List does not exist and no default value was - * specified, this will return an empty List. - *

- * This method will attempt to cast any values into a Short if possible, but may - * miss any values out if they are not compatible. - * - * @param path Path of the List to get. - * @return Requested List of Short. - */ - @NotNull - public List getShortList(@NotNull String path); - - /** - * Gets the requested List of Maps by path. - *

- * If the List does not exist but a default value has been specified, this will - * return the default value. If the List does not exist and no default value was - * specified, this will return an empty List. - *

- * This method will attempt to cast any values into a Map if possible, but may - * miss any values out if they are not compatible. - * - * @param path Path of the List to get. - * @return Requested List of Maps. - */ - @NotNull - public List> getMapList(@NotNull String path); - - // Bukkit - /** - * Gets the requested object at the given path. - * - * If the Object does not exist but a default value has been specified, this - * will return the default value. If the Object does not exist and no default - * value was specified, this will return null. - * - * Note: For example #getObject(path, String.class) is not - * equivalent to {@link #getString(String) #getString(path)} because - * {@link #getString(String) #getString(path)} converts internally all Objects - * to Strings. However, #getObject(path, Boolean.class) is equivalent to - * {@link #getBoolean(String) #getBoolean(path)} for example. - * - * @param the type of the requested object - * @param path the path to the object. - * @param clazz the type of the requested object - * @return Requested object - */ - @Nullable - public T getObject(@NotNull String path, @NotNull Class clazz); - - /** - * Gets the requested object at the given path, returning a default value if not - * found - * - * If the Object does not exist then the specified default value will returned - * regardless of if a default has been identified in the root - * {@link Configuration}. - * - * Note: For example #getObject(path, String.class, def) is not - * equivalent to {@link #getString(String, String) #getString(path, def)} - * because {@link #getString(String, String) #getString(path, def)} converts - * internally all Objects to Strings. However, #getObject(path, Boolean.class, - * def) is equivalent to {@link #getBoolean(String, boolean) #getBoolean(path, - * def)} for example. - * - * @param the type of the requested object - * @param path the path to the object. - * @param clazz the type of the requested object - * @param def the default object to return if the object is not present at the - * path - * @return Requested object - */ - @Nullable - public T getObject(@NotNull String path, @NotNull Class clazz, @Nullable T def); - - /** - * Gets the requested {@link ConfigurationSerializable} object at the given - * path. - * - * If the Object does not exist but a default value has been specified, this - * will return the default value. If the Object does not exist and no default - * value was specified, this will return null. - * - * @param the type of {@link ConfigurationSerializable} - * @param path the path to the object. - * @param clazz the type of {@link ConfigurationSerializable} - * @return Requested {@link ConfigurationSerializable} object - */ - @Nullable - public T getSerializable(@NotNull String path, @NotNull Class clazz); - - /** - * Gets the requested {@link ConfigurationSerializable} object at the given - * path, returning a default value if not found - * - * If the Object does not exist then the specified default value will returned - * regardless of if a default has been identified in the root - * {@link Configuration}. - * - * @param the type of {@link ConfigurationSerializable} - * @param path the path to the object. - * @param clazz the type of {@link ConfigurationSerializable} - * @param def the default object to return if the object is not present at the - * path - * @return Requested {@link ConfigurationSerializable} object - */ - @Nullable - public T getSerializable(@NotNull String path, @NotNull Class clazz, - @Nullable T def); - - /** - * Gets the requested ConfigurationSection by path. - *

- * If the ConfigurationSection does not exist but a default value has been - * specified, this will return the default value. If the ConfigurationSection - * does not exist and no default value was specified, this will return null. - * - * @param path Path of the ConfigurationSection to get. - * @return Requested ConfigurationSection. - */ - @Nullable - public ConfigurationSection getConfigurationSection(@NotNull String path); - - /** - * Checks if the specified path is a ConfigurationSection. - *

- * If the path exists but is not a ConfigurationSection, this will return false. - * If the path does not exist, this will return false. If the path does not - * exist but a default value has been specified, this will check if that default - * value is a ConfigurationSection and return appropriately. - * - * @param path Path of the ConfigurationSection to check. - * @return Whether or not the specified path is a ConfigurationSection. - */ - public boolean isConfigurationSection(@NotNull String path); - - /** - * Gets the equivalent {@link ConfigurationSection} from the default - * {@link Configuration} defined in {@link #getRoot()}. - *

- * If the root contains no defaults, or the defaults doesn't contain a value for - * this path, or the value at this path is not a {@link ConfigurationSection} - * then this will return null. - * - * @return Equivalent section in root configuration - */ - @Nullable - public ConfigurationSection getDefaultSection(); - - /** - * Sets the default value in the root at the given path as provided. - *

- * If no source {@link Configuration} was provided as a default collection, then - * a new {@link MemoryConfiguration} will be created to hold the new default - * value. - *

- * If value is null, the value will be removed from the default Configuration - * source. - *

- * If the value as returned by {@link #getDefaultSection()} is null, then this - * will create a new section at the path, replacing anything that may have - * existed there previously. - * - * @param path Path of the value to set. - * @param value Value to set the default to. - * @throws IllegalArgumentException Thrown if path is null. - */ - public void addDefault(@NotNull String path, @Nullable Object value); -} diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/InvalidConfigurationException.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/InvalidConfigurationException.java deleted file mode 100644 index 2d755098..00000000 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/InvalidConfigurationException.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration; - -/** - * Exception thrown when attempting to load an invalid {@link Configuration} - */ -@SuppressWarnings("serial") -public class InvalidConfigurationException extends Exception { - - /** - * Creates a new instance of InvalidConfigurationException without a message or - * cause. - */ - public InvalidConfigurationException() { - } - - /** - * Constructs an instance of InvalidConfigurationException with the specified - * message. - * - * @param msg The details of the exception. - */ - public InvalidConfigurationException(String msg) { - super(msg); - } - - /** - * Constructs an instance of InvalidConfigurationException with the specified - * cause. - * - * @param cause The cause of the exception. - */ - public InvalidConfigurationException(Throwable cause) { - super(cause); - } - - /** - * Constructs an instance of InvalidConfigurationException with the specified - * message and cause. - * - * @param cause The cause of the exception. - * @param msg The details of the exception. - */ - public InvalidConfigurationException(String msg, Throwable cause) { - super(msg, cause); - } -} diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/MemoryConfiguration.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/MemoryConfiguration.java deleted file mode 100644 index 88dff822..00000000 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/MemoryConfiguration.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration; - -import java.util.Map; -import org.apache.commons.lang.Validate; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * This is a {@link Configuration} implementation that does not save or load - * from any source, and stores all values in memory only. This is useful for - * temporary Configurations for providing defaults. - */ -public class MemoryConfiguration extends MemorySection implements Configuration { - protected Configuration defaults; - protected MemoryConfigurationOptions options; - - /** - * Creates an empty {@link MemoryConfiguration} with no default values. - */ - public MemoryConfiguration() { - } - - /** - * Creates an empty {@link MemoryConfiguration} using the specified - * {@link Configuration} as a source for all default values. - * - * @param defaults Default value provider - * @throws IllegalArgumentException Thrown if defaults is null - */ - public MemoryConfiguration(@Nullable Configuration defaults) { - this.defaults = defaults; - } - - @Override - public void addDefault(@NotNull String path, @Nullable Object value) { - Validate.notNull(path, "Path may not be null"); - - if (defaults == null) { - defaults = new MemoryConfiguration(); - } - - defaults.set(path, value); - } - - @Override - public void addDefaults(@NotNull Map defaults) { - Validate.notNull(defaults, "Defaults may not be null"); - - for (Map.Entry entry : defaults.entrySet()) { - addDefault(entry.getKey(), entry.getValue()); - } - } - - @Override - public void addDefaults(@NotNull Configuration defaults) { - Validate.notNull(defaults, "Defaults may not be null"); - - addDefaults(defaults.getValues(true)); - } - - @Override - public void setDefaults(@NotNull Configuration defaults) { - Validate.notNull(defaults, "Defaults may not be null"); - - this.defaults = defaults; - } - - @Override - @Nullable - public Configuration getDefaults() { - return defaults; - } - - @Nullable - @Override - public ConfigurationSection getParent() { - return null; - } - - @Override - @NotNull - public MemoryConfigurationOptions options() { - if (options == null) { - options = new MemoryConfigurationOptions(this); - } - - return options; - } -} diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/MemoryConfigurationOptions.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/MemoryConfigurationOptions.java deleted file mode 100644 index 61402e53..00000000 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/MemoryConfigurationOptions.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration; - -import org.jetbrains.annotations.NotNull; - -/** - * Various settings for controlling the input and output of a - * {@link MemoryConfiguration} - */ -public class MemoryConfigurationOptions extends ConfigurationOptions { - protected MemoryConfigurationOptions(@NotNull MemoryConfiguration configuration) { - super(configuration); - } - - @NotNull - @Override - public MemoryConfiguration configuration() { - return (MemoryConfiguration) super.configuration(); - } - - @NotNull - @Override - public MemoryConfigurationOptions copyDefaults(boolean value) { - super.copyDefaults(value); - return this; - } - - @NotNull - @Override - public MemoryConfigurationOptions pathSeparator(char value) { - super.pathSeparator(value); - return this; - } -} diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/MemorySection.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/MemorySection.java deleted file mode 100644 index 523d1911..00000000 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/MemorySection.java +++ /dev/null @@ -1,882 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration; - -import static org.bukkit.util.NumberConversions.toDouble; -import static org.bukkit.util.NumberConversions.toInt; -import static org.bukkit.util.NumberConversions.toLong; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import com.dumbdogdiner.stickyapi.common.configuration.serialization.ConfigurationSerializable; - -import org.apache.commons.lang.Validate; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * A type of {@link ConfigurationSection} that is stored in memory. - */ -public class MemorySection implements ConfigurationSection { - protected final Map map = new LinkedHashMap(); - private final Configuration root; - private final ConfigurationSection parent; - private final String path; - private final String fullPath; - - /** - * Creates an empty MemorySection for use as a root {@link Configuration} - * section. - *

- * Note that calling this without being yourself a {@link Configuration} will - * throw an exception! - * - * @throws IllegalStateException Thrown if this is not a {@link Configuration} - * root. - */ - protected MemorySection() { - if (!(this instanceof Configuration)) { - throw new IllegalStateException("Cannot construct a root MemorySection when not a Configuration"); - } - - this.path = ""; - this.fullPath = ""; - this.parent = null; - this.root = (Configuration) this; - } - - /** - * Creates an empty MemorySection with the specified parent and path. - * - * @param parent Parent section that contains this own section. - * @param path Path that you may access this section from via the root - * {@link Configuration}. - * @throws IllegalArgumentException Thrown is parent or path is null, or if - * parent contains no root Configuration. - */ - protected MemorySection(@NotNull ConfigurationSection parent, @NotNull String path) { - Validate.notNull(parent, "Parent cannot be null"); - Validate.notNull(path, "Path cannot be null"); - - this.path = path; - this.parent = parent; - this.root = parent.getRoot(); - - Validate.notNull(root, "Path cannot be orphaned"); - - this.fullPath = createPath(parent, path); - } - - @Override - @NotNull - public Set getKeys(boolean deep) { - Set result = new LinkedHashSet(); - - Configuration root = getRoot(); - if (root != null && root.options().copyDefaults()) { - ConfigurationSection defaults = getDefaultSection(); - - if (defaults != null) { - result.addAll(defaults.getKeys(deep)); - } - } - - mapChildrenKeys(result, this, deep); - - return result; - } - - @Override - @NotNull - public Map getValues(boolean deep) { - Map result = new LinkedHashMap(); - - Configuration root = getRoot(); - if (root != null && root.options().copyDefaults()) { - ConfigurationSection defaults = getDefaultSection(); - - if (defaults != null) { - result.putAll(defaults.getValues(deep)); - } - } - - mapChildrenValues(result, this, deep); - - return result; - } - - @Override - public boolean contains(@NotNull String path) { - return contains(path, false); - } - - @Override - public boolean contains(@NotNull String path, boolean ignoreDefault) { - return ((ignoreDefault) ? get(path, null) : get(path)) != null; - } - - @Override - public boolean isSet(@NotNull String path) { - Configuration root = getRoot(); - if (root == null) { - return false; - } - if (root.options().copyDefaults()) { - return contains(path); - } - return get(path, null) != null; - } - - @Override - @NotNull - public String getCurrentPath() { - return fullPath; - } - - @Override - @NotNull - public String getName() { - return path; - } - - @Override - @Nullable - public Configuration getRoot() { - return root; - } - - @Override - @Nullable - public ConfigurationSection getParent() { - return parent; - } - - @Override - public void addDefault(@NotNull String path, @Nullable Object value) { - Validate.notNull(path, "Path cannot be null"); - - Configuration root = getRoot(); - if (root == null) { - throw new IllegalStateException("Cannot add default without root"); - } - if (root == this) { - throw new UnsupportedOperationException("Unsupported addDefault(String, Object) implementation"); - } - root.addDefault(createPath(this, path), value); - } - - @Override - @Nullable - public ConfigurationSection getDefaultSection() { - Configuration root = getRoot(); - Configuration defaults = root == null ? null : root.getDefaults(); - - if (defaults != null) { - if (defaults.isConfigurationSection(getCurrentPath())) { - return defaults.getConfigurationSection(getCurrentPath()); - } - } - - return null; - } - - @Override - public void set(@NotNull String path, @Nullable Object value) { - Validate.notEmpty(path, "Cannot set to an empty path"); - - Configuration root = getRoot(); - if (root == null) { - throw new IllegalStateException("Cannot use section without a root"); - } - - final char separator = root.options().pathSeparator(); - // i1 is the leading (higher) index - // i2 is the trailing (lower) index - int i1 = -1, i2; - ConfigurationSection section = this; - while ((i1 = path.indexOf(separator, i2 = i1 + 1)) != -1) { - String node = path.substring(i2, i1); - ConfigurationSection subSection = section.getConfigurationSection(node); - if (subSection == null) { - if (value == null) { - // no need to create missing sub-sections if we want to remove the value: - return; - } - section = section.createSection(node); - } else { - section = subSection; - } - } - - String key = path.substring(i2); - if (section == this) { - if (value == null) { - map.remove(key); - } else { - map.put(key, value); - } - } else { - section.set(key, value); - } - } - - @Override - @Nullable - public Object get(@NotNull String path) { - return get(path, getDefault(path)); - } - - @Override - @Nullable - public Object get(@NotNull String path, @Nullable Object def) { - Validate.notNull(path, "Path cannot be null"); - - if (path.length() == 0) { - return this; - } - - Configuration root = getRoot(); - if (root == null) { - throw new IllegalStateException("Cannot access section without a root"); - } - - final char separator = root.options().pathSeparator(); - // i1 is the leading (higher) index - // i2 is the trailing (lower) index - int i1 = -1, i2; - ConfigurationSection section = this; - while ((i1 = path.indexOf(separator, i2 = i1 + 1)) != -1) { - section = section.getConfigurationSection(path.substring(i2, i1)); - if (section == null) { - return def; - } - } - - String key = path.substring(i2); - if (section == this) { - Object result = map.get(key); - return (result == null) ? def : result; - } - return section.get(key, def); - } - - @Override - @NotNull - public ConfigurationSection createSection(@NotNull String path) { - Validate.notEmpty(path, "Cannot create section at empty path"); - Configuration root = getRoot(); - if (root == null) { - throw new IllegalStateException("Cannot create section without a root"); - } - - final char separator = root.options().pathSeparator(); - // i1 is the leading (higher) index - // i2 is the trailing (lower) index - int i1 = -1, i2; - ConfigurationSection section = this; - while ((i1 = path.indexOf(separator, i2 = i1 + 1)) != -1) { - String node = path.substring(i2, i1); - ConfigurationSection subSection = section.getConfigurationSection(node); - if (subSection == null) { - section = section.createSection(node); - } else { - section = subSection; - } - } - - String key = path.substring(i2); - if (section == this) { - ConfigurationSection result = new MemorySection(this, key); - map.put(key, result); - return result; - } - return section.createSection(key); - } - - @Override - @NotNull - public ConfigurationSection createSection(@NotNull String path, @NotNull Map map) { - ConfigurationSection section = createSection(path); - - for (Map.Entry entry : map.entrySet()) { - if (entry.getValue() instanceof Map) { - section.createSection(entry.getKey().toString(), (Map) entry.getValue()); - } else { - section.set(entry.getKey().toString(), entry.getValue()); - } - } - - return section; - } - - // Primitives - @Override - @Nullable - public String getString(@NotNull String path) { - Object def = getDefault(path); - return getString(path, def != null ? def.toString() : null); - } - - @Override - @Nullable - public String getString(@NotNull String path, @Nullable String def) { - Object val = get(path, def); - return (val != null) ? val.toString() : def; - } - - @Override - public boolean isString(@NotNull String path) { - Object val = get(path); - return val instanceof String; - } - - @Override - public int getInt(@NotNull String path) { - Object def = getDefault(path); - return getInt(path, (def instanceof Number) ? toInt(def) : 0); - } - - @Override - public int getInt(@NotNull String path, int def) { - Object val = get(path, def); - return (val instanceof Number) ? toInt(val) : def; - } - - @Override - public boolean isInt(@NotNull String path) { - Object val = get(path); - return val instanceof Integer; - } - - @Override - public boolean getBoolean(@NotNull String path) { - Object def = getDefault(path); - return getBoolean(path, (def instanceof Boolean) ? (Boolean) def : false); - } - - @Override - public boolean getBoolean(@NotNull String path, boolean def) { - Object val = get(path, def); - return (val instanceof Boolean) ? (Boolean) val : def; - } - - @Override - public boolean isBoolean(@NotNull String path) { - Object val = get(path); - return val instanceof Boolean; - } - - @Override - public double getDouble(@NotNull String path) { - Object def = getDefault(path); - return getDouble(path, (def instanceof Number) ? toDouble(def) : 0); - } - - @Override - public double getDouble(@NotNull String path, double def) { - Object val = get(path, def); - return (val instanceof Number) ? toDouble(val) : def; - } - - @Override - public boolean isDouble(@NotNull String path) { - Object val = get(path); - return val instanceof Double; - } - - @Override - public long getLong(@NotNull String path) { - Object def = getDefault(path); - return getLong(path, (def instanceof Number) ? toLong(def) : 0); - } - - @Override - public long getLong(@NotNull String path, long def) { - Object val = get(path, def); - return (val instanceof Number) ? toLong(val) : def; - } - - @Override - public boolean isLong(@NotNull String path) { - Object val = get(path); - return val instanceof Long; - } - - // Java - @Override - @Nullable - public List getList(@NotNull String path) { - Object def = getDefault(path); - return getList(path, (def instanceof List) ? (List) def : null); - } - - @Override - @Nullable - public List getList(@NotNull String path, @Nullable List def) { - Object val = get(path, def); - return (List) ((val instanceof List) ? val : def); - } - - @Override - public boolean isList(@NotNull String path) { - Object val = get(path); - return val instanceof List; - } - - @Override - @NotNull - public List getStringList(@NotNull String path) { - List list = getList(path); - - if (list == null) { - return new ArrayList(0); - } - - List result = new ArrayList(); - - for (Object object : list) { - if ((object instanceof String) || (isPrimitiveWrapper(object))) { - result.add(String.valueOf(object)); - } - } - - return result; - } - - @Override - @NotNull - public List getIntegerList(@NotNull String path) { - List list = getList(path); - - if (list == null) { - return new ArrayList(0); - } - - List result = new ArrayList(); - - for (Object object : list) { - if (object instanceof Integer) { - result.add((Integer) object); - } else if (object instanceof String) { - try { - result.add(Integer.valueOf((String) object)); - } catch (Exception ex) { - } - } else if (object instanceof Character) { - result.add((int) ((Character) object).charValue()); - } else if (object instanceof Number) { - result.add(((Number) object).intValue()); - } - } - - return result; - } - - @Override - @NotNull - public List getBooleanList(@NotNull String path) { - List list = getList(path); - - if (list == null) { - return new ArrayList(0); - } - - List result = new ArrayList(); - - for (Object object : list) { - if (object instanceof Boolean) { - result.add((Boolean) object); - } else if (object instanceof String) { - if (Boolean.TRUE.toString().equals(object)) { - result.add(true); - } else if (Boolean.FALSE.toString().equals(object)) { - result.add(false); - } - } - } - - return result; - } - - @Override - @NotNull - public List getDoubleList(@NotNull String path) { - List list = getList(path); - - if (list == null) { - return new ArrayList(0); - } - - List result = new ArrayList(); - - for (Object object : list) { - if (object instanceof Double) { - result.add((Double) object); - } else if (object instanceof String) { - try { - result.add(Double.valueOf((String) object)); - } catch (Exception ex) { - } - } else if (object instanceof Character) { - result.add((double) ((Character) object).charValue()); - } else if (object instanceof Number) { - result.add(((Number) object).doubleValue()); - } - } - - return result; - } - - @Override - @NotNull - public List getFloatList(@NotNull String path) { - List list = getList(path); - - if (list == null) { - return new ArrayList(0); - } - - List result = new ArrayList(); - - for (Object object : list) { - if (object instanceof Float) { - result.add((Float) object); - } else if (object instanceof String) { - try { - result.add(Float.valueOf((String) object)); - } catch (Exception ex) { - } - } else if (object instanceof Character) { - result.add((float) ((Character) object).charValue()); - } else if (object instanceof Number) { - result.add(((Number) object).floatValue()); - } - } - - return result; - } - - @Override - @NotNull - public List getLongList(@NotNull String path) { - List list = getList(path); - - if (list == null) { - return new ArrayList(0); - } - - List result = new ArrayList(); - - for (Object object : list) { - if (object instanceof Long) { - result.add((Long) object); - } else if (object instanceof String) { - try { - result.add(Long.valueOf((String) object)); - } catch (Exception ex) { - } - } else if (object instanceof Character) { - result.add((long) ((Character) object).charValue()); - } else if (object instanceof Number) { - result.add(((Number) object).longValue()); - } - } - - return result; - } - - @Override - @NotNull - public List getByteList(@NotNull String path) { - List list = getList(path); - - if (list == null) { - return new ArrayList(0); - } - - List result = new ArrayList(); - - for (Object object : list) { - if (object instanceof Byte) { - result.add((Byte) object); - } else if (object instanceof String) { - try { - result.add(Byte.valueOf((String) object)); - } catch (Exception ex) { - } - } else if (object instanceof Character) { - result.add((byte) ((Character) object).charValue()); - } else if (object instanceof Number) { - result.add(((Number) object).byteValue()); - } - } - - return result; - } - - @Override - @NotNull - public List getCharacterList(@NotNull String path) { - List list = getList(path); - - if (list == null) { - return new ArrayList(0); - } - - List result = new ArrayList(); - - for (Object object : list) { - if (object instanceof Character) { - result.add((Character) object); - } else if (object instanceof String) { - String str = (String) object; - - if (str.length() == 1) { - result.add(str.charAt(0)); - } - } else if (object instanceof Number) { - result.add((char) ((Number) object).intValue()); - } - } - - return result; - } - - @Override - @NotNull - public List getShortList(@NotNull String path) { - List list = getList(path); - - if (list == null) { - return new ArrayList(0); - } - - List result = new ArrayList(); - - for (Object object : list) { - if (object instanceof Short) { - result.add((Short) object); - } else if (object instanceof String) { - try { - result.add(Short.valueOf((String) object)); - } catch (Exception ex) { - } - } else if (object instanceof Character) { - result.add((short) ((Character) object).charValue()); - } else if (object instanceof Number) { - result.add(((Number) object).shortValue()); - } - } - - return result; - } - - @Override - @NotNull - public List> getMapList(@NotNull String path) { - List list = getList(path); - List> result = new ArrayList>(); - - if (list == null) { - return result; - } - - for (Object object : list) { - if (object instanceof Map) { - result.add((Map) object); - } - } - - return result; - } - - // Bukkit - @Nullable - @Override - public T getObject(@NotNull String path, @NotNull Class clazz) { - Validate.notNull(clazz, "Class cannot be null"); - Object def = getDefault(path); - return getObject(path, clazz, (def != null && clazz.isInstance(def)) ? clazz.cast(def) : null); - } - - @Nullable - @Override - public T getObject(@NotNull String path, @NotNull Class clazz, @Nullable T def) { - Validate.notNull(clazz, "Class cannot be null"); - Object val = get(path, def); - return (val != null && clazz.isInstance(val)) ? clazz.cast(val) : def; - } - - @Nullable - @Override - public T getSerializable(@NotNull String path, @NotNull Class clazz) { - return getObject(path, clazz); - } - - @Nullable - @Override - public T getSerializable(@NotNull String path, @NotNull Class clazz, - @Nullable T def) { - return getObject(path, clazz, def); - } - - @Override - @Nullable - public ConfigurationSection getConfigurationSection(@NotNull String path) { - Object val = get(path, null); - if (val != null) { - return (val instanceof ConfigurationSection) ? (ConfigurationSection) val : null; - } - - val = get(path, getDefault(path)); - return (val instanceof ConfigurationSection) ? createSection(path) : null; - } - - @Override - public boolean isConfigurationSection(@NotNull String path) { - Object val = get(path); - return val instanceof ConfigurationSection; - } - - protected boolean isPrimitiveWrapper(@Nullable Object input) { - return input instanceof Integer || input instanceof Boolean || input instanceof Character - || input instanceof Byte || input instanceof Short || input instanceof Double || input instanceof Long - || input instanceof Float; - } - - @Nullable - protected Object getDefault(@NotNull String path) { - Validate.notNull(path, "Path cannot be null"); - - Configuration root = getRoot(); - Configuration defaults = root == null ? null : root.getDefaults(); - return (defaults == null) ? null : defaults.get(createPath(this, path)); - } - - protected void mapChildrenKeys(@NotNull Set output, @NotNull ConfigurationSection section, boolean deep) { - if (section instanceof MemorySection) { - MemorySection sec = (MemorySection) section; - - for (Map.Entry entry : sec.map.entrySet()) { - output.add(createPath(section, entry.getKey(), this)); - - if ((deep) && (entry.getValue() instanceof ConfigurationSection)) { - ConfigurationSection subsection = (ConfigurationSection) entry.getValue(); - mapChildrenKeys(output, subsection, deep); - } - } - } else { - Set keys = section.getKeys(deep); - - for (String key : keys) { - output.add(createPath(section, key, this)); - } - } - } - - protected void mapChildrenValues(@NotNull Map output, @NotNull ConfigurationSection section, - boolean deep) { - if (section instanceof MemorySection) { - MemorySection sec = (MemorySection) section; - - for (Map.Entry entry : sec.map.entrySet()) { - // Because of the copyDefaults call potentially copying out of order, we must - // remove and then add in our saved order - // This means that default values we haven't set end up getting placed first - // See SPIGOT-4558 for an example using spigot.yml - watch subsections move - // around to default order - String childPath = createPath(section, entry.getKey(), this); - output.remove(childPath); - output.put(childPath, entry.getValue()); - - if (entry.getValue() instanceof ConfigurationSection) { - if (deep) { - mapChildrenValues(output, (ConfigurationSection) entry.getValue(), deep); - } - } - } - } else { - Map values = section.getValues(deep); - - for (Map.Entry entry : values.entrySet()) { - output.put(createPath(section, entry.getKey(), this), entry.getValue()); - } - } - } - - /** - * Creates a full path to the given {@link ConfigurationSection} from its root - * {@link Configuration}. - *

- * You may use this method for any given {@link ConfigurationSection}, not only - * {@link MemorySection}. - * - * @param section Section to create a path for. - * @param key Name of the specified section. - * @return Full path of the section from its root. - */ - @NotNull - public static String createPath(@NotNull ConfigurationSection section, @Nullable String key) { - return createPath(section, key, (section == null) ? null : section.getRoot()); - } - - /** - * Creates a relative path to the given {@link ConfigurationSection} from the - * given relative section. - *

- * You may use this method for any given {@link ConfigurationSection}, not only - * {@link MemorySection}. - * - * @param section Section to create a path for. - * @param key Name of the specified section. - * @param relativeTo Section to create the path relative to. - * @return Full path of the section from its root. - */ - @NotNull - public static String createPath(@NotNull ConfigurationSection section, @Nullable String key, - @Nullable ConfigurationSection relativeTo) { - Validate.notNull(section, "Cannot create path without a section"); - Configuration root = section.getRoot(); - if (root == null) { - throw new IllegalStateException("Cannot create path without a root"); - } - char separator = root.options().pathSeparator(); - - StringBuilder builder = new StringBuilder(); - if (section != null) { - for (ConfigurationSection parent = section; (parent != null) - && (parent != relativeTo); parent = parent.getParent()) { - if (builder.length() > 0) { - builder.insert(0, separator); - } - - builder.insert(0, parent.getName()); - } - } - - if ((key != null) && (key.length() > 0)) { - if (builder.length() > 0) { - builder.append(separator); - } - - builder.append(key); - } - - return builder.toString(); - } - - @Override - public String toString() { - Configuration root = getRoot(); - return new StringBuilder().append(getClass().getSimpleName()).append("[path='").append(getCurrentPath()) - .append("', root='").append(root == null ? null : root.getClass().getSimpleName()).append("']") - .toString(); - } -} diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/FileConfiguration.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/FileConfiguration.java deleted file mode 100644 index 07cf5928..00000000 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/FileConfiguration.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration.file; - -import com.google.common.base.Charsets; -import com.google.common.io.Files; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.Reader; -import java.io.Writer; -import org.apache.commons.lang.Validate; -import com.dumbdogdiner.stickyapi.common.configuration.Configuration; -import com.dumbdogdiner.stickyapi.common.configuration.InvalidConfigurationException; -import com.dumbdogdiner.stickyapi.common.configuration.MemoryConfiguration; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * This is a base class for all File based implementations of - * {@link Configuration} - */ -public abstract class FileConfiguration extends MemoryConfiguration { - - /** - * Creates an empty {@link FileConfiguration} with no default values. - */ - public FileConfiguration() { - super(); - } - - /** - * Creates an empty {@link FileConfiguration} using the specified - * {@link Configuration} as a source for all default values. - * - * @param defaults Default value provider - */ - public FileConfiguration(@Nullable Configuration defaults) { - super(defaults); - } - - /** - * Saves this {@link FileConfiguration} to the specified location. - *

- * If the file does not exist, it will be created. If already exists, it will be - * overwritten. If it cannot be overwritten or created, an exception will be - * thrown. - *

- * This method will save using the system default encoding, or possibly using - * UTF8. - * - * @param file File to save to. - * @throws IOException Thrown when the given file cannot be written - * to for any reason. - * @throws IllegalArgumentException Thrown when file is null. - */ - public void save(@NotNull File file) throws IOException { - Validate.notNull(file, "File cannot be null"); - - Files.createParentDirs(file); - - String data = saveToString(); - - Writer writer = new OutputStreamWriter(new FileOutputStream(file), Charsets.UTF_8); - - try { - writer.write(data); - } finally { - writer.close(); - } - } - - /** - * Saves this {@link FileConfiguration} to the specified location. - *

- * If the file does not exist, it will be created. If already exists, it will be - * overwritten. If it cannot be overwritten or created, an exception will be - * thrown. - *

- * This method will save using the system default encoding, or possibly using - * UTF8. - * - * @param file File to save to. - * @throws IOException Thrown when the given file cannot be written - * to for any reason. - * @throws IllegalArgumentException Thrown when file is null. - */ - public void save(@NotNull String file) throws IOException { - Validate.notNull(file, "File cannot be null"); - - save(new File(file)); - } - - /** - * Saves this {@link FileConfiguration} to a string, and returns it. - * - * @return String containing this configuration. - */ - @NotNull - public abstract String saveToString(); - - /** - * Loads this {@link FileConfiguration} from the specified location. - *

- * All the values contained within this configuration will be removed, leaving - * only settings and defaults, and the new values will be loaded from the given - * file. - *

- * If the file cannot be loaded for any reason, an exception will be thrown. - * - * @param file File to load from. - * @throws FileNotFoundException Thrown when the given file cannot be - * opened. - * @throws IOException Thrown when the given file cannot be - * read. - * @throws InvalidConfigurationException Thrown when the given file is not a - * valid Configuration. - * @throws IllegalArgumentException Thrown when file is null. - */ - public void load(@NotNull File file) throws FileNotFoundException, IOException, InvalidConfigurationException { - Validate.notNull(file, "File cannot be null"); - - final FileInputStream stream = new FileInputStream(file); - - load(new InputStreamReader(stream, Charsets.UTF_8)); - } - - /** - * Loads this {@link FileConfiguration} from the specified reader. - *

- * All the values contained within this configuration will be removed, leaving - * only settings and defaults, and the new values will be loaded from the given - * stream. - * - * @param reader the reader to load from - * @throws IOException thrown when underlying reader throws an - * IOException - * @throws InvalidConfigurationException thrown when the reader does not - * represent a valid Configuration - * @throws IllegalArgumentException thrown when reader is null - */ - public void load(@NotNull Reader reader) throws IOException, InvalidConfigurationException { - BufferedReader input = reader instanceof BufferedReader ? (BufferedReader) reader : new BufferedReader(reader); - - StringBuilder builder = new StringBuilder(); - - try { - String line; - - while ((line = input.readLine()) != null) { - builder.append(line); - builder.append('\n'); - } - } finally { - input.close(); - } - - loadFromString(builder.toString()); - } - - /** - * Loads this {@link FileConfiguration} from the specified location. - *

- * All the values contained within this configuration will be removed, leaving - * only settings and defaults, and the new values will be loaded from the given - * file. - *

- * If the file cannot be loaded for any reason, an exception will be thrown. - * - * @param file File to load from. - * @throws FileNotFoundException Thrown when the given file cannot be - * opened. - * @throws IOException Thrown when the given file cannot be - * read. - * @throws InvalidConfigurationException Thrown when the given file is not a - * valid Configuration. - * @throws IllegalArgumentException Thrown when file is null. - */ - public void load(@NotNull String file) throws FileNotFoundException, IOException, InvalidConfigurationException { - Validate.notNull(file, "File cannot be null"); - - load(new File(file)); - } - - /** - * Loads this {@link FileConfiguration} from the specified string, as opposed to - * from file. - *

- * All the values contained within this configuration will be removed, leaving - * only settings and defaults, and the new values will be loaded from the given - * string. - *

- * If the string is invalid in any way, an exception will be thrown. - * - * @param contents Contents of a Configuration to load. - * @throws InvalidConfigurationException Thrown if the specified string is - * invalid. - * @throws IllegalArgumentException Thrown if contents is null. - */ - public abstract void loadFromString(@NotNull String contents) throws InvalidConfigurationException; - - /** - * Compiles the header for this {@link FileConfiguration} and returns the - * result. - *

- * This will use the header from {@link #options()} -> - * {@link FileConfigurationOptions#header()}, respecting the rules of - * {@link FileConfigurationOptions#copyHeader()} if set. - * - * @return Compiled header - */ - @NotNull - protected abstract String buildHeader(); - - @NotNull - @Override - public FileConfigurationOptions options() { - if (options == null) { - options = new FileConfigurationOptions(this); - } - - return (FileConfigurationOptions) options; - } -} diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/FileConfigurationOptions.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/FileConfigurationOptions.java deleted file mode 100644 index 48e126ea..00000000 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/FileConfigurationOptions.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration.file; - -import com.dumbdogdiner.stickyapi.common.configuration.MemoryConfiguration; -import com.dumbdogdiner.stickyapi.common.configuration.MemoryConfigurationOptions; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * Various settings for controlling the input and output of a - * {@link FileConfiguration} - */ -public class FileConfigurationOptions extends MemoryConfigurationOptions { - private String header = null; - private boolean copyHeader = true; - - protected FileConfigurationOptions(@NotNull MemoryConfiguration configuration) { - super(configuration); - } - - @NotNull - @Override - public FileConfiguration configuration() { - return (FileConfiguration) super.configuration(); - } - - @NotNull - @Override - public FileConfigurationOptions copyDefaults(boolean value) { - super.copyDefaults(value); - return this; - } - - @NotNull - @Override - public FileConfigurationOptions pathSeparator(char value) { - super.pathSeparator(value); - return this; - } - - /** - * Gets the header that will be applied to the top of the saved output. - *

- * This header will be commented out and applied directly at the top of the - * generated output of the {@link FileConfiguration}. It is not required to - * include a newline at the end of the header as it will automatically be - * applied, but you may include one if you wish for extra spacing. - *

- * Null is a valid value which will indicate that no header is to be applied. - * The default value is null. - * - * @return Header - */ - @Nullable - public String header() { - return header; - } - - /** - * Sets the header that will be applied to the top of the saved output. - *

- * This header will be commented out and applied directly at the top of the - * generated output of the {@link FileConfiguration}. It is not required to - * include a newline at the end of the header as it will automatically be - * applied, but you may include one if you wish for extra spacing. - *

- * Null is a valid value which will indicate that no header is to be applied. - * - * @param value New header - * @return This object, for chaining - */ - @NotNull - public FileConfigurationOptions header(@Nullable String value) { - this.header = value; - return this; - } - - /** - * Gets whether or not the header should be copied from a default source. - *

- * If this is true, if a default {@link FileConfiguration} is passed to - * {@link FileConfiguration#setDefaults(com.dumbdogdiner.stickyapi.common.configuration.Configuration)} - * then upon saving it will use the header from that config, instead of the one - * provided here. - *

- * If no default is set on the configuration, or the default is not of type - * FileConfiguration, or that config has no header ({@link #header()} returns - * null) then the header specified in this configuration will be used. - *

- * Defaults to true. - * - * @return Whether or not to copy the header - */ - public boolean copyHeader() { - return copyHeader; - } - - /** - * Sets whether or not the header should be copied from a default source. - *

- * If this is true, if a default {@link FileConfiguration} is passed to - * {@link FileConfiguration#setDefaults(com.dumbdogdiner.stickyapi.common.configuration.Configuration)} - * then upon saving it will use the header from that config, instead of the one - * provided here. - *

- * If no default is set on the configuration, or the default is not of type - * FileConfiguration, or that config has no header ({@link #header()} returns - * null) then the header specified in this configuration will be used. - *

- * Defaults to true. - * - * @param value Whether or not to copy the header - * @return This object, for chaining - */ - @NotNull - public FileConfigurationOptions copyHeader(boolean value) { - copyHeader = value; - - return this; - } -} diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlConfiguration.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlConfiguration.java deleted file mode 100644 index 5d5cfe27..00000000 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlConfiguration.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration.file; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.Reader; -import java.util.Map; -import java.util.logging.Level; -import org.apache.commons.lang.Validate; -import org.bukkit.Bukkit; -import com.dumbdogdiner.stickyapi.common.configuration.Configuration; -import com.dumbdogdiner.stickyapi.common.configuration.ConfigurationSection; -import com.dumbdogdiner.stickyapi.common.configuration.InvalidConfigurationException; -import org.jetbrains.annotations.NotNull; -import org.yaml.snakeyaml.DumperOptions; -import org.yaml.snakeyaml.Yaml; -import org.yaml.snakeyaml.error.YAMLException; -import org.yaml.snakeyaml.representer.Representer; - -/** - * An implementation of {@link Configuration} which saves all files in Yaml. - * Note that this implementation is not synchronized. - */ -public class YamlConfiguration extends FileConfiguration { - protected static final String COMMENT_PREFIX = "# "; - protected static final String BLANK_CONFIG = "{}\n"; - private final DumperOptions yamlOptions = new DumperOptions(); - private final Representer yamlRepresenter = new YamlRepresenter(); - private final Yaml yaml = new Yaml(new YamlConstructor(), yamlRepresenter, yamlOptions); - - @NotNull - @Override - public String saveToString() { - yamlOptions.setIndent(options().indent()); - yamlOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); - yamlRepresenter.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); - - String header = buildHeader(); - String dump = yaml.dump(getValues(false)); - - if (dump.equals(BLANK_CONFIG)) { - dump = ""; - } - - return header + dump; - } - - @Override - public void loadFromString(@NotNull String contents) throws InvalidConfigurationException { - Validate.notNull(contents, "Contents cannot be null"); - - Map input; - try { - input = (Map) yaml.load(contents); - } catch (YAMLException e) { - throw new InvalidConfigurationException(e); - } catch (ClassCastException e) { - throw new InvalidConfigurationException("Top level is not a Map."); - } - - String header = parseHeader(contents); - if (header.length() > 0) { - options().header(header); - } - - if (input != null) { - convertMapsToSections(input, this); - } - } - - protected void convertMapsToSections(@NotNull Map input, @NotNull ConfigurationSection section) { - for (Map.Entry entry : input.entrySet()) { - String key = entry.getKey().toString(); - Object value = entry.getValue(); - - if (value instanceof Map) { - convertMapsToSections((Map) value, section.createSection(key)); - } else { - section.set(key, value); - } - } - } - - @NotNull - protected String parseHeader(@NotNull String input) { - String[] lines = input.split("\r?\n", -1); - StringBuilder result = new StringBuilder(); - boolean readingHeader = true; - boolean foundHeader = false; - - for (int i = 0; (i < lines.length) && (readingHeader); i++) { - String line = lines[i]; - - if (line.startsWith(COMMENT_PREFIX)) { - if (i > 0) { - result.append("\n"); - } - - if (line.length() > COMMENT_PREFIX.length()) { - result.append(line.substring(COMMENT_PREFIX.length())); - } - - foundHeader = true; - } else if ((foundHeader) && (line.length() == 0)) { - result.append("\n"); - } else if (foundHeader) { - readingHeader = false; - } - } - - return result.toString(); - } - - @NotNull - @Override - protected String buildHeader() { - String header = options().header(); - - if (options().copyHeader()) { - Configuration def = getDefaults(); - - if ((def != null) && (def instanceof FileConfiguration)) { - FileConfiguration filedefaults = (FileConfiguration) def; - String defaultsHeader = filedefaults.buildHeader(); - - if ((defaultsHeader != null) && (defaultsHeader.length() > 0)) { - return defaultsHeader; - } - } - } - - if (header == null) { - return ""; - } - - StringBuilder builder = new StringBuilder(); - String[] lines = header.split("\r?\n", -1); - boolean startedHeader = false; - - for (int i = lines.length - 1; i >= 0; i--) { - builder.insert(0, "\n"); - - if ((startedHeader) || (lines[i].length() != 0)) { - builder.insert(0, lines[i]); - builder.insert(0, COMMENT_PREFIX); - startedHeader = true; - } - } - - return builder.toString(); - } - - @NotNull - @Override - public YamlConfigurationOptions options() { - if (options == null) { - options = new YamlConfigurationOptions(this); - } - - return (YamlConfigurationOptions) options; - } - - /** - * Creates a new {@link YamlConfiguration}, loading from the given file. - *

- * Any errors loading the Configuration will be logged and then ignored. If the - * specified input is not a valid config, a blank config will be returned. - *

- * The encoding used may follow the system dependent default. - * - * @param file Input file - * @return Resulting configuration - * @throws IllegalArgumentException Thrown if file is null - */ - @NotNull - public static YamlConfiguration loadConfiguration(@NotNull File file) { - Validate.notNull(file, "File cannot be null"); - - YamlConfiguration config = new YamlConfiguration(); - - try { - config.load(file); - } catch (FileNotFoundException ex) { - } catch (IOException ex) { - Bukkit.getLogger().log(Level.SEVERE, "Cannot load " + file, ex); - } catch (InvalidConfigurationException ex) { - Bukkit.getLogger().log(Level.SEVERE, "Cannot load " + file, ex); - } - - return config; - } - - /** - * Creates a new {@link YamlConfiguration}, loading from the given reader. - *

- * Any errors loading the Configuration will be logged and then ignored. If the - * specified input is not a valid config, a blank config will be returned. - * - * @param reader input - * @return resulting configuration - * @throws IllegalArgumentException Thrown if stream is null - */ - @NotNull - public static YamlConfiguration loadConfiguration(@NotNull Reader reader) { - Validate.notNull(reader, "Stream cannot be null"); - - YamlConfiguration config = new YamlConfiguration(); - - try { - config.load(reader); - } catch (IOException ex) { - Bukkit.getLogger().log(Level.SEVERE, "Cannot load configuration from stream", ex); - } catch (InvalidConfigurationException ex) { - Bukkit.getLogger().log(Level.SEVERE, "Cannot load configuration from stream", ex); - } - - return config; - } -} diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlConfigurationOptions.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlConfigurationOptions.java deleted file mode 100644 index dcf6621f..00000000 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlConfigurationOptions.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration.file; - -import org.apache.commons.lang.Validate; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * Various settings for controlling the input and output of a - * {@link YamlConfiguration} - */ -public class YamlConfigurationOptions extends FileConfigurationOptions { - private int indent = 2; - - protected YamlConfigurationOptions(@NotNull YamlConfiguration configuration) { - super(configuration); - } - - @NotNull - @Override - public YamlConfiguration configuration() { - return (YamlConfiguration) super.configuration(); - } - - @NotNull - @Override - public YamlConfigurationOptions copyDefaults(boolean value) { - super.copyDefaults(value); - return this; - } - - @NotNull - @Override - public YamlConfigurationOptions pathSeparator(char value) { - super.pathSeparator(value); - return this; - } - - @NotNull - @Override - public YamlConfigurationOptions header(@Nullable String value) { - super.header(value); - return this; - } - - @NotNull - @Override - public YamlConfigurationOptions copyHeader(boolean value) { - super.copyHeader(value); - return this; - } - - /** - * Gets how much spaces should be used to indent each line. - *

- * The minimum value this may be is 2, and the maximum is 9. - * - * @return How much to indent by - */ - public int indent() { - return indent; - } - - /** - * Sets how much spaces should be used to indent each line. - *

- * The minimum value this may be is 2, and the maximum is 9. - * - * @param value New indent - * @return This object, for chaining - */ - @NotNull - public YamlConfigurationOptions indent(int value) { - Validate.isTrue(value >= 2, "Indent must be at least 2 characters"); - Validate.isTrue(value <= 9, "Indent cannot be greater than 9 characters"); - - this.indent = value; - return this; - } -} diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlConstructor.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlConstructor.java deleted file mode 100644 index 76c5e60e..00000000 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlConstructor.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration.file; - -import java.util.Map; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.yaml.snakeyaml.constructor.SafeConstructor; -import org.yaml.snakeyaml.error.YAMLException; -import org.yaml.snakeyaml.nodes.Node; -import org.yaml.snakeyaml.nodes.Tag; - -public class YamlConstructor extends SafeConstructor { - - public YamlConstructor() { - this.yamlConstructors.put(Tag.MAP, new ConstructCustomObject()); - } - - private class ConstructCustomObject extends ConstructYamlMap { - - @Nullable - @Override - public Object construct(@NotNull Node node) { - if (node.isTwoStepsConstruction()) { - throw new YAMLException("Unexpected referential mapping structure. Node: " + node); - } - - Map raw = (Map) super.construct(node); - - return raw; - } - - @Override - public void construct2ndStep(@NotNull Node node, @NotNull Object object) { - throw new YAMLException("Unexpected referential mapping structure. Node: " + node); - } - } -} diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlRepresenter.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlRepresenter.java deleted file mode 100644 index b4faf714..00000000 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/YamlRepresenter.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration.file; - -import java.util.LinkedHashMap; -import java.util.Map; -import com.dumbdogdiner.stickyapi.common.configuration.ConfigurationSection; -import com.dumbdogdiner.stickyapi.common.configuration.serialization.ConfigurationSerializable; -import org.jetbrains.annotations.NotNull; -import org.yaml.snakeyaml.nodes.Node; -import org.yaml.snakeyaml.representer.Representer; - -public class YamlRepresenter extends Representer { - - public YamlRepresenter() { - this.multiRepresenters.put(ConfigurationSection.class, new RepresentConfigurationSection()); - this.multiRepresenters.put(ConfigurationSerializable.class, new RepresentConfigurationSerializable()); - } - - private class RepresentConfigurationSection extends RepresentMap { - - @NotNull - @Override - public Node representData(@NotNull Object data) { - return super.representData(((ConfigurationSection) data).getValues(false)); - } - } - - private class RepresentConfigurationSerializable extends RepresentMap { - - @NotNull - @Override - public Node representData(@NotNull Object data) { - ConfigurationSerializable serializable = (ConfigurationSerializable) data; - Map values = new LinkedHashMap(); - values.putAll(serializable.serialize()); - - return super.representData(values); - } - } -} diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/package-info.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/package-info.java deleted file mode 100644 index 29ca3ac3..00000000 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/file/package-info.java +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -/** - * Classes dedicated to facilitating - * {@link com.dumbdogdiner.stickyapi.common.configuration.Configuration - * configurations} to be read and stored on the filesystem. - */ -package com.dumbdogdiner.stickyapi.common.configuration.file; diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/ConfigurationSerializable.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/ConfigurationSerializable.java deleted file mode 100644 index 34a25eab..00000000 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/ConfigurationSerializable.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration.serialization; - -import java.util.Map; -import org.jetbrains.annotations.NotNull; - -/** - * Represents an object that may be serialized. - *

- * These objects MUST implement one of the following, in addition to the methods - * as defined by this interface: - *

- * - * @see DelegateDeserialization - * @see SerializableAs - */ -public interface ConfigurationSerializable { - - /** - * Creates a Map representation of this class. - *

- * This class must provide a method to restore this class, as defined in the - * {@link ConfigurationSerializable} interface javadocs. - * - * @return Map containing the current state of this class - */ - @NotNull - public Map serialize(); -} diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/DelegateDeserialization.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/DelegateDeserialization.java deleted file mode 100644 index effc6acf..00000000 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/DelegateDeserialization.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration.serialization; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.jetbrains.annotations.NotNull; - -/** - * Applies to a {@link ConfigurationSerializable} that will delegate all - * deserialization to another {@link ConfigurationSerializable}. - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface DelegateDeserialization { - /** - * Which class should be used as a delegate for this classes deserialization - * - * @return Delegate class - */ - @NotNull - public Class value(); -} diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/SerializableAs.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/SerializableAs.java deleted file mode 100644 index 870d87bc..00000000 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/SerializableAs.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -package com.dumbdogdiner.stickyapi.common.configuration.serialization; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.jetbrains.annotations.NotNull; - -/** - * Represents an "alias" that a {@link ConfigurationSerializable} may be stored - * as. If this is not present on a {@link ConfigurationSerializable} class, it - * will use the fully qualified name of the class. - *

- * This value will be stored in the configuration so that the configuration - * deserialization can determine what type it is. - *

- * Using this annotation on any other class than a - * {@link ConfigurationSerializable} will have no effect. - * - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface SerializableAs { - /** - * This is the name your class will be stored and retrieved as. - *

- * This name MUST be unique. We recommend using names such as "MyPluginThing" - * instead of "Thing". - * - * @return Name to serialize the class as. - */ - @NotNull - public String value(); -} diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/package-info.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/package-info.java deleted file mode 100644 index 30735e7b..00000000 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/serialization/package-info.java +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. - * Licensed under the MIT license, see LICENSE for more information... - */ -/** - * Classes dedicated to being able to perform serialization specialized for the - * Bukkit {@link com.dumbdogdiner.stickyapi.common.configuration.Configuration - * configuration} implementation. - */ -package com.dumbdogdiner.stickyapi.common.configuration.serialization; From 4be641ac0ae9208cf2f0027dfa61fd2c8bd1943a Mon Sep 17 00:00:00 2001 From: James Date: Fri, 5 Mar 2021 11:43:03 +0000 Subject: [PATCH 02/22] Initial idea for config rewrite --- .../common/configuration/Configuration.java | 90 +------------------ .../configuration/FileConfiguration.java | 18 ++++ .../configuration/providers/YamlProvider.java | 65 ++++++++++++++ .../stickyapi/common/translation/Locale.java | 9 +- 4 files changed, 92 insertions(+), 90 deletions(-) create mode 100644 common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/FileConfiguration.java create mode 100644 common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProvider.java diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/Configuration.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/Configuration.java index 048460d4..5ac69bc2 100644 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/Configuration.java +++ b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/Configuration.java @@ -4,90 +4,8 @@ */ package com.dumbdogdiner.stickyapi.common.configuration; -import java.util.Map; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +public interface Configuration { + public String getString(String path, String def); -/** - * Represents a source of configurable options and settings - */ -public interface Configuration extends ConfigurationSection { - /** - * Sets the default value of the given path as provided. - *

- * If no source {@link Configuration} was provided as a default collection, then - * a new {@link MemoryConfiguration} will be created to hold the new default - * value. - *

- * If value is null, the value will be removed from the default Configuration - * source. - * - * @param path Path of the value to set. - * @param value Value to set the default to. - * @throws IllegalArgumentException Thrown if path is null. - */ - @Override - public void addDefault(@NotNull String path, @Nullable Object value); - - /** - * Sets the default values of the given paths as provided. - *

- * If no source {@link Configuration} was provided as a default collection, then - * a new {@link MemoryConfiguration} will be created to hold the new default - * values. - * - * @param defaults A map of Path{@literal ->}Values to add to defaults. - * @throws IllegalArgumentException Thrown if defaults is null. - */ - public void addDefaults(@NotNull Map defaults); - - /** - * Sets the default values of the given paths as provided. - *

- * If no source {@link Configuration} was provided as a default collection, then - * a new {@link MemoryConfiguration} will be created to hold the new default - * value. - *

- * This method will not hold a reference to the specified Configuration, nor - * will it automatically update if that Configuration ever changes. If you - * require this, you should set the default source with - * {@link #setDefaults(com.dumbdogdiner.stickyapi.common.configuration.Configuration)}. - * - * @param defaults A configuration holding a list of defaults to copy. - * @throws IllegalArgumentException Thrown if defaults is null or this. - */ - public void addDefaults(@NotNull Configuration defaults); - - /** - * Sets the source of all default values for this {@link Configuration}. - *

- * If a previous source was set, or previous default values were defined, then - * they will not be copied to the new source. - * - * @param defaults New source of default values for this configuration. - * @throws IllegalArgumentException Thrown if defaults is null or this. - */ - public void setDefaults(@NotNull Configuration defaults); - - /** - * Gets the source {@link Configuration} for this configuration. - *

- * If no configuration source was set, but default values were added, then a - * {@link MemoryConfiguration} will be returned. If no source was set and no - * defaults were set, then this method will return null. - * - * @return Configuration source for default values, or null if none exist. - */ - @Nullable - public Configuration getDefaults(); - - /** - * Gets the {@link ConfigurationOptions} for this {@link Configuration}. - *

- * All setters through this method are chainable. - * - * @return Options for this configuration - */ - @NotNull - public ConfigurationOptions options(); -} + public String getString(String path); +} \ No newline at end of file diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/FileConfiguration.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/FileConfiguration.java new file mode 100644 index 00000000..751ba2f1 --- /dev/null +++ b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/FileConfiguration.java @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.configuration; + +import java.io.IOException; + +/** + * Interface for File-based Configurations. + */ +public interface FileConfiguration extends Configuration { + + /** + * Save the configuration to the given location. + */ + public void save(String path) throws IOException; +} diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProvider.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProvider.java new file mode 100644 index 00000000..213e3b7e --- /dev/null +++ b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProvider.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.configuration.providers; + +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + +import com.dumbdogdiner.stickyapi.common.configuration.FileConfiguration; + +import org.apache.commons.lang.Validate; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.Yaml; + +public class YamlProvider implements FileConfiguration { + + private Map data; + private YamlProvider(Map data) { + this.data = data; + } + + public static FileConfiguration load(InputStream stream) { + Validate.notNull(stream, "InputStream cannot be null!"); + + // Attempt to load the stream + + Yaml yaml = new Yaml(); + + Map obj = yaml.load(stream); + + return new YamlProvider(obj); + } + + @Override + public String getString(String path, String def) { + Object value = data.get(path); + return (value != null) ? value.toString() : def; + } + + @Override + public String getString(String path) { + Object value = data.get(path); + return (value != null) ? value.toString() : null; + } + + @Override + public void save(String path) throws IOException { + // Generate dumper options + DumperOptions options = new DumperOptions(); + options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + options.setIndent(2); + options.setPrettyFlow(true); + + // Create a new yaml object with our options + Yaml yaml = new Yaml(options); + + // Write the data + FileWriter fileWriter = new FileWriter(path); + yaml.dump(data, fileWriter); + + } +} diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/translation/Locale.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/translation/Locale.java index 38e5ff40..63809f05 100644 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/translation/Locale.java +++ b/common/src/main/java/com/dumbdogdiner/stickyapi/common/translation/Locale.java @@ -5,9 +5,10 @@ package com.dumbdogdiner.stickyapi.common.translation; import java.io.File; +import java.io.FileInputStream; -import com.dumbdogdiner.stickyapi.common.configuration.file.FileConfiguration; -import com.dumbdogdiner.stickyapi.common.configuration.file.YamlConfiguration; +import com.dumbdogdiner.stickyapi.common.configuration.Configuration; +import com.dumbdogdiner.stickyapi.common.configuration.providers.YamlProvider; import com.dumbdogdiner.stickyapi.common.util.Debugger; import org.jetbrains.annotations.NotNull; @@ -27,7 +28,7 @@ public class Locale { File localeFile; @Getter - FileConfiguration localeConfig = new YamlConfiguration(); + Configuration localeConfig; /** * Create a new locale object @@ -39,7 +40,7 @@ public class Locale { public Locale(@NotNull File localeFile) { this.localeFile = localeFile; try { - localeConfig.load(this.localeFile); + YamlProvider.load(new FileInputStream(localeFile)); isValid = true; } catch (Exception e) { e.printStackTrace(); From c6b66e33010b4f63c6d77a452298b7869adb434e Mon Sep 17 00:00:00 2001 From: James Date: Fri, 5 Mar 2021 12:09:05 +0000 Subject: [PATCH 03/22] Switch to constructor loading for YamlProvider --- .../configuration/providers/YamlProvider.java | 15 ++++++++++----- .../stickyapi/common/translation/Locale.java | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProvider.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProvider.java index 213e3b7e..1d3cb1ff 100644 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProvider.java +++ b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProvider.java @@ -4,6 +4,9 @@ */ package com.dumbdogdiner.stickyapi.common.configuration.providers; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; @@ -18,11 +21,8 @@ public class YamlProvider implements FileConfiguration { private Map data; - private YamlProvider(Map data) { - this.data = data; - } - public static FileConfiguration load(InputStream stream) { + public YamlProvider(InputStream stream) { Validate.notNull(stream, "InputStream cannot be null!"); // Attempt to load the stream @@ -31,7 +31,12 @@ public static FileConfiguration load(InputStream stream) { Map obj = yaml.load(stream); - return new YamlProvider(obj); + this.data = obj; + + } + + public YamlProvider(File file) throws FileNotFoundException { + this(new FileInputStream(file)); } @Override diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/translation/Locale.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/translation/Locale.java index 63809f05..33fa8c63 100644 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/translation/Locale.java +++ b/common/src/main/java/com/dumbdogdiner/stickyapi/common/translation/Locale.java @@ -40,7 +40,7 @@ public class Locale { public Locale(@NotNull File localeFile) { this.localeFile = localeFile; try { - YamlProvider.load(new FileInputStream(localeFile)); + localeConfig = new YamlProvider(localeFile); isValid = true; } catch (Exception e) { e.printStackTrace(); From 5253bff41602f29bcbbb6f4f031ab7b336567963 Mon Sep 17 00:00:00 2001 From: James Date: Fri, 5 Mar 2021 12:09:15 +0000 Subject: [PATCH 04/22] Add javadocs to Configuration --- .../common/configuration/Configuration.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/Configuration.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/Configuration.java index 5ac69bc2..577bf489 100644 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/Configuration.java +++ b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/Configuration.java @@ -4,8 +4,22 @@ */ package com.dumbdogdiner.stickyapi.common.configuration; +/** + * Base interface for a configuration. + */ public interface Configuration { + /** + * Gets the given string from the path, returning the given default value if not found. + * @param path The path of the string to get + * @param def The default value if the path is not found or is not a string + * @return The requested string. + */ public String getString(String path, String def); - + + /** + * Gets the given string from the path. + * @param path The path of the string to get + * @return The requested string, or null. + */ public String getString(String path); } \ No newline at end of file From 80054f869cf7b1b39a0740b6588c8dcd488de1cf Mon Sep 17 00:00:00 2001 From: James Date: Fri, 5 Mar 2021 12:38:59 +0000 Subject: [PATCH 05/22] Create YamlProvider test --- build.gradle | 1 + .../configuration/YamlProviderTest.java | 78 +++++++++++++++++++ common/src/test/resources/example.config.yml | 4 + 3 files changed, 83 insertions(+) create mode 100644 common/src/test/java/com/dumbdogdiner/stickyapi/common/configuration/YamlProviderTest.java create mode 100644 common/src/test/resources/example.config.yml diff --git a/build.gradle b/build.gradle index 512992b4..493dc77f 100644 --- a/build.gradle +++ b/build.gradle @@ -56,6 +56,7 @@ subprojects { mapping("java", "SLASHSTAR_STYLE") exclude "**/*.json" // Exclude JSON to keep the font width data valid exclude "**/*.md" + exclude "**/*.yml" exclude "**/*.MockMaker" } diff --git a/common/src/test/java/com/dumbdogdiner/stickyapi/common/configuration/YamlProviderTest.java b/common/src/test/java/com/dumbdogdiner/stickyapi/common/configuration/YamlProviderTest.java new file mode 100644 index 00000000..d14d7701 --- /dev/null +++ b/common/src/test/java/com/dumbdogdiner/stickyapi/common/configuration/YamlProviderTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.configuration; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; + +import com.dumbdogdiner.stickyapi.common.configuration.providers.YamlProvider; +import com.google.common.io.Files; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestInstance.Lifecycle; + +@TestInstance(Lifecycle.PER_CLASS) +public class YamlProviderTest { + + private static final String exampleConfigPath = "src/test/resources/example.config.yml"; + private static final String exampleConfigPathTestOutput = "build/example.config.yml.test-save"; + + private FileConfiguration exampleFileConfig; + + @BeforeAll + public void prepareGetExampleFile() { + try { + exampleFileConfig = new YamlProvider(new FileInputStream(exampleConfigPath)); + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testLoadFileAsFile() throws FileNotFoundException { + new YamlProvider(new File(exampleConfigPath)); + } + + @Test + public void testLoadFileAsInputStream() throws FileNotFoundException { + new YamlProvider(new FileInputStream(exampleConfigPath)); + } + + @Test + public void testGetValidString() { + assertEquals("Hello, World!", exampleFileConfig.getString("string")); + } + + @Test + public void testGetValidStringWithDefault() { + assertEquals("Hello, World!", exampleFileConfig.getString("string", "Goodbye, World!")); + } + + @Test + public void testGetNonExistentString() { + assertNull(exampleFileConfig.getString("non-existent")); + } + + @Test + public void testGetNonExistentStringWithDefault() { + assertEquals("Default Value", exampleFileConfig.getString("non-existent", "Default Value")); + } + + @Test + public void testSaveFile() throws IOException { + // Write the file + exampleFileConfig.save("build/example.config.yml.test-save"); + // Assert that the original and saved files match (bear in mind that snakeyaml doesn't keep comments!) + Files.equal(new File(exampleConfigPath), new File(exampleConfigPathTestOutput)); + } +} diff --git a/common/src/test/resources/example.config.yml b/common/src/test/resources/example.config.yml new file mode 100644 index 00000000..9dac156c --- /dev/null +++ b/common/src/test/resources/example.config.yml @@ -0,0 +1,4 @@ +string: "Hello, World!" +parent: + child: + child2: "value" From e862ccf6ffc7f39476dee4e6d30f529f35c4dc23 Mon Sep 17 00:00:00 2001 From: James Date: Fri, 5 Mar 2021 12:39:56 +0000 Subject: [PATCH 06/22] Move YamlProviderTest into providers pacakge --- .../configuration/{ => providers}/YamlProviderTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename common/src/test/java/com/dumbdogdiner/stickyapi/common/configuration/{ => providers}/YamlProviderTest.java (94%) diff --git a/common/src/test/java/com/dumbdogdiner/stickyapi/common/configuration/YamlProviderTest.java b/common/src/test/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProviderTest.java similarity index 94% rename from common/src/test/java/com/dumbdogdiner/stickyapi/common/configuration/YamlProviderTest.java rename to common/src/test/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProviderTest.java index d14d7701..71d05bf4 100644 --- a/common/src/test/java/com/dumbdogdiner/stickyapi/common/configuration/YamlProviderTest.java +++ b/common/src/test/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProviderTest.java @@ -2,7 +2,7 @@ * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. * Licensed under the MIT license, see LICENSE for more information... */ -package com.dumbdogdiner.stickyapi.common.configuration; +package com.dumbdogdiner.stickyapi.common.configuration.providers; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; @@ -12,7 +12,7 @@ import java.io.FileNotFoundException; import java.io.IOException; -import com.dumbdogdiner.stickyapi.common.configuration.providers.YamlProvider; +import com.dumbdogdiner.stickyapi.common.configuration.FileConfiguration; import com.google.common.io.Files; import org.junit.jupiter.api.BeforeAll; From b8ad0fcf8056314785daf3a05964194347ffd3c4 Mon Sep 17 00:00:00 2001 From: James Date: Fri, 5 Mar 2021 14:32:07 +0000 Subject: [PATCH 07/22] Add initial (in progress) LocaleProvider tests --- .../translation/LocaleProviderTest.java | 116 ++++++++++++++++++ .../localeprovider/group1/messages.en_us.yml | 86 +++++++++++++ 2 files changed, 202 insertions(+) create mode 100644 common/src/test/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProviderTest.java create mode 100644 common/src/test/resources/localeprovider/group1/messages.en_us.yml diff --git a/common/src/test/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProviderTest.java b/common/src/test/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProviderTest.java new file mode 100644 index 00000000..08e90201 --- /dev/null +++ b/common/src/test/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProviderTest.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + * Licensed under the MIT license, see LICENSE for more information... + */ +package com.dumbdogdiner.stickyapi.common.translation; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.File; +import java.util.concurrent.ConcurrentHashMap; + +import com.dumbdogdiner.stickyapi.common.util.Debugger; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; +import org.junit.jupiter.api.TestInstance.Lifecycle; + +@TestInstance(Lifecycle.PER_CLASS) +@TestMethodOrder(OrderAnnotation.class) +public class LocaleProviderTest { + + private static final File localeDirectoryGroup1 = new File("src/test/resources/localeprovider/group1"); + + private LocaleProvider localeProviderGroup1; + + // Used for tests 2/3 + private ConcurrentHashMap loadedLocales; + + @BeforeAll + public void setup() { + // Enable the StickyAPI debugger + Debugger.setEnabled(true); + // Create locale providers + localeProviderGroup1 = new LocaleProvider(localeDirectoryGroup1); + } + + @Test + @Order(1) + public void testLoadLocaleString() { + assertTrue(localeProviderGroup1.loadLocale("messages.en_us.yml")); + } + + @Test + @Order(2) + public void testLoadedLocalesSizeOneLoaded() { + loadedLocales = localeProviderGroup1.getLoadedLocales(); + assertEquals(1, loadedLocales.size()); + } + + @Test + @Order(3) + public void testLoadedLocalesContentOneLoaded() { + Locale onlyLocale = (Locale) loadedLocales.values().toArray()[0]; + assertEquals(localeProviderGroup1.getLocale("messages.en_us"), onlyLocale); + } + + @Test + @Order(4) + public void testGetDefaultLocaleNull() { + assertEquals(null, localeProviderGroup1.getDefaultLocale()); + } + + @Test + @Order(5) + public void testSetDefaultLocaleLoaded() { + assertTrue(localeProviderGroup1.setDefaultLocale("messages.en_us")); + } + + @Test + @Order(6) + public void testSetDefaultLocaleNotLoaded() { + assertFalse(localeProviderGroup1.setDefaultLocale("not-loaded-locale")); + } + + @Test + @Order(7) + public void testGetDefaultLocale() { + assertEquals(localeProviderGroup1.getLocale("messages.en_us"), localeProviderGroup1.getDefaultLocale()); + } + + @Test + @Order(8) + public void testLoadLocaleSameOneTwiceWithExtension() { + // Should return false and debug "already loaded" + assertFalse(localeProviderGroup1.loadLocale("messages.en_us.yml")); + } + + @Test + @Order(9) + public void testLoadLocaleSameOneTwiceNoExtension() { + // Should return false and debug "already loaded" + assertFalse(localeProviderGroup1.loadLocale("messages.en_us")); + } + + @Test + @Order(10) + public void testLoadLocaleNonExistentFile() { + // Should return false and debug "could not find file" + assertFalse(localeProviderGroup1.loadLocale("non-existent-locale.yml")); + } + + /* + Cannot be tested right now... + + public void testLoadLocaleInvalidFile() { + // Should return false and debug "encountered an error - skipping" + assertFalse(localeProviderGroup1.loadLocale("invalid.yml")); + }*/ + +} diff --git a/common/src/test/resources/localeprovider/group1/messages.en_us.yml b/common/src/test/resources/localeprovider/group1/messages.en_us.yml new file mode 100644 index 00000000..9f62345e --- /dev/null +++ b/common/src/test/resources/localeprovider/group1/messages.en_us.yml @@ -0,0 +1,86 @@ +# SRC: https://github.com/DumbDogDiner/StickyCommands/blob/master/bukkit/src/main/resources/messages.en_us.yml +# StickyCommands Translation file +# ------------------------- + +# Messages.yml - All plugin text is in this file +# +# Anything between curley brackets is replaced with the values of the named variables. + +# Global variables, you can use these in any message in this file. +newline: "&8&l» " +prefix: "&b&lStickyCommands {newline}" +network-name: "&bDumb Dog Diner" +website: "dumbdogdiner.com" + +# Common error messages used throughout the plugin +invalid-syntax: "{prefix}&cInvalid Syntax! Please use &f{syntax}&c!" +server-error: "{prefix}&cThe server encountered an error, please try again later." +no-permission: "{prefix}&cError! Permission denied!" +player-does-not-exist: "{prefix}&cError! The player {target} does not exist!" +player-has-not-joined: "{prefix}&cError! The player {target} has not joined before!" +must-be-player: "{prefix}&cYou must be a player to execute this command!" +not-online-player: "{prefix}&c Error! {player} is not online!" +invalid-group: "{prefix}&cError! Group {GROUP} is invalid!" + +# The config supports new lines (\n), it can be used on any node +whois-message: "{prefix}&bWhois data for {target}\n{newline}&b{target_online|yesno:'&aOnline,&cOffline'} &bsince: &f{target_last_seen|expiry}\n{newline}&bIP: &f{target_ipaddress}\n{newline}&bFirst Login: &f{target_first_seen|expiry}\n{newline}&bLast Login: &f{target_last_seen|expiry}\n{newline}&bLast Server: &f{target_last_server}\n{newline}&bFly/Walk: &f{target_fly_speed}&b / &f{target_walk_speed}" +seen-message: "{prefix}&f{target} &bhas been {target_online|yesno:'&aOnline,&cOffline'}\n{newline} &bSince: &f{target_last_seen|expiry}\n{newline} &bOn Server: &f{target_last_server}" +top-message: "{prefix}&bWoosh! You're at the top!" +jump-message: "{prefix}&bWEEEEE!!!" +speed-message: "{prefix}&bYour {player_flying|yesno:'fly,walk'} speed has been set to &f{player_speed}&b!" +reload: + configs-success: "{prefix}&aReloaded configuration and messages successfully!" + database-success: "{prefix}&aReloaded configuration and messages successfully!" + error: "{prefix}&cThere was an error reloading StickyCommands, please see console for details!" + +back: + no-previous: "{prefix}&cNo previous location found!" + teleported: "{prefix}&bYou have been returned to your last location!" + teleported-other: "{prefix}&bReturned &f{target} &bto their last location!" + +sell: + cannot-sell: "{prefix}&cThis item cannot be sold!" + bad-worth: "{prefix}&f1 {item} &cis worth a negative amount &f(${single_worth}) &cand cannot be sold &4(Please ask a developer)" + worth-message: "{prefix}&f1 {item} &bis worth &f${single_worth} &7(Hand: ${hand_worth}, Inventory: ${inventory_worth})" + sell-message: "{prefix}&bYou sold &f{amount} {item} &bfor &f${worth}&b!" + must-confirm: "{prefix}&cPlease confirm your sale by typing /sell [inventory/hand] confirm!" + log: + log-message: "{prefix}&bRecent sale logs" + log: "{newline}&7({short_date}) &f{log_player} &bsold &f{amount} {item} &bfor &f${price}" + log-hover: "&bSale &f#{saleid}\n&8&l» &bItem Sold:&f {item_enum}\n&8&l» &bAmount Sold:&f {amount}\n&8&l» &bNew Balance:&f &2(+${price})\n&8&l» &bSold:&f {date_duration}\n&8&l» &bTransaction ID:&f {saleid}" + no-sales: "{prefix}&bThere have been no sales!" + paginator: "{prefix}&bpage &f{current}&b/&f{total}" + +afk: + not-afk: "&7&o* {player} is no longer AFK!" + afk: "&7&o* {player} is now AFK!" + afk-kick: "&cYou have been AFK for {time|duration} and have been kicked!" + +hat: + no-hat: "{prefix}&bYou do not have a hat!" + new-hat: "{prefix}&bEnjoy your new hat!" + remove-hat: "{prefix}&bYour hat has been removed!" +item-message: "{prefix}&bGave you &f{amount} {item}&b!" + +kill: + you-were-killed: "{prefix}&bThou hast been slain!" + you-killed: "{prefix}&bYou killed &f{target}" + suicide: "{prefix}&bYou magically died!" + +smite: + smite-other-player: "{prefix}&bYour fury reigns down on &f{target}&b!" + smite-block: "{prefix}&bYour fury reigns down on the block at &f{location_x}, {location_y}, {location_z} &bof world &f{world}" + smite-message: "{prefix}&bThou hast been smitten!" + smite-immune: "{prefix}&f{target}&c is immune to your wrath!" + yourself: "{prefix}&bYou have smitten yourself!" + +powertool: + cleared: "{prefix}&bCleared your powertool!" + assigned: "{prefix}&bPowertool created with command &f\"{command}\"" + cannot-bind-air: "{prefix}&cYou may not bind a command to your hand!" + toggled: "{prefix}&bYour powertool has been toggled {toggled|yesno:'&aOn,&cOff'}" + no-powertool: "{prefix}&cYou do not have a powertool to toggle!" + +player-time: + time-reset: "{prefix}&bYour time has been synced with the server &f({time} ticks)&b!" + time-set: "{prefix}&bYour time has been set to &f{time} ticks&b{relative|empty_if_false:\" relative to server time\"}!" \ No newline at end of file From 4559859950fa8981cbb14af3404d36f6ef3cf57b Mon Sep 17 00:00:00 2001 From: James Date: Fri, 5 Mar 2021 19:13:52 +0000 Subject: [PATCH 08/22] Add non-existent directory instanciation test --- .../translation/LocaleProviderTest.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/common/src/test/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProviderTest.java b/common/src/test/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProviderTest.java index 08e90201..0272f24b 100644 --- a/common/src/test/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProviderTest.java +++ b/common/src/test/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProviderTest.java @@ -27,6 +27,8 @@ public class LocaleProviderTest { private static final File localeDirectoryGroup1 = new File("src/test/resources/localeprovider/group1"); + private static final File nonExistentDirectory = new File("build/localeprovider-newfolder"); + private LocaleProvider localeProviderGroup1; // Used for tests 2/3 @@ -36,8 +38,14 @@ public class LocaleProviderTest { public void setup() { // Enable the StickyAPI debugger Debugger.setEnabled(true); + // Create locale providers localeProviderGroup1 = new LocaleProvider(localeDirectoryGroup1); + + // Delete the non-existent testing directory if it exists + if (nonExistentDirectory.exists()) { + assertTrue(nonExistentDirectory.delete()); // Attempt to delete the directory + } } @Test @@ -113,4 +121,17 @@ public void testLoadLocaleInvalidFile() { assertFalse(localeProviderGroup1.loadLocale("invalid.yml")); }*/ + @Test + public void testCreateLocaleProviderWithNonExistentFolder() { + // Make sure the file does not exist + assertFalse(nonExistentDirectory.exists()); + + // Create a new instance of LocaleProvider (will create the directory) + new LocaleProvider(nonExistentDirectory); + + // Make sure that it now exists and is a directory + assertTrue(nonExistentDirectory.exists()); + assertTrue(nonExistentDirectory.isDirectory()); + } + } From 016c8675cb0560b2b9d7b120a0d78cef7ef77636 Mon Sep 17 00:00:00 2001 From: James Date: Fri, 5 Mar 2021 21:12:29 +0000 Subject: [PATCH 09/22] Add translate and translateNoColor tests --- .../translation/LocaleProviderTest.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/common/src/test/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProviderTest.java b/common/src/test/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProviderTest.java index 0272f24b..e4b8cc29 100644 --- a/common/src/test/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProviderTest.java +++ b/common/src/test/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProviderTest.java @@ -6,9 +6,11 @@ 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.assertTrue; import java.io.File; +import java.util.HashMap; import java.util.concurrent.ConcurrentHashMap; import com.dumbdogdiner.stickyapi.common.util.Debugger; @@ -113,6 +115,71 @@ public void testLoadLocaleNonExistentFile() { assertFalse(localeProviderGroup1.loadLocale("non-existent-locale.yml")); } + @Test + @Order(11) + public void testTranslate() { + String output = localeProviderGroup1.translate("player-has-not-joined", new HashMap() {{ + put("prefix", "Msg>"); + put("target", "Notch"); + }}); + + // Translate changes & to § for ChatColor codes + assertEquals("Msg>§cError! The player Notch has not joined before!", output); + } + + @Test + @Order(12) + public void testTranslateNonExistentNode() { + // should return null and debug "node does not exist" + assertNull(localeProviderGroup1.translate("non-existent", new HashMap<>())); + } + + @Test + @Order(13) + public void testTranslateEmptyNode() { + // should return null and debug "invalid node name" + assertNull(localeProviderGroup1.translate("", new HashMap<>())); + } + + @Test + @Order(14) + public void testTranslateNullNode() { + // should return null and debug "invalid node name" + assertNull(localeProviderGroup1.translate(null, new HashMap<>())); + } + + @Test + @Order(15) + public void testTranslateNoColor() { + String output = localeProviderGroup1.translateNoColor("player-has-not-joined", new HashMap() {{ + put("prefix", "Msg>"); + put("target", "Notch"); + }}); + + assertEquals("Msg>&cError! The player Notch has not joined before!", output); + } + + @Test + @Order(16) + public void testTranslateNoColorNonExistentNode() { + // should return null and debug "node does not exist" + assertNull(localeProviderGroup1.translateNoColor("non-existent", new HashMap<>())); + } + + @Test + @Order(17) + public void testTranslateNoColorEmptyNode() { + // should return null and debug "invalid node name" + assertNull(localeProviderGroup1.translateNoColor("", new HashMap<>())); + } + + @Test + @Order(18) + public void testTranslateNoColorNullNode() { + // should return null and debug "invalid node name" + assertNull(localeProviderGroup1.translateNoColor(null, new HashMap<>())); + } + /* Cannot be tested right now... From 5f2713a28a8e23e7bb6a776bcf7f866ad63bd318 Mon Sep 17 00:00:00 2001 From: James Date: Fri, 5 Mar 2021 21:18:35 +0000 Subject: [PATCH 10/22] Create loadAllLocales test (with ignored txt file for testing) --- .../common/translation/LocaleProviderTest.java | 12 ++++++++++-- .../test/resources/localeprovider/group1/ignored.txt | 6 ++++++ 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 common/src/test/resources/localeprovider/group1/ignored.txt diff --git a/common/src/test/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProviderTest.java b/common/src/test/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProviderTest.java index e4b8cc29..5c8c0f50 100644 --- a/common/src/test/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProviderTest.java +++ b/common/src/test/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProviderTest.java @@ -192,13 +192,21 @@ public void testLoadLocaleInvalidFile() { public void testCreateLocaleProviderWithNonExistentFolder() { // Make sure the file does not exist assertFalse(nonExistentDirectory.exists()); - // Create a new instance of LocaleProvider (will create the directory) new LocaleProvider(nonExistentDirectory); - // Make sure that it now exists and is a directory assertTrue(nonExistentDirectory.exists()); assertTrue(nonExistentDirectory.isDirectory()); } + + @Test + public void testCreateLocaleProviderAndLoadAllLocales() { + LocaleProvider localeProvider = new LocaleProvider(localeDirectoryGroup1); + + // Load all locales, and assert that only one was loaded. + // There are 2 files in the given directory, one .yml file and one .txt + // This should return 1 and ignore the txt file + assertEquals(1, localeProvider.loadAllLocales()); + } } diff --git a/common/src/test/resources/localeprovider/group1/ignored.txt b/common/src/test/resources/localeprovider/group1/ignored.txt new file mode 100644 index 00000000..f51d7add --- /dev/null +++ b/common/src/test/resources/localeprovider/group1/ignored.txt @@ -0,0 +1,6 @@ +==== + Copyright (c) 2020-2021 DumbDogDiner . All rights reserved. + Licensed under the MIT license, see LICENSE for more information... +==== + +(LocaleProvider should ignore this file) \ No newline at end of file From 73e53366b5499cac08d315818f1a41ee2d44ce04 Mon Sep 17 00:00:00 2001 From: James Date: Fri, 5 Mar 2021 21:36:25 +0000 Subject: [PATCH 11/22] Create get tests --- .../translation/LocaleProviderTest.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/common/src/test/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProviderTest.java b/common/src/test/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProviderTest.java index 5c8c0f50..cb8948c9 100644 --- a/common/src/test/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProviderTest.java +++ b/common/src/test/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProviderTest.java @@ -7,6 +7,7 @@ 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.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; @@ -36,6 +37,10 @@ public class LocaleProviderTest { // Used for tests 2/3 private ConcurrentHashMap loadedLocales; + private enum Values { + NETWORK_NAME + } + @BeforeAll public void setup() { // Enable the StickyAPI debugger @@ -180,6 +185,41 @@ public void testTranslateNoColorNullNode() { assertNull(localeProviderGroup1.translateNoColor(null, new HashMap<>())); } + @Test + @Order(19) + public void testGetEnum() { + // Sanity check - make sure translation works as expected + assertEquals("network-name", Values.NETWORK_NAME.name().toLowerCase().replace("_", "-")); + // Should translate to network-name and return the given value + assertEquals("&bDumb Dog Diner", localeProviderGroup1.get(Values.NETWORK_NAME)); + } + + @Test + @Order(20) + public void testGetWithNameAndNode() { + assertEquals("&bDumb Dog Diner", localeProviderGroup1.get("messages.en_us", "network-name")); + } + + @Test + @Order(21) + public void testGetWithNameAndNodeUnloadedLocale() { + assertThrows(IllegalArgumentException.class, () -> { + localeProviderGroup1.get("non-existent-locale", "network-name"); + }); + } + + @Test + @Order(22) + public void testGetDefault() { + assertEquals("&bDumb Dog Diner", localeProviderGroup1.getDefault("network-name", "&bExample Server")); + } + + @Test + @Order(23) + public void testGetDefaultNoNode() { + assertEquals("default value", localeProviderGroup1.getDefault("non-existent", "default value")); + } + /* Cannot be tested right now... @@ -188,6 +228,13 @@ public void testLoadLocaleInvalidFile() { assertFalse(localeProviderGroup1.loadLocale("invalid.yml")); }*/ + @Test + public void testGetNoDefaultLocale() { + LocaleProvider localeProvider = new LocaleProvider(localeDirectoryGroup1); + assertNull(localeProvider.get("player-has-not-joined")); // Valid node + assertNull(localeProvider.get("")); // Invalid node + } + @Test public void testCreateLocaleProviderWithNonExistentFolder() { // Make sure the file does not exist From 8401dd6b790320b5ad9e7ff85e3c19ad82765fc2 Mon Sep 17 00:00:00 2001 From: James Date: Fri, 5 Mar 2021 22:32:55 +0000 Subject: [PATCH 12/22] Use FileConfiguration instead of Configuration for localeConfig --- .../dumbdogdiner/stickyapi/common/translation/Locale.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/translation/Locale.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/translation/Locale.java index 33fa8c63..a8194e13 100644 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/translation/Locale.java +++ b/common/src/main/java/com/dumbdogdiner/stickyapi/common/translation/Locale.java @@ -5,9 +5,8 @@ package com.dumbdogdiner.stickyapi.common.translation; import java.io.File; -import java.io.FileInputStream; -import com.dumbdogdiner.stickyapi.common.configuration.Configuration; +import com.dumbdogdiner.stickyapi.common.configuration.FileConfiguration; import com.dumbdogdiner.stickyapi.common.configuration.providers.YamlProvider; import com.dumbdogdiner.stickyapi.common.util.Debugger; @@ -28,7 +27,7 @@ public class Locale { File localeFile; @Getter - Configuration localeConfig; + FileConfiguration localeConfig; /** * Create a new locale object From 32b638fba7c47d2ea46344d6339105e8331ab667 Mon Sep 17 00:00:00 2001 From: James Date: Sat, 6 Mar 2021 11:06:14 +0000 Subject: [PATCH 13/22] (breaking): Remove LocaleProvider#writeLocaleStream --- .../common/translation/LocaleProvider.java | 43 ------------------- 1 file changed, 43 deletions(-) diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProvider.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProvider.java index 22d062ab..3aa92795 100644 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProvider.java +++ b/common/src/main/java/com/dumbdogdiner/stickyapi/common/translation/LocaleProvider.java @@ -258,49 +258,6 @@ public boolean setDefaultLocale(@NotNull String name) { return true; } - /** - * Save an internal resource to the data file. - * - * @param in File inputstream - * @param resourcePath The path to which the resource should be saved - * @param replace Whether or not to replace the file if it already exists - * @throws IllegalArgumentException - * @throws IOException - */ - public void writeLocaleStream(@NotNull InputStream in, @NotNull String resourcePath, @NotNull boolean replace) - throws IllegalArgumentException, IOException { - if (resourcePath == null || resourcePath.equals("")) { - throw new IllegalArgumentException("Resource path cannot be null or empty"); - } - - resourcePath = resourcePath.replace('\\', '/'); - if (in == null) { - throw new IllegalArgumentException("The embedded resource '" + resourcePath + "' cannot be found"); - } - - File outFile = new File(localeFolder, resourcePath); - int lastIndex = resourcePath.lastIndexOf('/'); - File outDir = new File(localeFolder, resourcePath.substring(0, lastIndex >= 0 ? lastIndex : 0)); - - if (!outDir.exists()) { - outDir.mkdirs(); - } - - if (outFile.exists() && !replace) { - System.out.println("resource already exists"); - return; - } - - OutputStream out = new FileOutputStream(outFile); - byte[] buf = new byte[1024]; - int len; - while ((len = in.read(buf)) > 0) { - out.write(buf, 0, len); - } - out.close(); - in.close(); - } - /** * Checks if a locale with the given name is loaded. Throws * `IllegalArgumentException` if not found. From d95a9c4cdb60b37cee1dce61bf0bbbfa06a6e133 Mon Sep 17 00:00:00 2001 From: James Date: Sun, 7 Mar 2021 10:14:44 +0000 Subject: [PATCH 14/22] Extend save functionality to support FileWriter, File and string inputs --- .../configuration/FileConfiguration.java | 23 +++++++++- .../configuration/providers/YamlProvider.java | 43 +++++++++++++++++-- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/FileConfiguration.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/FileConfiguration.java index 751ba2f1..cb356881 100644 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/FileConfiguration.java +++ b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/FileConfiguration.java @@ -4,6 +4,8 @@ */ package com.dumbdogdiner.stickyapi.common.configuration; +import java.io.File; +import java.io.FileWriter; import java.io.IOException; /** @@ -12,7 +14,24 @@ public interface FileConfiguration extends Configuration { /** - * Save the configuration to the given location. + * Save the configuration to the given string path. + * + * @param path {@link String} output filename path + * @return Returns a {@link Boolean} value depending on if the save was successful or not */ - public void save(String path) throws IOException; + public boolean save(String path); + + /** + * + * @param output {@link File} to output to + * @return Returns a {@link Boolean} value depending on if the save was successful or not + */ + public boolean save(File output); + + /** + * Save the configuration to the given FileWriter. + * + * @param output {@link FileWriter} to output to + */ + public void save(FileWriter output); } diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProvider.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProvider.java index 1d3cb1ff..a5731c24 100644 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProvider.java +++ b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProvider.java @@ -52,7 +52,43 @@ public String getString(String path) { } @Override - public void save(String path) throws IOException { + public boolean save(String path) { + FileWriter fileWriter; + try { + // Attempt to create the FileWriter object (can throw IOException) + fileWriter = new FileWriter(path); + + // Save the config + save(fileWriter); + + // Saved successfully, return true + return true; + } catch (IOException e) { + // creating the FileWriter errored, so return false + return false; + } + + } + + public boolean save(File output) { + FileWriter fileWriter; + try { + // Attempt to create the FileWriter object (can throw IOException) + fileWriter = new FileWriter(output); + + // Save the config + save(fileWriter); + + // Saved successfully, return true + return true; + } catch (IOException e) { + // creating the FileWriter errored, so return false + return false; + } + } + + @Override + public void save(FileWriter output) { // Generate dumper options DumperOptions options = new DumperOptions(); options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); @@ -63,8 +99,7 @@ public void save(String path) throws IOException { Yaml yaml = new Yaml(options); // Write the data - FileWriter fileWriter = new FileWriter(path); - yaml.dump(data, fileWriter); - + yaml.dump(data, output); + } } From d37eccd3733836488ca7ead3eac2081c7e16b0b4 Mon Sep 17 00:00:00 2001 From: James Date: Sun, 7 Mar 2021 10:45:50 +0000 Subject: [PATCH 15/22] Add more YamlProviderTests for new loading methods --- .../providers/YamlProviderTest.java | 33 ++++++++++++++++--- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/common/src/test/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProviderTest.java b/common/src/test/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProviderTest.java index 71d05bf4..87c7a446 100644 --- a/common/src/test/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProviderTest.java +++ b/common/src/test/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProviderTest.java @@ -5,7 +5,9 @@ package com.dumbdogdiner.stickyapi.common.configuration.providers; 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.assertTrue; import java.io.File; import java.io.FileInputStream; @@ -24,7 +26,6 @@ public class YamlProviderTest { private static final String exampleConfigPath = "src/test/resources/example.config.yml"; - private static final String exampleConfigPathTestOutput = "build/example.config.yml.test-save"; private FileConfiguration exampleFileConfig; @@ -69,10 +70,32 @@ public void testGetNonExistentStringWithDefault() { } @Test - public void testSaveFile() throws IOException { + public void testSaveFileInputString() throws IOException { + String testOutput = "build/example.config.yml.string.test-save"; // Write the file - exampleFileConfig.save("build/example.config.yml.test-save"); - // Assert that the original and saved files match (bear in mind that snakeyaml doesn't keep comments!) - Files.equal(new File(exampleConfigPath), new File(exampleConfigPathTestOutput)); + assertTrue(exampleFileConfig.save(testOutput)); + // Assert that the original and saved files match (note that snakeyaml doesn't keep comments!) + // This *could* throw an IOException + Files.equal(new File(exampleConfigPath), new File(testOutput)); + } + + @Test + public void testSaveFileInputFile() throws IOException { + String testOutput = "build/example.config.yml.file.test-save"; + // Write the file + assertTrue(exampleFileConfig.save(new File(testOutput))); + // Assert that the original and saved files match (note that snakeyaml doesn't keep comments!) + // This *could* throw an IOException + Files.equal(new File(exampleConfigPath), new File(testOutput)); + } + + @Test + public void testSaveFileInputStringInvalid() { + assertFalse(exampleFileConfig.save("build")); + } + + @Test + public void testSaveFileInputFileInvalid() { + assertFalse(exampleFileConfig.save(new File("build"))); } } From 427041c9201765923fff6e4519d2cfe21cebc69a Mon Sep 17 00:00:00 2001 From: James Date: Sun, 7 Mar 2021 10:46:22 +0000 Subject: [PATCH 16/22] Add FileConfiguration#reload method --- .../configuration/FileConfiguration.java | 3 ++- .../configuration/providers/YamlProvider.java | 20 ++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/FileConfiguration.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/FileConfiguration.java index cb356881..02a6e838 100644 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/FileConfiguration.java +++ b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/FileConfiguration.java @@ -6,13 +6,14 @@ import java.io.File; import java.io.FileWriter; -import java.io.IOException; /** * Interface for File-based Configurations. */ public interface FileConfiguration extends Configuration { + public void reload(); + /** * Save the configuration to the given string path. * diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProvider.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProvider.java index a5731c24..10c547e3 100644 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProvider.java +++ b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProvider.java @@ -22,21 +22,27 @@ public class YamlProvider implements FileConfiguration { private Map data; + private InputStream inputStream; + public YamlProvider(InputStream stream) { Validate.notNull(stream, "InputStream cannot be null!"); - // Attempt to load the stream + this.inputStream = stream; + this.reload(); + } + + public YamlProvider(File file) throws FileNotFoundException { + this(new FileInputStream(file)); + } + + public void reload() { + // Attempt to (re)load the stream Yaml yaml = new Yaml(); - Map obj = yaml.load(stream); + Map obj = yaml.load(this.inputStream); this.data = obj; - - } - - public YamlProvider(File file) throws FileNotFoundException { - this(new FileInputStream(file)); } @Override From df8ed3d90e1153222e1b4a9eed207e5523954287 Mon Sep 17 00:00:00 2001 From: James Date: Sun, 7 Mar 2021 11:51:24 +0000 Subject: [PATCH 17/22] (bukkit/bungee StartupUtil): Try using YamlProvider instead of removed writeLocaleStream --- .../stickyapi/bukkit/util/StartupUtil.java | 11 ++++++++++- .../stickyapi/bungeecord/util/StartupUtil.java | 14 ++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/StartupUtil.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/StartupUtil.java index beb5505b..4f0514c6 100644 --- a/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/StartupUtil.java +++ b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/StartupUtil.java @@ -8,6 +8,7 @@ import javax.annotation.Nullable; +import com.dumbdogdiner.stickyapi.common.configuration.providers.YamlProvider; import com.dumbdogdiner.stickyapi.common.translation.LocaleProvider; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; @@ -62,7 +63,15 @@ public static LocaleProvider setupLocale(@NotNull JavaPlugin plugin, @Nullable L .severe("Failed to configure default locale file - perhaps you deleted it? Will create a new one."); // FIXME: This is horrible and needs to be improved try { - localeProvider.writeLocaleStream(plugin.getResource("messages.en_us.yml"), "messages.en_us.yml", true); + // Step 1:Load the yml from plugin.getResource (the internal .jar resource) + YamlProvider embeddedMessagesResource = new YamlProvider(plugin.getResource("messages.en_us.yml")); + + // Step 2: Create a File instance representing our output dir in the plugin's data folder + File outputLocation = new File(localeProvider.getLocaleFolder(), "messages.en_us.yml"); + // outputLocation should now be something like [..]/plugins/[..]/locale/messages.en_us.yml + + // Step 3: write the embedded messages resource to the plugin data dir + embeddedMessagesResource.save(outputLocation); } catch (Exception e) { e.printStackTrace(); plugin.getLogger().severe("Something went horribly wrong while saving the default locale."); diff --git a/bungee/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/util/StartupUtil.java b/bungee/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/util/StartupUtil.java index 89c50c7e..d2c6cb98 100644 --- a/bungee/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/util/StartupUtil.java +++ b/bungee/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/util/StartupUtil.java @@ -7,6 +7,7 @@ import java.io.File; import com.dumbdogdiner.stickyapi.annotation.Untested; +import com.dumbdogdiner.stickyapi.common.configuration.providers.YamlProvider; import com.dumbdogdiner.stickyapi.common.translation.LocaleProvider; import org.jetbrains.annotations.NotNull; @@ -69,8 +70,17 @@ public static LocaleProvider setupLocale(@NotNull Plugin plugin, @Nullable Local .severe("Failed to configure default locale file - perhaps you deleted it? Will create a new one."); // FIXME: This is horrible and needs to be improved try { - localeProvider.writeLocaleStream(plugin.getResourceAsStream("messages.en_us.yml"), "messages.en_us.yml", - true); + // Step 1:Load the yml from plugin.getResource (the internal .jar resource) + YamlProvider embeddedMessagesResource = new YamlProvider(plugin.getResourceAsStream("messages.en_us.yml")); + + // Step 2: Create a File instance representing our output dir in the plugin's + // data folder + File outputLocation = new File(localeProvider.getLocaleFolder(), "messages.en_us.yml"); + // outputLocation should now be something like + // [..]/plugins/[..]/locale/messages.en_us.yml + + // Step 3: write the embedded messages resource to the plugin data dir + embeddedMessagesResource.save(outputLocation); } catch (Exception e) { e.printStackTrace(); plugin.getLogger().severe("Something went horribly wrong while saving the default locale."); From 114e2da8eba9d83d78d341902f4d9bc26313e62e Mon Sep 17 00:00:00 2001 From: James Date: Sat, 13 Mar 2021 11:15:27 +0000 Subject: [PATCH 18/22] Use ConcurrentHashMaps to be thread-safe --- .../common/configuration/providers/YamlProvider.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProvider.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProvider.java index 10c547e3..46009c77 100644 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProvider.java +++ b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProvider.java @@ -11,6 +11,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import com.dumbdogdiner.stickyapi.common.configuration.FileConfiguration; @@ -20,7 +21,7 @@ public class YamlProvider implements FileConfiguration { - private Map data; + private ConcurrentHashMap data; private InputStream inputStream; @@ -40,9 +41,11 @@ public void reload() { Yaml yaml = new Yaml(); + // If we load to a ConcurrentHashMap directly, the map doesn't populate with our data Map obj = yaml.load(this.inputStream); - this.data = obj; + // Convert the loaded Map to a ConcurrentHashMap + this.data = new ConcurrentHashMap(obj); } @Override From d87e2936dbccf358462bcf5039a1c03fdafaa64f Mon Sep 17 00:00:00 2001 From: James Date: Sat, 13 Mar 2021 11:19:53 +0000 Subject: [PATCH 19/22] Use "this" keyword --- .../common/configuration/providers/YamlProvider.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProvider.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProvider.java index 46009c77..9f48a117 100644 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProvider.java +++ b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProvider.java @@ -50,13 +50,13 @@ public void reload() { @Override public String getString(String path, String def) { - Object value = data.get(path); + Object value = this.data.get(path); return (value != null) ? value.toString() : def; } @Override public String getString(String path) { - Object value = data.get(path); + Object value = this.data.get(path); return (value != null) ? value.toString() : null; } @@ -68,7 +68,7 @@ public boolean save(String path) { fileWriter = new FileWriter(path); // Save the config - save(fileWriter); + this.save(fileWriter); // Saved successfully, return true return true; @@ -86,7 +86,7 @@ public boolean save(File output) { fileWriter = new FileWriter(output); // Save the config - save(fileWriter); + this.save(fileWriter); // Saved successfully, return true return true; From b8fe82d48445fab82139aeb2db84605f4aa270d4 Mon Sep 17 00:00:00 2001 From: James Date: Sat, 13 Mar 2021 12:03:10 +0000 Subject: [PATCH 20/22] Add javadoc to reload function --- .../stickyapi/common/configuration/FileConfiguration.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/FileConfiguration.java b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/FileConfiguration.java index 02a6e838..fc5f37f8 100644 --- a/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/FileConfiguration.java +++ b/common/src/main/java/com/dumbdogdiner/stickyapi/common/configuration/FileConfiguration.java @@ -12,6 +12,11 @@ */ public interface FileConfiguration extends Configuration { + /** + * Reload the current configuration, for example to load new data. + * This will reload the configuration file from the filesystem into memory, + * overwriting the currently loaded data. + */ public void reload(); /** From d67d8df02f18c666587204d90a704dbaa4fddada Mon Sep 17 00:00:00 2001 From: SkyezerFox Date: Sat, 13 Mar 2021 17:18:10 +0000 Subject: [PATCH 21/22] tests: add async YamlProvider read test --- .../providers/YamlProviderTest.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/common/src/test/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProviderTest.java b/common/src/test/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProviderTest.java index 87c7a446..ea6d9068 100644 --- a/common/src/test/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProviderTest.java +++ b/common/src/test/java/com/dumbdogdiner/stickyapi/common/configuration/providers/YamlProviderTest.java @@ -13,6 +13,10 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicBoolean; import com.dumbdogdiner.stickyapi.common.configuration.FileConfiguration; import com.google.common.io.Files; @@ -98,4 +102,27 @@ public void testSaveFileInputStringInvalid() { public void testSaveFileInputFileInvalid() { assertFalse(exampleFileConfig.save(new File("build"))); } + + @Test + public void testAsynchronousRead() { + // create a new threadpool with n threads. + int threadCount = 3; + ExecutorService pool = Executors.newFixedThreadPool(threadCount); + AtomicBoolean didFail = new AtomicBoolean(); + // create n tasks and submit them to the pool. + for (int i = 0; i < threadCount; i++) { + pool.submit(() -> { + if (!exampleFileConfig.getString("string").equals("Hello, World!")) { + didFail.set(true); + } + }); + } + // wait for pool to finish execution. + pool.shutdown(); + assertFalse(didFail.get()); + } + + // This does not work yet - need to implement write. + // @Test + // public void testAsynchronousWrite() { } } From f8f7306a340aa69b8a4273abd64c6b7b2e870873 Mon Sep 17 00:00:00 2001 From: James Date: Mon, 15 Mar 2021 12:01:29 +0000 Subject: [PATCH 22/22] (bukkit/bungee): Add explicit file exists check --- .../stickyapi/bukkit/util/StartupUtil.java | 16 +++++++++++---- .../bungeecord/util/StartupUtil.java | 20 ++++++++++++------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/StartupUtil.java b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/StartupUtil.java index 4f0514c6..c12b8879 100644 --- a/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/StartupUtil.java +++ b/bukkit/src/main/java/com/dumbdogdiner/stickyapi/bukkit/util/StartupUtil.java @@ -5,6 +5,8 @@ package com.dumbdogdiner.stickyapi.bukkit.util; import java.io.File; +import java.io.FileNotFoundException; +import java.io.InputStream; import javax.annotation.Nullable; @@ -61,16 +63,22 @@ public static LocaleProvider setupLocale(@NotNull JavaPlugin plugin, @Nullable L if (!localeEnabled) { plugin.getLogger() .severe("Failed to configure default locale file - perhaps you deleted it? Will create a new one."); - // FIXME: This is horrible and needs to be improved try { - // Step 1:Load the yml from plugin.getResource (the internal .jar resource) + // Step 1: Make sure the locale file exists (returns null if not found) + InputStream localeFile = plugin.getResource("messages.en_us.yml"); + + // Step 1.5: Throw an exception if the file doesn't exist + if (localeFile == null) + throw new FileNotFoundException("The locale file was not found in our embedded resources!"); + + // Step 2: Load the yml from plugin.getResource (the internal .jar resource) YamlProvider embeddedMessagesResource = new YamlProvider(plugin.getResource("messages.en_us.yml")); - // Step 2: Create a File instance representing our output dir in the plugin's data folder + // Step 3: Create a File instance representing our output dir in the plugin's data folder File outputLocation = new File(localeProvider.getLocaleFolder(), "messages.en_us.yml"); // outputLocation should now be something like [..]/plugins/[..]/locale/messages.en_us.yml - // Step 3: write the embedded messages resource to the plugin data dir + // Step 4: write the embedded messages resource to the plugin data dir embeddedMessagesResource.save(outputLocation); } catch (Exception e) { e.printStackTrace(); diff --git a/bungee/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/util/StartupUtil.java b/bungee/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/util/StartupUtil.java index d2c6cb98..32ff282e 100644 --- a/bungee/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/util/StartupUtil.java +++ b/bungee/src/main/java/com/dumbdogdiner/stickyapi/bungeecord/util/StartupUtil.java @@ -5,6 +5,8 @@ package com.dumbdogdiner.stickyapi.bungeecord.util; import java.io.File; +import java.io.FileNotFoundException; +import java.io.InputStream; import com.dumbdogdiner.stickyapi.annotation.Untested; import com.dumbdogdiner.stickyapi.common.configuration.providers.YamlProvider; @@ -68,18 +70,22 @@ public static LocaleProvider setupLocale(@NotNull Plugin plugin, @Nullable Local if (!localeEnabled) { plugin.getLogger() .severe("Failed to configure default locale file - perhaps you deleted it? Will create a new one."); - // FIXME: This is horrible and needs to be improved try { - // Step 1:Load the yml from plugin.getResource (the internal .jar resource) + // Step 1: Make sure the locale file exists (returns null if not found) + InputStream localeFile = plugin.getResourceAsStream("messages.en_us.yml"); + + // Step 1.5: Throw an exception if the file doesn't exist + if (localeFile == null) + throw new FileNotFoundException("The locale file was not found in our embedded resources!"); + + // Step 2:Load the yml from plugin.getResource (the internal .jar resource) YamlProvider embeddedMessagesResource = new YamlProvider(plugin.getResourceAsStream("messages.en_us.yml")); - // Step 2: Create a File instance representing our output dir in the plugin's - // data folder + // Step 3: Create a File instance representing our output dir in the plugin's data folder File outputLocation = new File(localeProvider.getLocaleFolder(), "messages.en_us.yml"); - // outputLocation should now be something like - // [..]/plugins/[..]/locale/messages.en_us.yml + // outputLocation should now be something like [..]/plugins/[..]/locale/messages.en_us.yml - // Step 3: write the embedded messages resource to the plugin data dir + // Step 4: write the embedded messages resource to the plugin data dir embeddedMessagesResource.save(outputLocation); } catch (Exception e) { e.printStackTrace();