From bf8bca324474ad01bf7967ac6c8029820d07053a Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Tue, 29 Aug 2023 10:44:25 +0800 Subject: [PATCH] Specific flag builder for enum to streamline context and completion --- .../commands/CreateCommand.java | 16 +- .../commandtools/flags/CommandFlag.java | 15 +- .../commandtools/flags/CommandValueFlag.java | 139 +++++++++++++++--- 3 files changed, 128 insertions(+), 42 deletions(-) diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java index d4d8ea2b..2520c5bf 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/CreateCommand.java @@ -67,22 +67,8 @@ public class CreateCommand extends MultiverseCommand { .map(genplugin -> genplugin.getDescription().getName()) .collect(Collectors.toList())) .build()) - .add(CommandValueFlag.builder("--world-type", WorldType.class) + .add(CommandValueFlag.enumBuilder("--world-type", WorldType.class) .addAlias("-t") - .context((value) -> { - try { - return WorldType.valueOf(value.toUpperCase()); - } catch (IllegalArgumentException e) { - throw new InvalidCommandArgument("Invalid world type: " + value); - } - }) - .completion(() -> { - List types = new ArrayList<>(); - for (WorldType type : WorldType.values()) { - types.add(type.name().toLowerCase()); - } - return types; - }) .build()) .add(CommandFlag.builder("--adjust-spawn") .addAlias("-n") diff --git a/src/main/java/com/onarandombox/MultiverseCore/commandtools/flags/CommandFlag.java b/src/main/java/com/onarandombox/MultiverseCore/commandtools/flags/CommandFlag.java index 6323244e..0604f028 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commandtools/flags/CommandFlag.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commandtools/flags/CommandFlag.java @@ -26,11 +26,12 @@ public class CommandFlag { /** * Creates a new flag. * - * @param builder The builder. + * @param key The key for the new flag. + * @param aliases The aliases that also refer to this flag. */ - protected CommandFlag(@NotNull Builder builder) { - key = builder.key; - aliases = builder.aliases; + protected CommandFlag(@NotNull String key, @NotNull List aliases) { + this.key = key; + this.aliases = aliases; } /** @@ -57,8 +58,8 @@ public class CommandFlag { * @param The type of the builder. */ public static class Builder> { - private final String key; - private final List aliases; + protected final String key; + protected final List aliases; /** * Create a new builder. @@ -87,7 +88,7 @@ public class CommandFlag { * @return The flag. */ public @NotNull CommandFlag build(){ - return new CommandFlag(this); + return new CommandFlag(key, aliases); } } } diff --git a/src/main/java/com/onarandombox/MultiverseCore/commandtools/flags/CommandValueFlag.java b/src/main/java/com/onarandombox/MultiverseCore/commandtools/flags/CommandValueFlag.java index bf1a7034..558250ee 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commandtools/flags/CommandValueFlag.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commandtools/flags/CommandValueFlag.java @@ -1,12 +1,16 @@ package com.onarandombox.MultiverseCore.commandtools.flags; -import java.util.Collection; -import java.util.function.Function; -import java.util.function.Supplier; - +import co.aikar.commands.InvalidCommandArgument; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collectors; + /** * Represents a flag with a value. * @@ -16,14 +20,25 @@ public class CommandValueFlag extends CommandFlag { /** * A builder for a flag. * - * @param key The key for the new flag. - * @param type The type of the value. + * @param key The key for the new flag. + * @param type The type of the value. * @return The builder. */ public static @NotNull Builder builder(@NotNull String key, @NotNull Class type) { return new Builder<>(key, type); } + /** + * A builder for a flag with enum value. + * + * @param key The key for the new flag. + * @param type The type of the value, must be enum. + * @return The builder. + */ + public static @NotNull > EnumBuilder enumBuilder(@NotNull String key, @NotNull Class type) { + return new EnumBuilder<>(key, type); + } + private final Class type; private final boolean optional; private final T defaultValue; @@ -33,15 +48,29 @@ public class CommandValueFlag extends CommandFlag { /** * Creates a new flag. * - * @param builder The builder. + * @param key The key for the new flag. + * @param aliases The aliases that also refer to this flag. + * @param type The type of the value. + * @param optional Allow for flag without value. + * @param defaultValue The default value if optional is true and user does not specify a value. + * @param context Function to parse string into value type. + * @param completion Function to get completion for this flag. */ - protected CommandValueFlag(@NotNull Builder builder) { - super(builder); - type = builder.type; - optional = builder.optional; - defaultValue = builder.defaultValue; - context = builder.context; - completion = builder.completion; + protected CommandValueFlag( + @NotNull String key, + @NotNull List aliases, + @NotNull Class type, + boolean optional, + @Nullable T defaultValue, + @Nullable Function context, + @Nullable Supplier> completion + ) { + super(key, aliases); + this.type = type; + this.optional = optional; + this.defaultValue = defaultValue; + this.context = context; + this.completion = completion; } /** @@ -96,11 +125,11 @@ public class CommandValueFlag extends CommandFlag { * @param The type of the builder. */ public static class Builder> extends CommandFlag.Builder { - private final Class type; - private boolean optional = false; - private T defaultValue = null; - private Function context = null; - private Supplier> completion = null; + protected final Class type; + protected boolean optional = false; + protected T defaultValue = null; + protected Function context = null; + protected Supplier> completion = null; /** * Create a new builder. @@ -166,7 +195,77 @@ public class CommandValueFlag extends CommandFlag { if (context == null && !String.class.equals(type)) { throw new IllegalStateException("Context is required for none-string value flags"); } - return new CommandValueFlag<>(this); + return new CommandValueFlag<>(key, aliases, type, optional, defaultValue, context, completion); + } + } + + /** + * Specific builder for a flag with enum value. + * + * @param The type of the value. + * @param The type of the builder. + */ + public static class EnumBuilder, S extends EnumBuilder> extends CommandFlag.Builder { + protected final Class type; + protected boolean optional = false; + protected T defaultValue = null; + protected Function context = null; + protected Supplier> completion = null; + + public EnumBuilder(@NotNull String key, @NotNull Class type) { + super(key); + this.type = type; + setEnumContext(); + setEnumCompletion(); + } + + private void setEnumContext() { + this.context = (String value) -> { + try { + return Enum.valueOf(type, value.toUpperCase()); + } catch (IllegalArgumentException e) { + throw new InvalidCommandArgument("Invalid value for argument " + key + ": " + value); + } + }; + } + + private void setEnumCompletion() { + List types = Arrays.stream(type.getEnumConstants()) + .map(type -> type.name().toLowerCase()) + .collect(Collectors.toList()); + + this.completion = () -> types; + } + + /** + * Set the flag as optional for users to specify a value. + * + * @return The builder. + */ + public @NotNull S optional() { + this.optional = true; + return (S) this; + } + + /** + * Set the default value. Used if optional is true and user does not specify a value. + * + * @param defaultValue The default value. + * @return The builder. + */ + public @NotNull S defaultValue(@NotNull T defaultValue) { + this.defaultValue = defaultValue; + return (S) this; + } + + /** + * Build the flag. + * + * @return The flag. + */ + @Override + public @NotNull CommandFlag build() { + return new CommandValueFlag<>(key, aliases, type, optional, defaultValue, context, completion); } } }