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 41709a5b..bb7d16e2 100644 --- a/cloud-core/src/main/java/com/intellectualsites/commands/Command.java +++ b/cloud-core/src/main/java/com/intellectualsites/commands/Command.java @@ -120,7 +120,8 @@ public class Command { } /** - * Create a new command builder + * 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 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 f141f4fb..f93c2777 100644 --- a/cloud-core/src/main/java/com/intellectualsites/commands/CommandManager.java +++ b/cloud-core/src/main/java/com/intellectualsites/commands/CommandManager.java @@ -125,7 +125,7 @@ public abstract class CommandManager { @Nonnull public CompletableFuture> executeCommand(@Nonnull final C commandSender, @Nonnull final String input) { final CommandContext context = this.commandContextFactory.create(false, commandSender); - final LinkedList inputQueue = this.tokenize(input); + final LinkedList inputQueue = tokenize(input); try { if (this.preprocessContext(context, inputQueue) == State.ACCEPTED) { return this.commandExecutionCoordinator.coordinateExecution(context, inputQueue); @@ -150,7 +150,7 @@ public abstract class CommandManager { @Nonnull public List suggest(@Nonnull final C commandSender, @Nonnull final String input) { final CommandContext context = this.commandContextFactory.create(true, commandSender); - final LinkedList inputQueue = this.tokenize(input); + final LinkedList inputQueue = tokenize(input); if (this.preprocessContext(context, inputQueue) == State.ACCEPTED) { return this.commandSuggestionProcessor.apply(new CommandPreprocessingContext<>(context, inputQueue), this.commandTree.getSuggestions( @@ -297,6 +297,7 @@ public abstract class CommandManager { * are called in LIFO order * * @param processor Processor to register + * @see #preprocessContext(CommandContext, LinkedList) Preprocess a context */ public void registerCommandPreProcessor(@Nonnull final CommandPreprocessor processor) { this.servicePipeline.registerServiceImplementation(new TypeToken>() { @@ -310,6 +311,7 @@ public abstract class CommandManager { * @param context Command context * @param inputQueue Command input as supplied by sender * @return {@link State#ACCEPTED} if the command should be parsed and executed, else {@link State#REJECTED} + * @see #registerExceptionHandler(Class, BiConsumer) Register a command preprocessor */ public State preprocessContext(@Nonnull final CommandContext context, @Nonnull final LinkedList inputQueue) { this.servicePipeline.pump(new CommandPreprocessingContext<>(context, inputQueue)) @@ -325,6 +327,7 @@ public abstract class CommandManager { * Get the command suggestions processor instance currently used in this command manager * * @return Command suggestions processor + * @see #setCommandSuggestionProcessor(CommandSuggestionProcessor) Setting the suggestion processor */ @Nonnull public CommandSuggestionProcessor getCommandSuggestionProcessor() { @@ -332,7 +335,9 @@ public abstract class CommandManager { } /** - * Set the command suggestions processor for this command manager + * Set the command suggestions processor for this command manager. This will be called every + * time {@link #suggest(Object, String)} is called, to process the list of suggestions + * before it's returned to the caller * * @param commandSuggestionProcessor New command suggestions processor */ @@ -341,7 +346,15 @@ public abstract class CommandManager { } /** - * Get the parser registry instance + * Get the parser registry instance. The parser registry contains default + * mappings to {@link com.intellectualsites.commands.arguments.parser.ArgumentParser} + * and allows for the registration of custom mappings. The parser registry also + * contains mappings of annotations to {@link com.intellectualsites.commands.arguments.parser.ParserParameter} + * which allows for annotations to be used to customize parser settings. + *

+ * When creating a new parser type, it is recommended to register it in the parser + * registry. In particular, default parser types (shipped with cloud implementations) + * should be registered in the constructor of the platform {@link CommandManager} * * @return Parser registry instance */ @@ -356,6 +369,7 @@ public abstract class CommandManager { * @param clazz Exception class * @param Exception type * @return Exception handler, or {@code null} + * @see #registerCommandPreProcessor(CommandPreprocessor) Registering an exception handler */ @Nullable public final BiConsumer getExceptionHandler(@Nullable final Class clazz) { @@ -368,7 +382,9 @@ public abstract class CommandManager { } /** - * Register an exception handler for an exception type + * Register an exception handler for an exception type. This will then be used + * when {@link #handleException(Object, Class, Exception, BiConsumer)} is called + * for the particular exception type * * @param clazz Exception class * @param handler Exception handler @@ -380,13 +396,14 @@ public abstract class CommandManager { } /** - * Handler an exception using the registered exception handler for the exception type, or using the + * Handle an exception using the registered exception handler for the exception type, or using the * provided default handler if no exception handler has been registered for the exception type * * @param sender Executing command sender * @param clazz Exception class - * @param exception Exception - * @param defaultHandler Default exception handler + * @param exception Exception instance + * @param defaultHandler Default exception handler. Will be called if there is no exception + * handler stored for the exception type * @param Exception type */ public final void handleException(@Nonnull final C sender, @@ -397,7 +414,7 @@ public abstract class CommandManager { } /** - * Get all registered commands + * Get a collection containing all registered commands. * * @return Unmodifiable view of all registered commands */ @@ -407,9 +424,11 @@ public abstract class CommandManager { } /** - * Get a command help handler instance + * Get a command help handler instance. This can be used to assist in the production + * of command help menus, etc. * - * @return Command help handler + * @return Command help handler. A new instance will be created + * each time this method is called. */ @Nonnull public final CommandHelpHandler getCommandHelpHandler() { diff --git a/cloud-core/src/main/java/com/intellectualsites/commands/CommandTree.java b/cloud-core/src/main/java/com/intellectualsites/commands/CommandTree.java index 3a63e436..691944b5 100644 --- a/cloud-core/src/main/java/com/intellectualsites/commands/CommandTree.java +++ b/cloud-core/src/main/java/com/intellectualsites/commands/CommandTree.java @@ -52,7 +52,29 @@ import java.util.Queue; import java.util.stream.Collectors; /** - * Tree containing all commands and command paths + * Tree containing all commands and command paths. + *

+ * All {@link Command commands} consists of unique paths made out of {@link CommandArgument arguments}. + * These arguments may be {@link StaticArgument literals} or variables. Command may either be required + * or optional, with the requirement that no optional argument precedes a required argument. + *

+ * The {@link Command commands} are stored in this tree and the nodes of tree consists of the command + * {@link CommandArgument arguments}. Each leaf node of the tree should containing a fully parsed + * {@link Command}. It is thus possible to walk the tree and determine whether or not the supplied + * input from a command sender constitutes a proper command. + *

+ * When parsing input, the tree will be walked until one of four scenarios occur: + *

    + *
  1. The input queue is empty at a non-leaf node
  2. + *
  3. The input queue is not empty following a leaf node
  4. + *
  5. No child node is able to accept the input
  6. + *
  7. The input queue is empty following a leaf node
  8. + *
+ *

+ * Scenarios one and two would result in a {@link InvalidSyntaxException} being thrown, whereas + * scenario three would result in a {@link NoSuchCommandException} if occurring at the root node + * or a {@link InvalidSyntaxException otherwise}. Only the fourth scenario would result in a complete + * command being parsed. * * @param Command sender type */ @@ -70,8 +92,8 @@ public final class CommandTree { /** * Create a new command tree instance * - * @param commandManager Command manager - * @param Command sender type + * @param commandManager Command manager + * @param Command sender type * @return New command tree */ @Nonnull @@ -528,7 +550,7 @@ public final class CommandTree { if (node.getValue() != null && node.getValue() instanceof StaticArgument) { final StaticArgument staticArgument = (StaticArgument) node.getValue(); for (final String alias : staticArgument.getAliases()) { - if (alias.equalsIgnoreCase(name)) { + if (alias.equalsIgnoreCase(name)) { return node; } }