From 3b2ccdca145e5b3cbf7c7be953cf73bd9c2ade21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Wed, 23 Sep 2020 20:55:17 +0200 Subject: [PATCH] Clean up descriptions --- README.md | 44 +++++++++- .../annotations/AnnotationParser.java | 5 +- ...scription.java => CommandDescription.java} | 2 +- .../intellectualsites/commands/Command.java | 82 ++++++++++++++---- .../commands/CommandManager.java | 68 +++++++++++++-- .../commands/Description.java | 86 +++++++++++++++++++ .../arguments/standard/BooleanArgument.java | 10 +-- .../commands/context/CommandContext.java | 13 +++ .../commands/CommandHelpHandlerTest.java | 2 +- .../commands/BukkitTest.java | 6 +- 10 files changed, 281 insertions(+), 37 deletions(-) rename cloud-annotations/src/main/java/com/intellectualsites/commands/annotations/{Description.java => CommandDescription.java} (97%) create mode 100644 cloud-core/src/main/java/com/intellectualsites/commands/Description.java diff --git a/README.md b/README.md index 8c351ee8..22ffece1 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,7 @@ The code is based on a (W.I.P) paper that can be found [here](https://github.com - **cloud-minecraft/cloud-paper**: Module that extends cloud-bukkit to add special support for Paper 1.8.8+ - **cloud-minecraft/cloud-bungee**: BungeeCord 1.8.8+ implementation of Cloud - **cloud-minecraft/cloud-velocity**: Velocity v1.1.0 implementation of cloud +- **cloud-minecraft/cloud-cloudburst**: Cloudburst v1.0.0+ implementation of cloud ## links @@ -91,8 +92,8 @@ To use `cloud` you will first need to add it as a dependency to your project. Cl intellectualsites-snapshots https://mvn.intellectualsites.com/content/repositories/snapshots -``` - +``` + ```xml com.intellectualsites @@ -110,6 +111,45 @@ To use `cloud` you will first need to add it as a dependency to your project. Cl ``` +If you are shading in cloud, it is highly recommended that you relocate all of our classes to prevent issues +with conflicting dependencies: + +```xml + + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.4 + + + package + + shade + + + false + + + + + ${project.build.directory}/dependency-reduced-pom.xml + + + com.intellectualsites.commands + YOUR.PACKAGE.HERE.cloud + + + com.intellectualsites.services + YOUR.PACKAGE.HERE.cloud.pipeline + + + + + + +``` + **gradle**: ```groovy repositories { diff --git a/cloud-annotations/src/main/java/com/intellectualsites/commands/annotations/AnnotationParser.java b/cloud-annotations/src/main/java/com/intellectualsites/commands/annotations/AnnotationParser.java index 8364ca0e..3718fac8 100644 --- a/cloud-annotations/src/main/java/com/intellectualsites/commands/annotations/AnnotationParser.java +++ b/cloud-annotations/src/main/java/com/intellectualsites/commands/annotations/AnnotationParser.java @@ -80,7 +80,8 @@ public final class AnnotationParser { this.manager = manager; this.metaFactory = new MetaFactory(this, metaMapper); this.annotationMappers = Maps.newHashMap(); - this.registerAnnotationMapper(Description.class, d -> ParserParameters.single(StandardParameters.DESCRIPTION, d.value())); + this.registerAnnotationMapper(CommandDescription.class, d -> + ParserParameters.single(StandardParameters.DESCRIPTION, d.value())); } /** @@ -181,7 +182,7 @@ public final class AnnotationParser { } final String description = argumentDescriptions.getOrDefault(argument, ""); - builder = builder.argument(argument, description); + builder = builder.argument(argument, com.intellectualsites.commands.Description.of(description)); } } /* Try to find the command sender type */ diff --git a/cloud-annotations/src/main/java/com/intellectualsites/commands/annotations/Description.java b/cloud-annotations/src/main/java/com/intellectualsites/commands/annotations/CommandDescription.java similarity index 97% rename from cloud-annotations/src/main/java/com/intellectualsites/commands/annotations/Description.java rename to cloud-annotations/src/main/java/com/intellectualsites/commands/annotations/CommandDescription.java index 7dbe10c5..afaa6ab8 100644 --- a/cloud-annotations/src/main/java/com/intellectualsites/commands/annotations/Description.java +++ b/cloud-annotations/src/main/java/com/intellectualsites/commands/annotations/CommandDescription.java @@ -33,7 +33,7 @@ import java.lang.annotation.Target; */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) -public @interface Description { +public @interface CommandDescription { /** * Command description diff --git a/cloud-core/src/main/java/com/intellectualsites/commands/Command.java b/cloud-core/src/main/java/com/intellectualsites/commands/Command.java index 8d1f0b58..0509e73d 100644 --- a/cloud-core/src/main/java/com/intellectualsites/commands/Command.java +++ b/cloud-core/src/main/java/com/intellectualsites/commands/Command.java @@ -27,6 +27,7 @@ import com.intellectualsites.commands.arguments.CommandArgument; import com.intellectualsites.commands.arguments.StaticArgument; import com.intellectualsites.commands.execution.CommandExecutionHandler; import com.intellectualsites.commands.meta.CommandMeta; +import com.intellectualsites.commands.meta.SimpleCommandMeta; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -44,10 +45,9 @@ import java.util.function.Consumer; * * @param Command sender type */ -@SuppressWarnings("unused") public class Command { - @Nonnull private final Map, String> arguments; + @Nonnull private final Map, Description> arguments; @Nonnull private final CommandExecutionHandler commandExecutionHandler; @Nullable private final Class senderType; @Nonnull private final String commandPermission; @@ -62,7 +62,7 @@ public class Command { * @param commandPermission Command permission * @param commandMeta Command meta instance */ - public Command(@Nonnull final Map, String> commandArguments, + public Command(@Nonnull final Map, Description> commandArguments, @Nonnull final CommandExecutionHandler commandExecutionHandler, @Nullable final Class senderType, @Nonnull final String commandPermission, @@ -99,7 +99,7 @@ public class Command { * @param senderType Required sender type. May be {@code null} * @param commandMeta Command meta instance */ - public Command(@Nonnull final Map, String> commandArguments, + public Command(@Nonnull final Map, Description> commandArguments, @Nonnull final CommandExecutionHandler commandExecutionHandler, @Nullable final Class senderType, @Nonnull final CommandMeta commandMeta) { @@ -114,11 +114,33 @@ public class Command { * @param commandPermission Command permission * @param commandMeta Command meta instance */ - public Command(@Nonnull final Map, String> commandArguments, + public Command(@Nonnull final Map, Description> commandArguments, @Nonnull final CommandExecutionHandler commandExecutionHandler, @Nonnull final String commandPermission, @Nonnull final CommandMeta commandMeta) { - this(commandArguments, commandExecutionHandler, null, "", commandMeta); + this(commandArguments, commandExecutionHandler, null, commandPermission, commandMeta); + } + + /** + * Create a new command builder. Is recommended to use the builder methods + * in {@link CommandManager} rather than invoking this method directly. + * + * @param commandName Base command argument + * @param commandMeta Command meta instance + * @param description Command description + * @param aliases Command aliases + * @param Command sender type + * @return Command builder + */ + @Nonnull + public static Builder newBuilder(@Nonnull final String commandName, + @Nonnull final CommandMeta commandMeta, + @Nonnull final Description description, + @Nonnull final String... aliases) { + final Map, Description> map = new LinkedHashMap<>(); + map.put(StaticArgument.required(commandName, aliases), description); + return new Builder<>(null, commandMeta, null, map, + new CommandExecutionHandler.NullCommandExecutionHandler<>(), ""); } /** @@ -135,8 +157,8 @@ public class Command { public static Builder newBuilder(@Nonnull final String commandName, @Nonnull final CommandMeta commandMeta, @Nonnull final String... aliases) { - final Map, String> map = new LinkedHashMap<>(); - map.put(StaticArgument.required(commandName, aliases), ""); + final Map, Description> map = new LinkedHashMap<>(); + map.put(StaticArgument.required(commandName, aliases), Description.empty()); return new Builder<>(null, commandMeta, null, map, new CommandExecutionHandler.NullCommandExecutionHandler<>(), ""); } @@ -199,7 +221,7 @@ public class Command { */ @Nonnull public String getArgumentDescription(@Nonnull final CommandArgument argument) { - return this.arguments.get(argument); + return this.arguments.get(argument).getDescription(); } @@ -212,7 +234,7 @@ public class Command { public static final class Builder { @Nonnull private final CommandMeta commandMeta; - @Nonnull private final Map, String> commandArguments; + @Nonnull private final Map, Description> commandArguments; @Nonnull private final CommandExecutionHandler commandExecutionHandler; @Nullable private final Class senderType; @Nonnull private final String commandPermission; @@ -221,7 +243,7 @@ public class Command { private Builder(@Nullable final CommandManager commandManager, @Nonnull final CommandMeta commandMeta, @Nullable final Class senderType, - @Nonnull final Map, String> commandArguments, + @Nonnull final Map, Description> commandArguments, @Nonnull final CommandExecutionHandler commandExecutionHandler, @Nonnull final String commandPermission) { this.commandManager = commandManager; @@ -232,6 +254,20 @@ public class Command { this.commandMeta = Objects.requireNonNull(commandMeta, "Meta may not be null"); } + /** + * Add command meta to the internal command meta map + * + * @param key Meta key + * @param value Meta value + * @return New builder instance using the inserted meta key-value pair + */ + @Nonnull + public Builder meta(@Nonnull final String key, @Nonnull final String value) { + final CommandMeta commandMeta = SimpleCommandMeta.builder().with(this.commandMeta).build(); + return new Builder<>(this.commandManager, commandMeta, this.senderType, this.commandArguments, + this.commandExecutionHandler, this.commandPermission); + } + /** * Supply a command manager instance to the builder. This will be used when attempting to * retrieve command argument parsers, in the case that they're needed. This @@ -258,6 +294,21 @@ public class Command { return this.argument(StaticArgument.required(main, aliases)); } + /** + * Inserts a required {@link StaticArgument} into the command chain + * + * @param main Main argument name + * @param description Literal description + * @param aliases Argument aliases + * @return New builder instance with the modified command chain + */ + @Nonnull + public Builder literal(@Nonnull final String main, + @Nonnull final Description description, + @Nonnull final String... aliases) { + return this.argument(StaticArgument.required(main, aliases), description); + } + /** * Add a new command argument with an empty description to the command * @@ -267,7 +318,7 @@ public class Command { */ @Nonnull public Builder argument(@Nonnull final CommandArgument argument) { - return this.argument(argument, ""); + return this.argument(argument, Description.empty()); } /** @@ -275,12 +326,13 @@ public class Command { * * @param argument Argument to add * @param description Argument description - * @param Argument type + * @param Argument type * @return New builder instance with the command argument inserted into the argument list */ @Nonnull - public Builder argument(@Nonnull final CommandArgument argument, @Nonnull final String description) { - final Map, String> commandArgumentMap = new LinkedHashMap<>(this.commandArguments); + public Builder argument(@Nonnull final CommandArgument argument, + @Nonnull final Description description) { + final Map, Description> commandArgumentMap = new LinkedHashMap<>(this.commandArguments); commandArgumentMap.put(argument, description); return new Builder<>(this.commandManager, this.commandMeta, this.senderType, commandArgumentMap, this.commandExecutionHandler, this.commandPermission); diff --git a/cloud-core/src/main/java/com/intellectualsites/commands/CommandManager.java b/cloud-core/src/main/java/com/intellectualsites/commands/CommandManager.java index f35158ea..81f855ae 100644 --- a/cloud-core/src/main/java/com/intellectualsites/commands/CommandManager.java +++ b/cloud-core/src/main/java/com/intellectualsites/commands/CommandManager.java @@ -220,6 +220,23 @@ public abstract class CommandManager { */ public abstract boolean hasPermission(@Nonnull C sender, @Nonnull String permission); + /** + * Create a new command builder + * + * @param name Command name + * @param aliases Command aliases + * @param description Command description + * @param meta Command meta + * @return Builder instance + */ + @Nonnull + public Command.Builder commandBuilder(@Nonnull final String name, + @Nonnull final Collection aliases, + @Nonnull final Description description, + @Nonnull final CommandMeta meta) { + return Command.newBuilder(name, meta, description, aliases.toArray(new String[0])); + } + /** * Create a new command builder * @@ -232,7 +249,24 @@ public abstract class CommandManager { public Command.Builder commandBuilder(@Nonnull final String name, @Nonnull final Collection aliases, @Nonnull final CommandMeta meta) { - return Command.newBuilder(name, meta, aliases.toArray(new String[0])); + return Command.newBuilder(name, meta, Description.empty(), aliases.toArray(new String[0])); + } + + /** + * Create a new command builder + * + * @param name Command name + * @param meta Command meta + * @param description Command description + * @param aliases Command aliases + * @return Builder instance + */ + @Nonnull + public Command.Builder commandBuilder(@Nonnull final String name, + @Nonnull final CommandMeta meta, + @Nonnull final Description description, + @Nonnull final String... aliases) { + return Command.newBuilder(name, meta, description, aliases); } /** @@ -247,21 +281,39 @@ public abstract class CommandManager { public Command.Builder commandBuilder(@Nonnull final String name, @Nonnull final CommandMeta meta, @Nonnull final String... aliases) { - return Command.newBuilder(name, meta, aliases); + return Command.newBuilder(name, meta, Description.empty(), aliases); } /** * Create a new command builder using a default command meta instance. * - * @param name Command name - * @param aliases Command aliases + * @param name Command name + * @param description Command description + * @param aliases Command aliases * @return Builder instance * @throws UnsupportedOperationException If the command manager does not support default command meta creation * @see #createDefaultCommandMeta() Default command meta creation */ @Nonnull - public Command.Builder commandBuilder(@Nonnull final String name, @Nonnull final String... aliases) { - return Command.newBuilder(name, this.createDefaultCommandMeta(), aliases).manager(this); + public Command.Builder commandBuilder(@Nonnull final String name, + @Nonnull final Description description, + @Nonnull final String... aliases) { + return Command.newBuilder(name, this.createDefaultCommandMeta(), description, aliases).manager(this); + } + + /** + * Create a new command builder using a default command meta instance. + * + * @param name Command name + * @param aliases Command aliases + * @return Builder instance + * @throws UnsupportedOperationException If the command manager does not support default command meta creation + * @see #createDefaultCommandMeta() Default command meta creation + */ + @Nonnull + public Command.Builder commandBuilder(@Nonnull final String name, + @Nonnull final String... aliases) { + return Command.newBuilder(name, this.createDefaultCommandMeta(), Description.empty(), aliases).manager(this); } /** @@ -344,8 +396,8 @@ public abstract class CommandManager { /** * Postprocess a command context instance * - * @param context Command context - * @param command Command instance + * @param context Command context + * @param command Command instance * @return {@link State#ACCEPTED} if the command should be parsed and executed, else {@link State#REJECTED} * @see #registerCommandPostProcessor(CommandPostprocessor) Register a command postprocessor */ diff --git a/cloud-core/src/main/java/com/intellectualsites/commands/Description.java b/cloud-core/src/main/java/com/intellectualsites/commands/Description.java new file mode 100644 index 00000000..e5119fca --- /dev/null +++ b/cloud-core/src/main/java/com/intellectualsites/commands/Description.java @@ -0,0 +1,86 @@ +// +// MIT License +// +// Copyright (c) 2020 Alexander Söderberg +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +package com.intellectualsites.commands; + +import javax.annotation.Nonnull; + +/** + * {@link com.intellectualsites.commands.arguments.CommandArgument} description + */ +public final class Description { + + /** + * Empty command description + */ + private static final Description EMPTY = Description.of(""); + + private final String description; + + private Description(@Nonnull final String description) { + this.description = description; + } + + /** + * Get an empty command description + * + * @return Command description + */ + @Nonnull + public static Description empty() { + return EMPTY; + } + + /** + * Create a command description instance + * + * @param string Command description + * @return Created command description + */ + @Nonnull + public static Description of(@Nonnull final String string) { + return new Description(string); + } + + /** + * Get the command description + * + * @return Command description + */ + @Nonnull + public String getDescription() { + return this.description; + } + + /** + * Get the command description + * + * @return Command description + */ + @Nonnull + @Override + public String toString() { + return this.description; + } + +} diff --git a/cloud-core/src/main/java/com/intellectualsites/commands/arguments/standard/BooleanArgument.java b/cloud-core/src/main/java/com/intellectualsites/commands/arguments/standard/BooleanArgument.java index 6d9fb6b8..a2c98ac6 100644 --- a/cloud-core/src/main/java/com/intellectualsites/commands/arguments/standard/BooleanArgument.java +++ b/cloud-core/src/main/java/com/intellectualsites/commands/arguments/standard/BooleanArgument.java @@ -85,15 +85,15 @@ public final class BooleanArgument extends CommandArgument { /** * Create a new required command argument with a default value * - * @param name Argument name - * @param defaultNum Default num - * @param Command sender type + * @param name Argument name + * @param defaultBoolean Default num + * @param Command sender type * @return Created argument */ @Nonnull public static CommandArgument optional(@Nonnull final String name, - final String defaultNum) { - return BooleanArgument.newBuilder(name).asOptionalWithDefault(defaultNum).build(); + final boolean defaultBoolean) { + return BooleanArgument.newBuilder(name).asOptionalWithDefault(Boolean.toString(defaultBoolean)).build(); } /** diff --git a/cloud-core/src/main/java/com/intellectualsites/commands/context/CommandContext.java b/cloud-core/src/main/java/com/intellectualsites/commands/context/CommandContext.java index ffa9dafa..563df9aa 100644 --- a/cloud-core/src/main/java/com/intellectualsites/commands/context/CommandContext.java +++ b/cloud-core/src/main/java/com/intellectualsites/commands/context/CommandContext.java @@ -125,4 +125,17 @@ public final class CommandContext { return (T) value; } + /** + * Get a value if it exists, else return the provided default value + * + * @param key Argument key + * @param defaultValue Default value + * @param Argument type + * @return Argument, or supplied default value + */ + @Nonnull + public T getOrDefault(@Nonnull final String key, @Nonnull final T defaultValue) { + return this.get(key).orElse(defaultValue); + } + } diff --git a/cloud-core/src/test/java/com/intellectualsites/commands/CommandHelpHandlerTest.java b/cloud-core/src/test/java/com/intellectualsites/commands/CommandHelpHandlerTest.java index e280ad0f..7e62270a 100644 --- a/cloud-core/src/test/java/com/intellectualsites/commands/CommandHelpHandlerTest.java +++ b/cloud-core/src/test/java/com/intellectualsites/commands/CommandHelpHandlerTest.java @@ -47,7 +47,7 @@ class CommandHelpHandlerTest { manager.command(manager.commandBuilder("test", meta1).literal("this").literal("thing").build()); final SimpleCommandMeta meta2 = SimpleCommandMeta.builder().with("description", "Command with variables").build(); manager.command(manager.commandBuilder("test", meta2).literal("int"). - argument(IntegerArgument.required("int"), "A number").build()); + argument(IntegerArgument.required("int"), Description.of("A number")).build()); } @Test diff --git a/cloud-minecraft/cloud-bukkit-test/src/main/java/com/intellectualsites/commands/BukkitTest.java b/cloud-minecraft/cloud-bukkit-test/src/main/java/com/intellectualsites/commands/BukkitTest.java index 1cdfe7ae..d2c95dd5 100644 --- a/cloud-minecraft/cloud-bukkit-test/src/main/java/com/intellectualsites/commands/BukkitTest.java +++ b/cloud-minecraft/cloud-bukkit-test/src/main/java/com/intellectualsites/commands/BukkitTest.java @@ -27,7 +27,7 @@ import com.intellectualsites.commands.annotations.AnnotationParser; import com.intellectualsites.commands.annotations.Argument; import com.intellectualsites.commands.annotations.CommandMethod; import com.intellectualsites.commands.annotations.Confirmation; -import com.intellectualsites.commands.annotations.Description; +import com.intellectualsites.commands.annotations.CommandDescription; import com.intellectualsites.commands.annotations.specifier.Completions; import com.intellectualsites.commands.annotations.specifier.Range; import com.intellectualsites.commands.arguments.parser.ArgumentParseResult; @@ -203,7 +203,7 @@ public final class BukkitTest extends JavaPlugin { .literal("help") .argument(StringArgument.newBuilder("query").greedy() .asOptionalWithDefault("") - .build(), "Help query") + .build(), Description.of("Help Query")) .handler(c -> minecraftHelp.queryCommands(c.get("query").orElse(""), c.getSender())).build()); } catch (final Exception e) { @@ -211,7 +211,7 @@ public final class BukkitTest extends JavaPlugin { } } - @Description("Test cloud command using @CommandMethod") + @CommandDescription("Test cloud command using @CommandMethod") @CommandMethod(value = "annotation|a [number]", permission = "some.permission.node") private void annotatedCommand(@Nonnull final Player player, @Argument(value = "input", description = "Some string") @Completions("one,two,duck")