diff --git a/commands-bukkit/src/main/java/com/intellectualsites/commands/BukkitCommandSender.java b/commands-bukkit/src/main/java/com/intellectualsites/commands/BukkitCommandSender.java index 2268aede..c77b1ebd 100644 --- a/commands-bukkit/src/main/java/com/intellectualsites/commands/BukkitCommandSender.java +++ b/commands-bukkit/src/main/java/com/intellectualsites/commands/BukkitCommandSender.java @@ -82,4 +82,8 @@ public abstract class BukkitCommandSender implements CommandSender { @Nonnull public abstract Player asPlayer(); + @Override + public boolean hasPermission(@Nonnull final String permission) { + return this.internalSender.hasPermission(permission); + } } diff --git a/commands-core/src/main/java/com/intellectualsites/commands/Command.java b/commands-core/src/main/java/com/intellectualsites/commands/Command.java index fc7cb869..6af472e4 100644 --- a/commands-core/src/main/java/com/intellectualsites/commands/Command.java +++ b/commands-core/src/main/java/com/intellectualsites/commands/Command.java @@ -144,7 +144,13 @@ public class Command { } - public static class Builder { + /** + * Builder for {@link Command} instances. The builder is immutable, and each + * setter method will return a new builder instance. + * + * @param Command sender type + */ + public static final class Builder { @Nonnull private final List> commandComponents; @Nonnull private final CommandExecutionHandler commandExecutionHandler; @@ -155,10 +161,10 @@ public class Command { @Nonnull final List> commandComponents, @Nonnull final CommandExecutionHandler commandExecutionHandler, @Nonnull final String commandPermission) { - this.commandComponents = commandComponents; - this.commandExecutionHandler = commandExecutionHandler; this.senderType = senderType; - this.commandPermission = commandPermission; + this.commandComponents = Objects.requireNonNull(commandComponents, "Components may not be null"); + this.commandExecutionHandler = Objects.requireNonNull(commandExecutionHandler, "Execution handler may not be null"); + this.commandPermission = Objects.requireNonNull(commandPermission, "Permission may not be null"); } /** diff --git a/commands-core/src/main/java/com/intellectualsites/commands/CommandManager.java b/commands-core/src/main/java/com/intellectualsites/commands/CommandManager.java index 8ab9633a..3f00e4a6 100644 --- a/commands-core/src/main/java/com/intellectualsites/commands/CommandManager.java +++ b/commands-core/src/main/java/com/intellectualsites/commands/CommandManager.java @@ -59,11 +59,28 @@ public abstract class CommandManager { this.commandRegistrationHandler = commandRegistrationHandler; } + /** + * Execute a command and get a future that completes with the result + * + * @param commandSender Sender of the command + * @param input Input provided by the sender + * @return Command result + */ + @Nonnull public CompletableFuture executeCommand(@Nonnull final C commandSender, @Nonnull final String input) { final CommandContext context = new CommandContext<>(commandSender); return this.commandExecutionCoordinator.coordinateExecution(context, tokenize(input)); } + /** + * Get command suggestions for the "next" argument that would yield a correctly + * parsing command input + * + * @param commandSender Sender of the command + * @param input Input provided by the sender + * @return List of suggestions + */ + @Nonnull public List suggest(@Nonnull final C commandSender, @Nonnull final String input) { final CommandContext context = new CommandContext<>(commandSender); return this.commandTree.getSuggestions(context, tokenize(input)); @@ -105,10 +122,15 @@ public abstract class CommandManager { * * @param commandSyntaxFormatter New formatter */ - public void setCommandSyntaxFormatter(@Nonnull final CommandSyntaxFormatter commandSyntaxFormatter) { + public void setCommandSyntaxFormatter(@Nonnull final CommandSyntaxFormatter commandSyntaxFormatter) { this.commandSyntaxFormatter = commandSyntaxFormatter; } + /** + * Get the command registration handler + * + * @return Command registration handler + */ @Nonnull protected CommandRegistrationHandler getCommandRegistrationHandler() { return this.commandRegistrationHandler; diff --git a/commands-core/src/main/java/com/intellectualsites/commands/CommandTree.java b/commands-core/src/main/java/com/intellectualsites/commands/CommandTree.java index 91623893..53cf4858 100644 --- a/commands-core/src/main/java/com/intellectualsites/commands/CommandTree.java +++ b/commands-core/src/main/java/com/intellectualsites/commands/CommandTree.java @@ -130,7 +130,7 @@ public class CommandTree { throw new InvalidSyntaxException(this.commandManager.getCommandSyntaxFormatter() .apply(Objects.requireNonNull(child.getValue() .getOwningCommand()) - .getComponents()), + .getComponents()), commandContext.getCommandSender(), this.getChain(root) .stream() .map(Node::getValue) @@ -167,13 +167,12 @@ public class CommandTree { throw new InvalidSyntaxException(this.commandManager.getCommandSyntaxFormatter() .apply(Objects.requireNonNull( Objects.requireNonNull(root.getValue()) - .getOwningCommand()) - .getComponents()), + .getOwningCommand()) + .getComponents()), commandContext.getCommandSender(), this.getChain(root) .stream() .map(Node::getValue) - .collect( - Collectors.toList())); + .collect(Collectors.toList())); } } else { final Iterator>> childIterator = root.getChildren().iterator(); @@ -258,7 +257,8 @@ public class CommandTree { if (component.getValue() == null || !this.isPermitted(commandContext.getCommandSender(), component)) { continue; } - suggestions.addAll(component.getValue().getParser().suggestions(commandContext, stringOrEmpty(commandQueue.peek()))); + suggestions.addAll( + component.getValue().getParser().suggestions(commandContext, stringOrEmpty(commandQueue.peek()))); } return suggestions; } @@ -410,6 +410,11 @@ public class CommandTree { } + /** + * Very simple tree structure + * + * @param Node value type + */ private static final class Node { private final Map nodeMeta = new HashMap<>(); diff --git a/commands-core/src/main/java/com/intellectualsites/commands/components/CommandComponent.java b/commands-core/src/main/java/com/intellectualsites/commands/components/CommandComponent.java index 80de965f..a4463198 100644 --- a/commands-core/src/main/java/com/intellectualsites/commands/components/CommandComponent.java +++ b/commands-core/src/main/java/com/intellectualsites/commands/components/CommandComponent.java @@ -179,7 +179,13 @@ public class CommandComponent implements Comparable< } - public static class Builder { + /** + * Mutable builder for {@link CommandComponent} instances + * + * @param Command sender type + * @param Component value type + */ + public static final class Builder { private String name; private boolean required = true; diff --git a/commands-core/src/main/java/com/intellectualsites/commands/components/CommandSyntaxFormatter.java b/commands-core/src/main/java/com/intellectualsites/commands/components/CommandSyntaxFormatter.java index d360a4a4..7a64e662 100644 --- a/commands-core/src/main/java/com/intellectualsites/commands/components/CommandSyntaxFormatter.java +++ b/commands-core/src/main/java/com/intellectualsites/commands/components/CommandSyntaxFormatter.java @@ -29,6 +29,11 @@ import javax.annotation.Nonnull; import java.util.List; import java.util.function.Function; +/** + * Utility that formats chains of {@link CommandComponent command components} into syntax strings + * + * @param Command sender type + */ @FunctionalInterface public interface CommandSyntaxFormatter extends Function>, String> { diff --git a/commands-core/src/main/java/com/intellectualsites/commands/components/StandardCommandSyntaxFormatter.java b/commands-core/src/main/java/com/intellectualsites/commands/components/StandardCommandSyntaxFormatter.java index cc930cd7..f677bb81 100644 --- a/commands-core/src/main/java/com/intellectualsites/commands/components/StandardCommandSyntaxFormatter.java +++ b/commands-core/src/main/java/com/intellectualsites/commands/components/StandardCommandSyntaxFormatter.java @@ -29,6 +29,16 @@ import javax.annotation.Nonnull; import java.util.Iterator; import java.util.List; +/** + * {@link CommandSyntaxFormatter} implementation that uses the following rules: + *
    + *
  • static components are serialized as their name, without a bracket
  • + *
  • required components are serialized as their name, surrounded by angle brackets
  • + *
  • optional components are serialized as their name, surrounded by square brackets
  • + *
+ * + * @param Command sender type + */ public class StandardCommandSyntaxFormatter implements CommandSyntaxFormatter { public StandardCommandSyntaxFormatter() { diff --git a/commands-core/src/main/java/com/intellectualsites/commands/components/StaticComponent.java b/commands-core/src/main/java/com/intellectualsites/commands/components/StaticComponent.java index 3a1238d8..1d835986 100644 --- a/commands-core/src/main/java/com/intellectualsites/commands/components/StaticComponent.java +++ b/commands-core/src/main/java/com/intellectualsites/commands/components/StaticComponent.java @@ -37,18 +37,39 @@ import java.util.Locale; import java.util.Queue; import java.util.Set; +/** + * {@link CommandComponent} type that recognizes fixed strings. This type does not parse variables. + * + * @param Command sender type + */ public final class StaticComponent extends CommandComponent { private StaticComponent(final boolean required, @Nonnull final String name, @Nonnull final String... aliases) { super(required, name, new StaticComponentParser<>(name, aliases)); } + /** + * Create a new static component instance for a required command component + * + * @param name Component name + * @param aliases Component aliases + * @param Command sender type + * @return Constructed component + */ @Nonnull public static StaticComponent required(@Nonnull final String name, @Nonnull final String... aliases) { return new StaticComponent<>(true, name, aliases); } + /** + * Create a new static component instance for an optional command component + * + * @param name Component name + * @param aliases Component aliases + * @param Command sender type + * @return Constructed component + */ @Nonnull public static StaticComponent optional(@Nonnull final String name, @Nonnull final String... aliases) { @@ -72,7 +93,7 @@ public final class StaticComponent extends CommandCompo @Nonnull final Queue inputQueue) { final String string = inputQueue.peek(); if (string == null) { - return ComponentParseResult.failure(this.name); + return ComponentParseResult.failure(new NullPointerException("No input provided")); } for (final String acceptedString : this.acceptedStrings) { if (string.equalsIgnoreCase(acceptedString)) { @@ -81,7 +102,7 @@ public final class StaticComponent extends CommandCompo return ComponentParseResult.success(this.name); } } - return ComponentParseResult.failure(this.name); + return ComponentParseResult.failure(new IllegalArgumentException(string)); } @Nonnull diff --git a/commands-core/src/main/java/com/intellectualsites/commands/context/CommandContext.java b/commands-core/src/main/java/com/intellectualsites/commands/context/CommandContext.java index 4f3e78a3..0b0c71e9 100644 --- a/commands-core/src/main/java/com/intellectualsites/commands/context/CommandContext.java +++ b/commands-core/src/main/java/com/intellectualsites/commands/context/CommandContext.java @@ -30,11 +30,21 @@ import java.util.HashMap; import java.util.Map; import java.util.Optional; +/** + * Command context used to assist in the parsing of commands + * + * @param Command sender type + */ public class CommandContext { private final Map internalStorage = new HashMap<>(); private final C commandSender; + /** + * Create a new command context instance + * + * @param commandSender Sender of the command + */ public CommandContext(@Nonnull final C commandSender) { this.commandSender = commandSender; } diff --git a/commands-core/src/main/java/com/intellectualsites/commands/exceptions/InvalidSyntaxException.java b/commands-core/src/main/java/com/intellectualsites/commands/exceptions/InvalidSyntaxException.java index 3b575004..ef462f06 100644 --- a/commands-core/src/main/java/com/intellectualsites/commands/exceptions/InvalidSyntaxException.java +++ b/commands-core/src/main/java/com/intellectualsites/commands/exceptions/InvalidSyntaxException.java @@ -29,6 +29,9 @@ import com.intellectualsites.commands.sender.CommandSender; import javax.annotation.Nonnull; import java.util.List; +/** + * Exception sent when a {@link CommandSender} inputs invalid command syntax + */ public class InvalidSyntaxException extends CommandParseException { private final String correctSyntax; @@ -40,6 +43,11 @@ public class InvalidSyntaxException extends CommandParseException { this.correctSyntax = correctSyntax; } + /** + * Get the correct syntax of the command + * + * @return Correct command syntax + */ @Nonnull public String getCorrectSyntax() { return this.correctSyntax; diff --git a/commands-core/src/main/java/com/intellectualsites/commands/execution/CommandExecutionCoordinator.java b/commands-core/src/main/java/com/intellectualsites/commands/execution/CommandExecutionCoordinator.java index 2d102c8b..e8173f21 100644 --- a/commands-core/src/main/java/com/intellectualsites/commands/execution/CommandExecutionCoordinator.java +++ b/commands-core/src/main/java/com/intellectualsites/commands/execution/CommandExecutionCoordinator.java @@ -77,7 +77,12 @@ public abstract class CommandExecutionCoordinator { } - public static class SimpleCoordinator extends CommandExecutionCoordinator { + /** + * A simple command execution coordinator that executes all commands immediately, on the calling thread + * + * @param Command sender type + */ + public static final class SimpleCoordinator extends CommandExecutionCoordinator { private SimpleCoordinator(@Nonnull final CommandTree commandTree) { super(commandTree); diff --git a/commands-core/src/main/java/com/intellectualsites/commands/execution/CommandExecutionHandler.java b/commands-core/src/main/java/com/intellectualsites/commands/execution/CommandExecutionHandler.java index 2da19edd..5b2d1560 100644 --- a/commands-core/src/main/java/com/intellectualsites/commands/execution/CommandExecutionHandler.java +++ b/commands-core/src/main/java/com/intellectualsites/commands/execution/CommandExecutionHandler.java @@ -45,11 +45,15 @@ public interface CommandExecutionHandler { void execute(@Nonnull final CommandContext commandContext); + /** + * Command execution handler that does nothing + * + * @param Command sender type + */ class NullCommandExecutionHandler implements CommandExecutionHandler { @Override public void execute(@Nonnull final CommandContext commandContext) { - } } diff --git a/commands-core/src/main/java/com/intellectualsites/commands/execution/CommandResult.java b/commands-core/src/main/java/com/intellectualsites/commands/execution/CommandResult.java index 7a09cd68..8535a31b 100644 --- a/commands-core/src/main/java/com/intellectualsites/commands/execution/CommandResult.java +++ b/commands-core/src/main/java/com/intellectualsites/commands/execution/CommandResult.java @@ -23,5 +23,8 @@ // package com.intellectualsites.commands.execution; +/** + * The result of a command execution + */ public class CommandResult { } diff --git a/commands-core/src/main/java/com/intellectualsites/commands/parser/ComponentParseResult.java b/commands-core/src/main/java/com/intellectualsites/commands/parser/ComponentParseResult.java index 637310eb..bb203dc0 100644 --- a/commands-core/src/main/java/com/intellectualsites/commands/parser/ComponentParseResult.java +++ b/commands-core/src/main/java/com/intellectualsites/commands/parser/ComponentParseResult.java @@ -26,26 +26,55 @@ package com.intellectualsites.commands.parser; import javax.annotation.Nonnull; import java.util.Optional; +/** + * Result of the parsing done by a {@link ComponentParser} + * + * @param Parser return type + */ public abstract class ComponentParseResult { private ComponentParseResult() { } + /** + * Indicate that the parsing failed + * + * @param failure Failure reason + * @param Parser return type + * @return Failed parse result + */ @Nonnull - public static ComponentParseResult failure(@Nonnull final String failure) { + public static ComponentParseResult failure(@Nonnull final Throwable failure) { return new ParseFailure<>(failure); } + /** + * Indicate that the parsing succeeded + * + * @param value Value produced by the parser + * @param Parser return type + * @return Succeeded parse result + */ @Nonnull public static ComponentParseResult success(@Nonnull final T value) { return new ParseSuccess<>(value); } + /** + * Get the parsed value, if it exists + * + * @return Optional containing the parsed value + */ @Nonnull public abstract Optional getParsedValue(); + /** + * Get the failure reason, if it exists + * + * @return Optional containing the failure reason + */ @Nonnull - public abstract Optional getFailure(); + public abstract Optional getFailure(); private static final class ParseSuccess extends ComponentParseResult { @@ -64,7 +93,7 @@ public abstract class ComponentParseResult { @Nonnull @Override - public Optional getFailure() { + public Optional getFailure() { return Optional.empty(); } @@ -73,9 +102,9 @@ public abstract class ComponentParseResult { private static final class ParseFailure extends ComponentParseResult { - private final String failure; + private final Throwable failure; - private ParseFailure(@Nonnull final String failure) { + private ParseFailure(@Nonnull final Throwable failure) { this.failure = failure; } @@ -87,7 +116,7 @@ public abstract class ComponentParseResult { @Nonnull @Override - public Optional getFailure() { + public Optional getFailure() { return Optional.of(this.failure); } } diff --git a/commands-core/src/main/java/com/intellectualsites/commands/parser/ComponentParser.java b/commands-core/src/main/java/com/intellectualsites/commands/parser/ComponentParser.java index 6d330c90..9523ad1a 100644 --- a/commands-core/src/main/java/com/intellectualsites/commands/parser/ComponentParser.java +++ b/commands-core/src/main/java/com/intellectualsites/commands/parser/ComponentParser.java @@ -31,6 +31,12 @@ import java.util.Collections; import java.util.List; import java.util.Queue; +/** + * Parser that parses strings into values of a specific type + * + * @param Command sender type + * @param Value type + */ @FunctionalInterface public interface ComponentParser { @@ -44,6 +50,13 @@ public interface ComponentParser { @Nonnull ComponentParseResult parse(@Nonnull CommandContext commandContext, @Nonnull Queue inputQueue); + /** + * Get a list of suggested arguments that would be correctly parsed by this parser + * + * @param commandContext Command context + * @param input Input string + * @return List of suggestions + */ @Nonnull default List suggestions(@Nonnull final CommandContext commandContext, @Nonnull final String input) { return Collections.emptyList(); diff --git a/commands-core/src/main/java/com/intellectualsites/commands/sender/CommandSender.java b/commands-core/src/main/java/com/intellectualsites/commands/sender/CommandSender.java index 65dcefbd..3833b42c 100644 --- a/commands-core/src/main/java/com/intellectualsites/commands/sender/CommandSender.java +++ b/commands-core/src/main/java/com/intellectualsites/commands/sender/CommandSender.java @@ -27,8 +27,11 @@ import javax.annotation.Nonnull; public interface CommandSender { - default boolean hasPermission(@Nonnull final String permission) { - return true; - } + /** + * Check if the command sender has a given permission node + * + * @param permission Permission node + */ + boolean hasPermission(@Nonnull String permission); }