diff --git a/api/src/main/java/me/lokka30/treasury/api/economy/EconomyProvider.java b/api/src/main/java/me/lokka30/treasury/api/economy/EconomyProvider.java index 4125e840..c5e52dc1 100644 --- a/api/src/main/java/me/lokka30/treasury/api/economy/EconomyProvider.java +++ b/api/src/main/java/me/lokka30/treasury/api/economy/EconomyProvider.java @@ -7,6 +7,7 @@ import java.util.Collection; import java.util.HashSet; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -310,15 +311,48 @@ default void retrieveAllAccountsPlayerHasPermission( @NotNull Currency getPrimaryCurrency(); /** - * Get the {@link UUID} of the primary or main {@link Currency} of the economy. + * Used to find a currency based on a specific identifier. * - * @return the {@code UUID} identifying the primary currency + * @param identifier The {@link Currency#getIdentifier()} of the {@link Currency} we are searching for. + * @return The {@link Optional} containing the search result. This will contain the + * resulting {@link Currency} if it exists, otherwise it will return {@link Optional#empty()}. + * @author creatorfromhell + * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} + */ + Optional findCurrency(@NotNull String identifier); + + /** + * Used to get a set of every {@link Currency} object for the server. + * + * @return A set of every {@link Currency} object that is available for the server. + * @author creatorfromhell + * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} + */ + Set getCurrencies(); + + /** + * Get the String identifier of the primary or main {@link Currency} of the economy. + * + * @return the String identifier identifying the primary currency * @author lokka30 * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} */ @NotNull - default UUID getPrimaryCurrencyId() { - return getPrimaryCurrency().getCurrencyId(); + default String getPrimaryCurrencyId() { + return getPrimaryCurrency().getIdentifier(); } + /** + * Used to register a currency with the {@link EconomyProvider} to be utilized by + * other plugins. + * + * @param currency The currency to register with the {@link EconomyProvider}. + * @param subscription The {@link EconomySubscriber} representing the result of the + * attempted {@link Currency} registration with an {@link Boolean}. + * This will be {@link Boolean#TRUE} if it was registered, otherwise + * it'll be {@link Boolean#FALSE}. + * @author creatorfromhell + * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} + */ + void registerCurrency(@NotNull Currency currency, @NotNull EconomySubscriber subscription); } diff --git a/api/src/main/java/me/lokka30/treasury/api/economy/account/Account.java b/api/src/main/java/me/lokka30/treasury/api/economy/account/Account.java index 151fa6a9..2fe6a1a3 100644 --- a/api/src/main/java/me/lokka30/treasury/api/economy/account/Account.java +++ b/api/src/main/java/me/lokka30/treasury/api/economy/account/Account.java @@ -285,13 +285,13 @@ public void fail(@NotNull EconomyException exception) { void deleteAccount(@NotNull EconomySubscriber subscription); /** - * Returns the {@link Currency Currencies} this {@code Account} holds balance for. + * Returns the {@link Currency#getIdentifier() Currencies} this {@code Account} holds balance for. * * @param subscription the {@link EconomySubscriber} accepting the currencies * @author MrIvanPlays * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} */ - void retrieveHeldCurrencies(@NotNull EconomySubscriber> subscription); + void retrieveHeldCurrencies(@NotNull EconomySubscriber> subscription); /** * Request the {@link EconomyTransaction} history, limited by the {@code transactionCount} and the {@link Temporal} diff --git a/api/src/main/java/me/lokka30/treasury/api/economy/currency/Currency.java b/api/src/main/java/me/lokka30/treasury/api/economy/currency/Currency.java index 4ac7f255..9edadead 100644 --- a/api/src/main/java/me/lokka30/treasury/api/economy/currency/Currency.java +++ b/api/src/main/java/me/lokka30/treasury/api/economy/currency/Currency.java @@ -5,10 +5,8 @@ package me.lokka30.treasury.api.economy.currency; import java.util.Locale; -import java.util.Objects; import java.util.UUID; -import java.util.function.BiFunction; -import java.util.function.Function; +import me.lokka30.treasury.api.economy.response.EconomySubscriber; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -19,218 +17,133 @@ * plugin can award players 'Tokens', but a job plugin * can award players 'Dollars'. Facilitates great customisability. * - * @author lokka30, Geolykt, MrIvanPlays + * @author creatorfromhell * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} */ -public class Currency { +public interface Currency { /** - * Creates a new currency with random {@link UUID} {@code currencyId} and a {@code startingBalance} handler of - * always returning 0. + * Gets the unique non-user friendly identifier for the currency. * - * @param currencyChar a way to identify the currency via a character e.g. '$' for a dollar. can be null. - * @param roundedDigits to which digit shall we round balances. can specify -1 for no rounding. - * @param conversionCoefficient coefficient at which this currency is going to be converted to other currencies. - * @param balanceFormatter a function, giving a human-readable format of a balance. - * @param names acceptable names of the currency. primary name shall be the first specified. - * @return new currency instance - * @author MrIvanPlays + * @return A unique non-user friendly identifier for the currency. + * @author creatorfromhell * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} */ - @NotNull - public static Currency of( - @Nullable Character currencyChar, - int roundedDigits, - double conversionCoefficient, - @NotNull BiFunction balanceFormatter, - @NotNull String @NotNull ... names - ) { - return new Currency( - null, - currencyChar, - roundedDigits, - conversionCoefficient, - null, - balanceFormatter, - names - ); - } + String getIdentifier(); /** - * Creates a new currency. + * Gets the currency's symbol. This could be something as simple as a dollar sign '$'. * - * @param currencyId the currency id. - * @param currencyChar a way to identify the currency via a character e.g. '$' for a dollar. can be null. - * @param roundedDigits to which digit shall we round balances. can specify -1 for no rounding. - * @param conversionCoefficient coefficient at which this currency is going to be converted to other currencies. - * @param startingBalance a function, giving a starting balance for the inputted player uuid, which can be null. - * @param balanceFormatter a function, giving a human-readable format of a balance. - * @param names acceptable names of the currency. primary name shall be the first specified. - * @return new currency instance - * @author MrIvanPlays + * @return The currency's symbol. + * @author creatorfromhell * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} */ - @NotNull - public static Currency of( - @NotNull UUID currencyId, - @Nullable Character currencyChar, - int roundedDigits, - double conversionCoefficient, - @Nullable Function startingBalance, - @NotNull BiFunction balanceFormatter, - @NotNull String @NotNull ... names - ) { - Objects.requireNonNull(currencyId, "currencyId"); - return new Currency( - currencyId, - currencyChar, - roundedDigits, - conversionCoefficient, - startingBalance, - balanceFormatter, - names - ); - } - - private final UUID currencyId; - private final Character currencyChar; - private final String[] names; - private final int roundedDigits; - private double conversionCoefficient; - private final Function startingBalance; - private final BiFunction balanceFormatter; - - private Currency( - @Nullable UUID currencyId, - @Nullable Character currencyChar, - int roundedDigits, - double conversionCoefficient, - @Nullable Function startingBalance, - @NotNull BiFunction balanceFormatter, - @NotNull String @NotNull ... names - ) { - if (names.length < 1) { - throw new IllegalArgumentException("Empty array specified for currency name."); - } - this.balanceFormatter = Objects.requireNonNull(balanceFormatter, "balanceFormatter"); - this.names = Objects.requireNonNull(names, "names"); - this.currencyId = currencyId == null ? UUID.randomUUID() : currencyId; - this.currencyChar = currencyChar; - this.roundedDigits = roundedDigits; - this.conversionCoefficient = conversionCoefficient; - this.startingBalance = startingBalance == null ? ($) -> 0d : startingBalance; - } + String getSymbol(); /** - * Gets the {@link UUID} of the currency. + * Get's the currency's decimal character to be used for formatting purposes. * - * @return the UUID of the currency - * @author lokka30, MrIvanPlays + * @return The currency's decimal character. + * @author creatorfromhell * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} */ - @NotNull - public UUID getCurrencyId() { - return currencyId; - } + char getDecimal(); /** - * Gets the character which identifies this currency, which may be null. + * Gets the currency's user-friendly display name. * - * @return char identifier. could be null - * @author MrIvanPlays + * @return The currency's user-friendly display name. + * @author creatorfromhell * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} */ - @Nullable - public Character getCurrencyCharacter() { - return currencyChar; - } + String getDisplayName(); /** - * Get the primary name of the currency, e.g. 'dollar' or 'token'. + * Gets the plural form of the currency's user-friendly display name. * - * @return the name of the currency - * @author lokka30, MrIvanPlays + * @return The plural form of the currency's user-friendly display name. + * @author creatorfromhell * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} */ - @NotNull - public String getPrimaryCurrencyName() { - return names[0]; - } + String getDisplayNamePlural(); /** - * Get the acceptable currency names. Used for parsing. + * Gets the currency's default number of decimal digits when formatting this currency. * - * @return acceptable currency names - * @author MrIvanPlays + * @return The currency's default number of decimal digits when formatting this currency. + * @author creatorfromhell * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} */ - @NotNull - public String @NotNull [] getCurrencyNames() { - return names; - } + int getPrecision(); /** - * Some economy providers like to round balances' decimals. - * Economy providers that do not round any digits should specify `-1`. + * Checks if this currency is the default currency to use. * - * @return how many rounded digits the provider uses, or `-1` for none - * @author lokka30, MrIvanPlays + * @return True if this currency is the default currency. This method should use a global + * context if multi-world support is not present, otherwise it should use the default world + * for this check. + * @author creatorfromhell * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} */ - public int getRoundedDigits() { - return roundedDigits; - } + boolean isDefault(); /** - * Get the conversion coefficient of this currency. + * Used to convert this {@link Currency} to another based on a specified amount of the other + * currency. * - * @return conversion coefficient - * @author MrIvanPlays + * @param currency The currency we are converting to. + * @param amount The amount to be converted to the specified {@link Currency} + * @param subscription The {@link EconomySubscriber} accepting the resulting {@link Double} that + * represents the converted amount of the specified {@link Currency}. + * @author creatorfromhell * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} */ - public double getConversionCoefficient() { - return conversionCoefficient; - } + void to(@NotNull Currency currency, double amount, @NotNull EconomySubscriber subscription); /** - * Sets a new conversion coefficient of this currency. + * Used to get the double representation of an amount represented by a formatted string. * - * @param conversionCoefficient new conversion coefficient - * @author MrIvanPlays + * @param formatted The formatted string to be converted to double form. + * @param subscription The {@link EconomySubscriber} accepting the resulting {@link Double} that + * represents the deformatted amount of the formatted String. + * @author creatorfromhell * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} */ - protected void setConversionCoefficient(double conversionCoefficient) { - this.conversionCoefficient = conversionCoefficient; - } + void parse(@NotNull String formatted, @NotNull EconomySubscriber subscription); /** - * Get the starting balance of the currency. - * The player {@link UUID} is nullable, it should be specified if the starting balance - * concerns a {@link me.lokka30.treasury.api.economy.account.PlayerAccount}. + * Gets the starting balance of a specific player account for this currency. * - * @param playerUUID a UUID of the player account created. For global scenarios, specify `null`. - * @return the starting balance of the currency concerning specified player's UUID. - * @author lokka30, Geolykt, MrIvanPlays + * @param playerID The UUID of the player we are getting the starting balance for. + * @return The starting balance of the player for this currency. + * @author creatorfromhell * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} */ - public double getStartingBalance(@Nullable UUID playerUUID) { - return startingBalance.apply(playerUUID); - } + double getStartingBalance(@Nullable UUID playerID); /** - * Gets a human-readable format of the balance. - * For example, '$1.50' or '1.50 dollars' or 'One dollar and fifty cents'. + * Used to translate an amount to a user readable format with the default precision. * - * @param amount to be formatted. - * @param locale of the formatted balance being requested. - * @return the human-readable format of the specified amount and locale. - * @author lokka30, MrIvanPlays + * @param amount The amount to format. + * @param locale The locale to use for formatting the balance. This value may be null if the + * provider should provide the default Locale. + * @return The formatted text. + * @author creatorfromhell * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} */ - @NotNull - public String formatBalance(double amount, @NotNull Locale locale) { - Objects.requireNonNull(locale, "locale"); - return balanceFormatter.apply(amount, locale); - } + String format(double amount, @Nullable Locale locale); + + /** + * Used to translate an amount to a user readable format with the specified amount of decimal places. + * + * @param amount The amount to format. + * @param locale The locale to use for formatting the balance. This value may be null if the + * * provider should provide the default Locale. + * @param precision The amount of decimal digits to use when formatting. + * @return The formatted text. + * @author creatorfromhell + * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} + */ + String format(double amount, @Nullable Locale locale, int precision); } diff --git a/api/src/main/java/me/lokka30/treasury/api/economy/currency/CurrencyManager.java b/api/src/main/java/me/lokka30/treasury/api/economy/currency/CurrencyManager.java deleted file mode 100644 index 53e679aa..00000000 --- a/api/src/main/java/me/lokka30/treasury/api/economy/currency/CurrencyManager.java +++ /dev/null @@ -1,375 +0,0 @@ -/* - * This file is/was part of Treasury. To read more information about Treasury such as its licensing, see . - */ - -package me.lokka30.treasury.api.economy.currency; - -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import org.jetbrains.annotations.NotNull; - -/** - * Represents a manager of {@link Currency currencies}. - * - * @author MrIvanPlays - * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} - */ -public enum CurrencyManager { - INSTANCE; - - private Map BY_NAME = new ConcurrentHashMap<>(); - private Map BY_CHAR = new ConcurrentHashMap<>(); - private Map BY_ID = new ConcurrentHashMap<>(); - - /** - * Registers a new {@link Currency}. - * - * @param currency the currency you want to register - * @throws IllegalArgumentException if the currency is already registered in at least one of the 3 types of identification. - * @author MrIvanPlays - * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} - */ - public void registerCurrency(@NotNull Currency currency) { - Objects.requireNonNull(currency, "currency"); - - if (currency.getCurrencyCharacter() != null) { - if (hasCurrency(currency.getCurrencyCharacter())) { - throw new IllegalArgumentException( - "Currency already registered with currency char '" + currency.getCurrencyCharacter() + "'" - ); - } - } - - boolean foundRegistration = false; - String name = ""; - for (String acceptableName : currency.getCurrencyNames()) { - if (hasCurrency(acceptableName)) { - foundRegistration = true; - name = acceptableName; - break; - } - } - if (foundRegistration) { - throw new IllegalArgumentException("Currency already registered with currency name '" + name + "'"); - } - - if (hasCurrency(currency.getCurrencyId())) { - throw new IllegalArgumentException("Currency already registered with currency id '" + currency.getCurrencyId() + "'"); - } - - BY_ID.put(currency.getCurrencyId(), currency); - for (String acceptableName : currency.getCurrencyNames()) { - BY_NAME.put(acceptableName, currency.getCurrencyId()); - } - if (currency.getCurrencyCharacter() != null) { - BY_CHAR.put(currency.getCurrencyCharacter(), currency.getCurrencyId()); - } - } - - /** - * @param currencies currencies to register - * @see #registerCurrency(Currency) - */ - public void registerCurrencies(@NotNull Currency @NotNull ... currencies) { - Objects.requireNonNull(currencies, "currencies"); - for (Currency currency : currencies) { - registerCurrency(currency); - } - } - - /** - * @param currencies currencies to register - * @see #registerCurrency(Currency) - */ - public void registerCurrencies(@NotNull Iterable<@NotNull Currency> currencies) { - Objects.requireNonNull(currencies, "currencies"); - for (Currency currency : currencies) { - registerCurrency(currency); - } - } - - /** - * Unregisters the specified {@link Currency} {@code currency} if it has been registered. - * - * @param currency the currency you want unregistered - * @author MrIvanPlays - * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} - */ - public void unregisterCurrency(@NotNull Currency currency) { - Objects.requireNonNull(currency, "currency"); - BY_ID.remove(currency.getCurrencyId()); - for (String acceptableName : currency.getCurrencyNames()) { - BY_NAME.remove(acceptableName); - } - if (currency.getCurrencyCharacter() != null) { - BY_CHAR.remove(currency.getCurrencyCharacter()); - } - } - - /** - * @param currencies the currencies you want unregistered - * @see #unregisterCurrency(Currency) - */ - public void unregisterCurrencies(@NotNull Currency @NotNull ... currencies) { - Objects.requireNonNull(currencies, "currencies"); - for (Currency currency : currencies) { - unregisterCurrency(currency); - } - } - - /** - * @param currencies the currencies you want unregistered - * @see #unregisterCurrency(Currency) - */ - public void unregisterCurrencies(@NotNull Iterable<@NotNull Currency> currencies) { - Objects.requireNonNull(currencies, "currencies"); - for (Currency currency : currencies) { - unregisterCurrency(currency); - } - } - - /** - * Unregisters the {@link Currency} which has been registered with the specified {@link UUID} {@code currencyId} if - * it is present. - * - * @param currencyId the id of the currency you want unregistered - * @author MrIvanPlays - * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} - */ - public void unregisterCurrency(@NotNull UUID currencyId) { - getCurrency(currencyId).ifPresent(this::unregisterCurrency); - } - - /** - * @param currencyIds currency ids to unregister - * @see #unregisterCurrency(UUID) - */ - public void unregisterCurrencies(@NotNull UUID @NotNull ... currencyIds) { - Objects.requireNonNull(currencyIds, "currencyIds"); - for (UUID currencyId : currencyIds) { - unregisterCurrency(currencyId); - } - } - - /** - * @param currencyIds currency ids to unregister - * @see #unregisterCurrency(UUID) - */ - public void unregisterCurrenciesById(@NotNull Iterable<@NotNull UUID> currencyIds) { - Objects.requireNonNull(currencyIds, "currencyIds"); - for (UUID currencyId : currencyIds) { - unregisterCurrency(currencyId); - } - } - - /** - * Returns whether there is a {@link Currency} registered with the specified {@link UUID} {@code currencyId}. - * - * @param currencyId currency id you want to check if busy - * @return boolean value - * @author MrIvanPlays - * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} - */ - public boolean hasCurrency(@NotNull UUID currencyId) { - Objects.requireNonNull(currencyId, "currencyId"); - return BY_ID.containsKey(currencyId); - } - - /** - * Returns whether there is a {@link Currency} registered with the specified {@link String} {@code currencyName}. - * - * @param currencyName currency name to check if busy - * @return boolean value - * @author MrIvanPlays - * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} - */ - public boolean hasCurrency(@NotNull String currencyName) { - Objects.requireNonNull(currencyName, "currencyName"); - return BY_NAME.containsKey(currencyName); - } - - /** - * Returns whether there is a {@link Currency} registered with the specified {@link Character} {@code currencyCharacter}. - * - * @param currencyCharacter currency character to check if busy - * @return boolean value - * @author MrIvanPlays - * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} - */ - public boolean hasCurrency(@NotNull Character currencyCharacter) { - Objects.requireNonNull(currencyCharacter, "currencyCharacter"); - return BY_CHAR.containsKey(currencyCharacter); - } - - /** - * Returns the {@link Currency} bound to the specified {@link UUID} {@code currencyId}, if present. - * - * @param currencyId currency id you want the currency of - * @return currency if present, empty optional otherwise - * @author MrIvanPlays - * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} - */ - public Optional getCurrency(@NotNull UUID currencyId) { - Objects.requireNonNull(currencyId, "currencyId"); - return Optional.ofNullable(BY_ID.get(currencyId)); - } - - /** - * Returns the {@link Currency} bound to the specified {@link String} {@code currencyName}, if present. - * - * @param currencyName the name of the currency needed - * @return currency if present, empty optional otherwise - * @author MrIvanPlays - * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} - */ - public Optional getCurrency(@NotNull String currencyName) { - if (!hasCurrency(currencyName)) { - return Optional.empty(); - } - UUID currencyId = null; - for (String key : BY_NAME.keySet()) { - if (key.equalsIgnoreCase(currencyName)) { - currencyId = BY_NAME.get(key); - break; - } - } - if (currencyId != null) { - return getCurrency(currencyId); - } else { - return Optional.empty(); - } - } - - /** - * Returns the {@link Currency} bound to the specified {@link Character} {@code currencyCharacter}, if present. - * - * @param currencyCharacter the character of the currency needed - * @return currency if present, empty optional otherwise - * @author MrIvanPlays - * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} - */ - public Optional getCurrency(@NotNull Character currencyCharacter) { - if (!hasCurrency(currencyCharacter)) { - return Optional.empty(); - } - return Optional.of(BY_ID.get(BY_CHAR.get(currencyCharacter))); - } - - /** - * Converts the specified {@code value} from the {@link Currency} {@code from} to the {@link Currency} {@code to} by - * using their {@link Currency#getConversionCoefficient()}. - * - * @param from the currency to convert from - * @param to the currency to convert to - * @param value the value to convert - * @return converted value - * @throws IllegalArgumentException if one or both of the currencies are not registered - * @author MrIvanPlays, MrNemo64 - * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} - */ - public double convertCurrency(@NotNull Currency from, @NotNull Currency to, double value) { - Objects.requireNonNull(from, "from"); - Objects.requireNonNull(to, "to"); - if (!hasCurrency(from.getCurrencyId()) || !hasCurrency(to.getCurrencyId())) { - throw new IllegalArgumentException("Specified currencies are unknown to the currency manager"); - } - if (from.getConversionCoefficient() == 0 || to.getConversionCoefficient() == 0 || value == 0) { - return 0; - } - // thanks MrNemo64 for the formula - // see https://github.com/lokka30/Treasury/issues/49#issuecomment-986255592 for an explanation - double generalAmount = value * from.getConversionCoefficient(); - return generalAmount / to.getConversionCoefficient(); - } - - /** - * Converts the specified {@code value} from the {@link UUID} {@code fromId}, associated with a {@link Currency} to - * the {@link UUID} {@code toId}, associated with a {@link Currency} by using their {@link Currency#getConversionCoefficient()}. - * - * @param fromId the currency id to convert from - * @param toId the currency id to convert to - * @param value the value to convert - * @return converted value - * @throws IllegalArgumentException if one or both of the currencies are not registered - * @author MrNemo64, MrIvanPlays - * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} - */ - public double convertCurrency(@NotNull UUID fromId, @NotNull UUID toId, double value) { - if (value == 0) { - return 0; - } - Optional fromCurrency = getCurrency(fromId); - Optional toCurrency = getCurrency(toId); - if (!fromCurrency.isPresent() || !toCurrency.isPresent()) { - throw new IllegalArgumentException( - "Specified currency id(s) is/are not registered with any currency in the currency manager." - ); - } - return convertCurrency(fromCurrency.get(), toCurrency.get(), value); - } - - /** - * Tries to extract the {@link Currency} and the value encapsulated into the specified {@code input}. - * - * @param input the string to parse. - * @return parse result - * @author MrIvanPlays, MrNemo64 - * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} - */ - @NotNull - public CurrencyParseResult parseCurrencyAndValue(@NotNull String input) { - Objects.requireNonNull(input, "input"); - StringBuilder currency = new StringBuilder(); - StringBuilder value = new StringBuilder(); - boolean hadSeparator = false; - for (char c : input.toCharArray()) { - if (Character.isWhitespace(c)) { - continue; - } - if (!Character.isDigit(c) && !isSeparator(c)) { - currency.append(c); - } else if (Character.isDigit(c)) { - value.append(c); - } else if (isSeparator(c)) { - boolean nowChanged = false; - if (!hadSeparator) { - hadSeparator = true; - nowChanged = true; - } - if (!nowChanged) { - value = new StringBuilder(); - break; - } - value.append(c); - } - } - Optional currencyOpt; - if (currency.length() == 1) { - currencyOpt = getCurrency(currency.charAt(0)); - } else { - currencyOpt = getCurrency(currency.toString()); - } - - if (!currencyOpt.isPresent()) { - return CurrencyParseResult.failure(CurrencyParseResult.State.UNKNOWN_CURRENCY); - } - if (value.length() == 0) { - return CurrencyParseResult.failure(CurrencyParseResult.State.INVALID_VALUE); - } - - double val; - try { - val = Double.parseDouble(value.toString()); - } catch (NumberFormatException e) { - return CurrencyParseResult.failure(CurrencyParseResult.State.INVALID_VALUE); - } - return CurrencyParseResult.success(val, currencyOpt); - } - - private boolean isSeparator(char c) { - return c == '.' || c == ',' || c == '\''; - } -} diff --git a/api/src/main/java/me/lokka30/treasury/api/economy/currency/CurrencyParseResult.java b/api/src/main/java/me/lokka30/treasury/api/economy/currency/CurrencyParseResult.java deleted file mode 100644 index 029ff203..00000000 --- a/api/src/main/java/me/lokka30/treasury/api/economy/currency/CurrencyParseResult.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * This file is/was part of Treasury. To read more information about Treasury such as its licensing, see . - */ - -package me.lokka30.treasury.api.economy.currency; - -import java.util.Objects; -import java.util.Optional; -import java.util.OptionalDouble; -import org.jetbrains.annotations.NotNull; - -/** - * Represents a result of parsing an {@link String} input to a - * {@link Double} {@code value} and a {@link Currency} {@code currency}. - * - *

Example: "$20", "USD20", "dola20" ; this gets parsed to currency of 'dollar' and value of '20' if there is such - * currency registered with a character '$' and the names specified. - * - * @author MrIvanPlays - * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} - */ -public final class CurrencyParseResult { - - /** - * Represents a stated result of a {@link CurrencyParseResult} - * - * @author MrIvanPlays - * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} - */ - public enum State { - - /** - * State indicates successful parse. - * - * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} - */ - SUCCESS, - - /** - * State indicates unknown currency was inputted. - * - * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} - */ - UNKNOWN_CURRENCY, - - /** - * State indicates invalid value was inputted. An invalid value may be a value which does not - * consist of numbers. - * - * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} - */ - INVALID_VALUE - } - - /** - * Creates a new {@link CurrencyParseResult}, indicating a successful parse. - * - * @param value the value which got parsed - * @param currencyOptional the currency optional - * @return successful parse result - * @author MrIvanPlays - * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} - */ - @NotNull - public static CurrencyParseResult success(double value, Optional currencyOptional) { - return new CurrencyParseResult(State.SUCCESS, OptionalDouble.of(value), currencyOptional); - } - - /** - * Creates a new {@link CurrencyParseResult}, which is not indicating successful parse. - * - * @param state the state/reason why parsing failed - * @return state only parse result - * @author MrIvanPlays - * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} - */ - @NotNull - public static CurrencyParseResult failure(@NotNull State state) { - return new CurrencyParseResult(state, OptionalDouble.empty(), Optional.empty()); - } - - private final State state; - private final OptionalDouble value; - private final Optional currency; - - private CurrencyParseResult(@NotNull State state, @NotNull OptionalDouble value, @NotNull Optional currency) { - this.state = Objects.requireNonNull(state, "state"); - this.value = value; - this.currency = currency; - } - - /** - * Get the state of this parse result. - * - * @return state - * @author MrIvanPlays - * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} - */ - @NotNull - public State getState() { - return state; - } - - /** - * Get the value parsed. - * - * @return value parsed, or empty optional - * @author MrIvanPlays - * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} - */ - public OptionalDouble getValue() { - return value; - } - - /** - * Get the currency parsed. - * - * @return parsed currency, or empty optional - * @author MrIvanPlays - * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} - */ - public Optional getCurrency() { - return currency; - } - -} diff --git a/api/src/main/java/me/lokka30/treasury/api/economy/transaction/EconomyTransaction.java b/api/src/main/java/me/lokka30/treasury/api/economy/transaction/EconomyTransaction.java index 6bacffad..74648e32 100644 --- a/api/src/main/java/me/lokka30/treasury/api/economy/transaction/EconomyTransaction.java +++ b/api/src/main/java/me/lokka30/treasury/api/economy/transaction/EconomyTransaction.java @@ -34,7 +34,7 @@ public static Builder newBuilder() { private final double transactionAmount; @NotNull - private final UUID currencyUUID; + private final String currencyID; @NotNull private final EconomyTransactionInitiator initiator; @NotNull @@ -46,7 +46,7 @@ public static Builder newBuilder() { /** * Creates a new account transaction object. * - * @param currencyUUID the currency's UUID the transaction was made into + * @param currencyID the currency's {@link Currency#getIdentifier() identifier} the transaction was made into * @param initiator the one who initiated the transaction * @param timestamp the time at which this transaction occurred. specifying null would mean "now" * @param economyTransactionType the transaction type @@ -55,14 +55,14 @@ public static Builder newBuilder() { * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} */ public EconomyTransaction( - @NotNull UUID currencyUUID, + @NotNull String currencyID, @NotNull EconomyTransactionInitiator initiator, @Nullable Temporal timestamp, @NotNull EconomyTransactionType economyTransactionType, @Nullable String reason, final double transactionAmount ) { - this.currencyUUID = Objects.requireNonNull(currencyUUID, "currencyUUID"); + this.currencyID = Objects.requireNonNull(currencyID, "currencyID"); this.initiator = Objects.requireNonNull(initiator, "initiator"); this.economyTransactionType = Objects.requireNonNull(economyTransactionType, "transactionType"); this.reason = Optional.ofNullable(reason); @@ -93,17 +93,18 @@ public EconomyTransactionType getTransactionType() { } /** - * Returns the {@link me.lokka30.treasury.api.economy.currency.Currency}'s {@link UUID} with which the transaction was made. + * Returns the {@link me.lokka30.treasury.api.economy.currency.Currency}'s {@link Currency#getIdentifier() identifier } with + * which the transaction was made. * - *

A {@code Currency} object is retrievable via the {@link me.lokka30.treasury.api.economy.currency.CurrencyManager} if + *

A {@code Currency} object is retrievable via {@link me.lokka30.treasury.api.economy.EconomyProvider#findCurrency(String)} if * you need such. * - * @return currency + * @return The currency {@link Currency#getIdentifier() identifier}. * @since {@link me.lokka30.treasury.api.economy.misc.EconomyAPIVersion#v1_0 v1.0} */ @NotNull - public UUID getCurrencyUniqueId() { - return currencyUUID; + public String getCurrencyID() { + return currencyID; } /** @@ -142,7 +143,7 @@ public Optional getReason() { */ public static class Builder { - private UUID currencyUUID; + private String currencyID; private EconomyTransactionInitiator initiator; private Temporal timestamp; private EconomyTransactionType economyTransactionType; @@ -158,7 +159,7 @@ public Builder() { * @param other the other builder to create a new builder from */ public Builder(Builder other) { - this.currencyUUID = other.currencyUUID; + this.currencyID = other.currencyID; this.initiator = other.initiator; this.timestamp = other.timestamp; this.economyTransactionType = other.economyTransactionType; @@ -182,18 +183,18 @@ public Builder copy() { * @return this instance for chaining */ public Builder withCurrency(@NotNull Currency currency) { - this.currencyUUID = Objects.requireNonNull(currency, "currency").getCurrencyId(); + this.currencyID = Objects.requireNonNull(currency, "currency").getIdentifier(); return this; } /** - * Specify the {@link UUID} {@code currencyId} of a {@link Currency} the transaction was made in. + * Specify the {@link Currency#getIdentifier() identifier} of a {@link Currency} the transaction was made in. * * @param currencyId currency id * @return this instance for chaining */ - public Builder withCurrencyId(@NotNull UUID currencyId) { - this.currencyUUID = Objects.requireNonNull(currencyId, "currencyId"); + public Builder withCurrencyId(@NotNull String currencyId) { + this.currencyID = Objects.requireNonNull(currencyId, "currencyId"); return this; } @@ -259,11 +260,11 @@ public Builder withTransactionAmount(double transactionAmount) { * @return transaction object */ public EconomyTransaction build() { - Objects.requireNonNull(currencyUUID, "currencyUUID"); + Objects.requireNonNull(currencyID, "currencyID"); Objects.requireNonNull(initiator, "initiator"); Objects.requireNonNull(economyTransactionType, "transactionType"); Objects.requireNonNull(transactionAmount, "transactionAmount"); - return new EconomyTransaction(currencyUUID, initiator, timestamp, economyTransactionType, reason, transactionAmount); + return new EconomyTransaction(currencyID, initiator, timestamp, economyTransactionType, reason, transactionAmount); } } diff --git a/api/src/test/java/me/lokka30/treasury/api/economy/currency/CurrencyTests.java b/api/src/test/java/me/lokka30/treasury/api/economy/currency/CurrencyTests.java deleted file mode 100644 index 37d71824..00000000 --- a/api/src/test/java/me/lokka30/treasury/api/economy/currency/CurrencyTests.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * This file is/was part of Treasury. To read more information about Treasury such as its licensing, see . - */ - -package me.lokka30.treasury.api.economy.currency; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -public class CurrencyTests { - - private static Currency euro; - private static Currency dollar; - - @BeforeAll - public static void registerCurrencies() { - euro = Currency.of( - '€', - -1, - 1, - (value, locale) -> "€" + value, - "euro", - "EUR" - ); - dollar = Currency.of( - '$', - -1, - 0.884059, - (value, locale) -> "$" + value, - "dollar", - "USD" - ); - CurrencyManager.INSTANCE.registerCurrency(dollar); - CurrencyManager.INSTANCE.registerCurrency(euro); - } - - @Test - public void testConvertEuroToDollar() { - double converted = CurrencyManager.INSTANCE.convertCurrency(euro, dollar, 1); - Assertions.assertEquals(1.1311462244035748, converted); - } - - @Test - public void testConvertDollarToEuro() { - double converted = CurrencyManager.INSTANCE.convertCurrency(dollar, euro, 1); - Assertions.assertEquals(0.884059, converted); - } - - @Test - public void testParsingDollar() { - Assertions.assertEquals('$', parseCurrency("1dollar")); - Assertions.assertEquals('$', parseCurrency("$1")); - Assertions.assertEquals('$', parseCurrency("1$")); - Assertions.assertEquals('$', parseCurrency("dollar1")); - } - - @Test - public void testParsingEuro() { - Assertions.assertEquals('€', parseCurrency("1euro")); - Assertions.assertEquals('€', parseCurrency("€1")); - Assertions.assertEquals('€', parseCurrency("1€")); - Assertions.assertEquals('€', parseCurrency("euro1")); - } - - private Character parseCurrency(String input) { - Currency currency = CurrencyManager.INSTANCE.parseCurrencyAndValue(input).getCurrency().orElse(null); - return currency == null ? null : currency.getCurrencyCharacter(); - } - -} diff --git a/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/economy/EconomyInfoSub.java b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/economy/EconomyInfoSub.java index 60ee05f7..9e1c3c5e 100644 --- a/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/economy/EconomyInfoSub.java +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/economy/EconomyInfoSub.java @@ -56,7 +56,7 @@ public void execute(@NotNull final CommandSource sender, @NotNull final String l .getSupportedOptionalEconomyApiFeatures() .contains(OptionalEconomyApiFeature.BUKKIT_TRANSACTION_EVENTS)) ), - placeholder("primary-currency", provider.getPrimaryCurrency().getPrimaryCurrencyName()) + placeholder("primary-currency", provider.getPrimaryCurrency().getIdentifier()) )); } } diff --git a/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/economy/migrate/AccountMigrator.java b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/economy/migrate/AccountMigrator.java index b64af5bc..eca24da5 100644 --- a/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/economy/migrate/AccountMigrator.java +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/economy/migrate/AccountMigrator.java @@ -16,10 +16,10 @@ import me.lokka30.treasury.api.economy.EconomyProvider; import me.lokka30.treasury.api.economy.account.Account; import me.lokka30.treasury.api.economy.currency.Currency; -import me.lokka30.treasury.api.economy.currency.CurrencyManager; import me.lokka30.treasury.api.economy.response.EconomyException; import me.lokka30.treasury.api.economy.response.EconomySubscriber; import me.lokka30.treasury.api.economy.transaction.EconomyTransactionInitiator; +import me.lokka30.treasury.plugin.core.TreasuryPlugin; import org.jetbrains.annotations.NotNull; interface AccountMigrator { @@ -45,12 +45,12 @@ default void migrate( @NotNull T toAccount, @NotNull MigrationData migration ) { - CompletableFuture> fromCurrencies = new CompletableFuture<>(); + CompletableFuture> fromCurrencies = new CompletableFuture<>(); - fromAccount.retrieveHeldCurrencies(new PhasedSubscriber>(phaser) { + fromAccount.retrieveHeldCurrencies(new PhasedSubscriber>(phaser) { @Override - public void phaseAccept(@NotNull final Collection uuids) { - fromCurrencies.complete(uuids); + public void phaseAccept(@NotNull final Collection currencies) { + fromCurrencies.complete(currencies); } @Override @@ -60,13 +60,21 @@ public void phaseFail(@NotNull final EconomyException exception) { } }); - fromCurrencies.thenAccept(currencyIds -> { - Collection currencies = currencyIds.stream().map(uuid -> { - Optional currency = CurrencyManager.INSTANCE.getCurrency(uuid); - if (currency.isPresent()) { + fromCurrencies.thenAccept(currenciesIDS -> { + + Collection currencies = currenciesIDS.stream().map(identifier->{ + if(TreasuryPlugin.getInstance().economyProviderProvider() == null) { + migration.debug(() -> "Economy provider is null."); + return null; + } + + Optional currency = + TreasuryPlugin.getInstance().economyProviderProvider().provide().findCurrency(identifier); + + if(currency.isPresent()) { return currency.get(); } else { - migration.debug(() -> "Currency with ID '&b" + uuid + "&7' will " + "not be migrated."); + migration.debug(() -> "Currency with ID '&b" + identifier + "&7' will " + "not be migrated."); return null; } }).filter(Objects::nonNull).collect(Collectors.toList()); @@ -99,11 +107,11 @@ public void phaseFail(@NotNull final EconomyException exception) { migration.debug(() -> String.format( "Failed to recover from an issue transferring %s %s from %s, currency will not be migrated!", balance, - currency.getPrimaryCurrencyName(), + currency.getDisplayName(), fromAccount.getIdentifier() )); - if (!migration.nonMigratedCurrencies().contains(currency.getPrimaryCurrencyName())) { - migration.nonMigratedCurrencies().add(currency.getPrimaryCurrencyName()); + if (!migration.nonMigratedCurrencies().contains(currency.getIdentifier())) { + migration.nonMigratedCurrencies().add(currency.getIdentifier()); } })); }); diff --git a/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/economy/migrate/MigrationEconomy.java b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/economy/migrate/MigrationEconomy.java index fef69bd1..3336f6ce 100644 --- a/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/economy/migrate/MigrationEconomy.java +++ b/core/src/main/java/me/lokka30/treasury/plugin/core/command/subcommand/economy/migrate/MigrationEconomy.java @@ -7,6 +7,8 @@ import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.Locale; +import java.util.Optional; import java.util.Set; import java.util.UUID; import me.lokka30.treasury.api.economy.EconomyProvider; @@ -16,8 +18,8 @@ import me.lokka30.treasury.api.economy.misc.EconomyAPIVersion; import me.lokka30.treasury.api.economy.misc.OptionalEconomyApiFeature; import me.lokka30.treasury.api.economy.response.EconomyException; -import me.lokka30.treasury.api.economy.response.EconomySubscriber; import me.lokka30.treasury.api.economy.response.EconomyFailureReason; +import me.lokka30.treasury.api.economy.response.EconomySubscriber; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -32,8 +34,79 @@ class MigrationEconomy implements EconomyProvider { private final @NotNull EconomyException migrationException; MigrationEconomy() { - this.currency = Currency.of(null, 0, 1, (amt, $) -> String.valueOf(amt), "MigrationMoney"); - this.migrationException = new EconomyException(EconomyFailureReason.MIGRATION, "Economy unavailable during migration process."); + this.currency = new Currency() { + @Override + public String getIdentifier() { + return "MigrationMoney"; + } + + @Override + public String getSymbol() { + return "$"; + } + + @Override + public char getDecimal() { + return 0; + } + + @Override + public String getDisplayName() { + return "MigrationMoney"; + } + + @Override + public String getDisplayNamePlural() { + return "MigrationMonies"; + } + + @Override + public int getPrecision() { + return 0; + } + + @Override + public boolean isDefault() { + return false; + } + + @Override + public void to( + @NotNull final Currency currency, + final double amount, + @NotNull final EconomySubscriber subscription + ) { + subscription.fail(new EconomyException(EconomyFailureReason.MIGRATION, "Migration currency not convertable.")); + } + + @Override + public void parse(@NotNull final String formatted, @NotNull final EconomySubscriber subscription) { + subscription.fail(new EconomyException( + EconomyFailureReason.MIGRATION, + "Migration in progress, cannot deformat!" + )); + } + + @Override + public double getStartingBalance(@Nullable final UUID playerID) { + return 0; + } + + @Override + public String format(final double amount, @Nullable final Locale locale) { + return String.valueOf(amount); + } + + @Override + public String format(final double amount, @Nullable final Locale locale, final int precision) { + return String.valueOf(amount); + } + }; + this.migrationException = new EconomyException( + EconomyFailureReason.MIGRATION, + "Economy unavailable during migration process." + ); + } @Override @@ -103,4 +176,19 @@ public void retrieveNonPlayerAccountIds(@NotNull EconomySubscriber findCurrency(@NotNull final String identifier) { + return Optional.empty(); + } + + @Override + public Set getCurrencies() { + return new HashSet<>(); + } + + @Override + public void registerCurrency(@NotNull final Currency currency, @NotNull final EconomySubscriber subscription) { + subscription.fail(new EconomyException(EconomyFailureReason.MIGRATION, "Cannot register currencies during migration!")); + } + }