From 90d37f1df82349ac0ac18fa1d67b7904cffc0b54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Thu, 10 Sep 2020 13:03:26 +0200 Subject: [PATCH] Add command meta & add new guided builder methods for components --- .../commands/BukkitCommandManager.java | 6 +- .../commands/BukkitCommandMeta.java | 36 +++++ .../commands/BukkitCommandMetaBuilder.java | 65 ++++++++ .../BukkitPluginRegistrationHandler.java | 5 +- .../intellectualsites/commands/Command.java | 83 +++++++--- .../commands/CommandManager.java | 23 +-- .../commands/CommandTree.java | 111 +++++++------ .../commands/components/CommandComponent.java | 31 ++-- .../components/standard/ByteComponent.java | 16 +- .../components/standard/IntegerComponent.java | 14 +- .../CommandExecutionCoordinator.java | 18 ++- .../internal/CommandRegistrationHandler.java | 20 +-- .../commands/meta/CommandMeta.java | 34 ++++ .../commands/meta/SimpleCommandMeta.java | 149 ++++++++++++++++++ .../commands/CommandTest.java | 9 +- .../commands/CommandTreeTest.java | 11 +- .../commands/TestCommandManager.java | 5 +- cloud-jline/pom.xml | 4 +- .../commands/jline/JLineCommandManager.java | 59 +++---- .../commands/jline/JLineCommandSender.java | 8 + pom.xml | 2 +- 21 files changed, 540 insertions(+), 169 deletions(-) create mode 100644 cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitCommandMeta.java create mode 100644 cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitCommandMetaBuilder.java create mode 100644 cloud-core/src/main/java/com/intellectualsites/commands/meta/CommandMeta.java create mode 100644 cloud-core/src/main/java/com/intellectualsites/commands/meta/SimpleCommandMeta.java diff --git a/cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitCommandManager.java b/cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitCommandManager.java index 8573f018..f88dad9a 100644 --- a/cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitCommandManager.java +++ b/cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitCommandManager.java @@ -33,7 +33,7 @@ import java.util.function.Function; * Command manager for the Bukkit platform, using {@link BukkitCommandSender} as the * command sender type */ -public class BukkitCommandManager extends CommandManager { +public class BukkitCommandManager extends CommandManager { private final Plugin owningPlugin; @@ -45,8 +45,8 @@ public class BukkitCommandManager extends CommandManager { * @throws Exception If the construction of the manager fails */ public BukkitCommandManager(@Nonnull final Plugin owningPlugin, - @Nonnull final Function, - CommandExecutionCoordinator> commandExecutionCoordinator) + @Nonnull final Function, + CommandExecutionCoordinator> commandExecutionCoordinator) throws Exception { super(commandExecutionCoordinator, new BukkitPluginRegistrationHandler()); ((BukkitPluginRegistrationHandler) this.getCommandRegistrationHandler()).initialize(this); diff --git a/cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitCommandMeta.java b/cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitCommandMeta.java new file mode 100644 index 00000000..4635f76b --- /dev/null +++ b/cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitCommandMeta.java @@ -0,0 +1,36 @@ +// +// MIT License +// +// Copyright (c) 2020 IntellectualSites +// +// 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 com.intellectualsites.commands.meta.SimpleCommandMeta; + +import javax.annotation.Nonnull; + +public class BukkitCommandMeta extends SimpleCommandMeta { + + public BukkitCommandMeta(@Nonnull final SimpleCommandMeta simpleCommandMeta) { + super(simpleCommandMeta.getAll()); + } + +} diff --git a/cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitCommandMetaBuilder.java b/cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitCommandMetaBuilder.java new file mode 100644 index 00000000..bd290b28 --- /dev/null +++ b/cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitCommandMetaBuilder.java @@ -0,0 +1,65 @@ +// +// MIT License +// +// Copyright (c) 2020 IntellectualSites +// +// 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 com.intellectualsites.commands.meta.CommandMeta; + +import javax.annotation.Nonnull; + +public final class BukkitCommandMetaBuilder { + + private BukkitCommandMetaBuilder() { + } + + @Nonnull public static BuilderStage1 builder() { + return new BuilderStage1(); + } + + public static final class BuilderStage1 { + + private BuilderStage1() { + } + + @Nonnull public BuilderStage2 withDescription(@Nonnull final String description) { + return new BuilderStage2(description); + } + + } + + + public static final class BuilderStage2 { + + private final String description; + + private BuilderStage2(@Nonnull final String description) { + this.description = description; + } + + @Nonnull public BukkitCommandMeta build() { + return new BukkitCommandMeta(CommandMeta.simple().with("description", this.description).build()); + } + + } + +} diff --git a/cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitPluginRegistrationHandler.java b/cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitPluginRegistrationHandler.java index afe2061b..7342d6b5 100644 --- a/cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitPluginRegistrationHandler.java +++ b/cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitPluginRegistrationHandler.java @@ -35,7 +35,7 @@ import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; -final class BukkitPluginRegistrationHandler implements CommandRegistrationHandler { +final class BukkitPluginRegistrationHandler implements CommandRegistrationHandler { private final Map, org.bukkit.command.Command> registeredCommands = new HashMap<>(); @@ -59,7 +59,7 @@ final class BukkitPluginRegistrationHandler implements CommandRegistrationHandle } @Override - public boolean registerCommand(@Nonnull final Command command) { + public boolean registerCommand(@Nonnull final Command command) { /* We only care about the root command component */ final CommandComponent commandComponent = command.getComponents().get(0); if (this.registeredCommands.containsKey(commandComponent)) { @@ -71,6 +71,7 @@ final class BukkitPluginRegistrationHandler implements CommandRegistrationHandle } else { label = commandComponent.getName(); } + @SuppressWarnings("unchecked") final BukkitCommand bukkitCommand = new BukkitCommand((CommandComponent) commandComponent, this.bukkitCommandManager); this.bukkitCommands.put(label, bukkitCommand); 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 6f1d9df2..dbda2e3e 100644 --- a/cloud-core/src/main/java/com/intellectualsites/commands/Command.java +++ b/cloud-core/src/main/java/com/intellectualsites/commands/Command.java @@ -26,6 +26,7 @@ package com.intellectualsites.commands; import com.intellectualsites.commands.components.CommandComponent; import com.intellectualsites.commands.components.StaticComponent; import com.intellectualsites.commands.execution.CommandExecutionHandler; +import com.intellectualsites.commands.meta.CommandMeta; import com.intellectualsites.commands.sender.CommandSender; import javax.annotation.Nonnull; @@ -35,24 +36,28 @@ import java.util.LinkedList; import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.function.Consumer; /** * A command consists out of a chain of {@link com.intellectualsites.commands.components.CommandComponent command components}. * * @param Command sender type + * @param Command meta type */ @SuppressWarnings("unused") -public class Command { +public class Command { @Nonnull private final List> components; @Nonnull private final CommandExecutionHandler commandExecutionHandler; @Nullable private final Class senderType; @Nonnull private final String commandPermission; + @Nonnull private final M commandMeta; public Command(@Nonnull final List> commandComponents, @Nonnull final CommandExecutionHandler commandExecutionHandler, @Nullable final Class senderType, - @Nonnull final String commandPermission) { + @Nonnull final String commandPermission, + @Nonnull final M commandMeta) { this.components = Objects.requireNonNull(commandComponents, "Command components may not be null"); if (this.components.size() == 0) { throw new IllegalArgumentException("At least one command component is required"); @@ -74,18 +79,21 @@ public class Command { this.commandExecutionHandler = commandExecutionHandler; this.senderType = senderType; this.commandPermission = commandPermission; + this.commandMeta = commandMeta; } public Command(@Nonnull final List> commandComponents, @Nonnull final CommandExecutionHandler commandExecutionHandler, - @Nullable final Class senderType) { - this(commandComponents, commandExecutionHandler, senderType, ""); + @Nullable final Class senderType, + @Nonnull final M commandMeta) { + this(commandComponents, commandExecutionHandler, senderType, "", commandMeta); } public Command(@Nonnull final List> commandComponents, @Nonnull final CommandExecutionHandler commandExecutionHandler, - @Nonnull final String commandPermission) { - this(commandComponents, commandExecutionHandler, null, ""); + @Nonnull final String commandPermission, + @Nonnull final M commandMeta) { + this(commandComponents, commandExecutionHandler, null, "", commandMeta); } /** @@ -95,8 +103,9 @@ public class Command { * @return Command builder */ @Nonnull - public static Builder newBuilder(@Nonnull final String commandName) { - return new Builder<>(null, Collections.singletonList(StaticComponent.required(commandName)), + public static Builder newBuilder(@Nonnull final String commandName, + @Nonnull final M commandMeta) { + return new Builder<>(commandMeta, null, Collections.singletonList(StaticComponent.required(commandName)), new CommandExecutionHandler.NullCommandExecutionHandler<>(), ""); } @@ -140,13 +149,23 @@ public class Command { return this.commandPermission; } + /** + * Get the command meta instance + * + * @return Command meta + */ + @Nonnull + public M getCommandMeta() { + return this.commandMeta; + } + /** * Get the longest chain of similar components for * two commands * * @return List containing the longest shared component chain */ - public List> getSharedComponentChain(@Nonnull final Command other) { + public List> getSharedComponentChain(@Nonnull final Command other) { final List> commandComponents = new LinkedList<>(); for (int i = 0; i < this.components.size() && i < other.components.size(); i++) { if (this.components.get(i).equals(other.components.get(i))) { @@ -164,15 +183,18 @@ public class Command { * setter method will return a new builder instance. * * @param Command sender type + * @param Command meta type */ - public static final class Builder { + public static final class Builder { + @Nonnull private final M commandMeta; @Nonnull private final List> commandComponents; @Nonnull private final CommandExecutionHandler commandExecutionHandler; @Nullable private final Class senderType; @Nonnull private final String commandPermission; - private Builder(@Nullable final Class senderType, + private Builder(@Nonnull final M commandMeta, + @Nullable final Class senderType, @Nonnull final List> commandComponents, @Nonnull final CommandExecutionHandler commandExecutionHandler, @Nonnull final String commandPermission) { @@ -180,6 +202,7 @@ public class Command { 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"); + this.commandMeta = Objects.requireNonNull(commandMeta, "Meta may not be null"); } /** @@ -190,10 +213,28 @@ public class Command { * @return New builder instance with the command component inserted into the component list */ @Nonnull - public Builder withComponent(@Nonnull final CommandComponent component) { + public Builder withComponent(@Nonnull final CommandComponent component) { final List> commandComponents = new LinkedList<>(this.commandComponents); commandComponents.add(component); - return new Builder<>(this.senderType, commandComponents, this.commandExecutionHandler, this.commandPermission); + return new Builder<>(this.commandMeta, this.senderType, commandComponents, this.commandExecutionHandler, this.commandPermission); + } + + /** + * Add a new command component by interacting with a constructed command component builder + * + * @param clazz Component class + * @param name Component name + * @param builderConsumer Builder consumer + * @param Component type + * @return New builder instance with the command component inserted into the component list + */ + @Nonnull + public Builder withComponent(@Nonnull final Class clazz, + @Nonnull final String name, + @Nonnull final Consumer> builderConsumer) { + final CommandComponent.Builder builder = CommandComponent.ofType(clazz, name); + builderConsumer.accept(builder); + return this.withComponent(builder.build()); } /** @@ -203,8 +244,8 @@ public class Command { * @return New builder instance using the command execution handler */ @Nonnull - public Builder withHandler(@Nonnull final CommandExecutionHandler commandExecutionHandler) { - return new Builder<>(this.senderType, this.commandComponents, commandExecutionHandler, this.commandPermission); + public Builder withHandler(@Nonnull final CommandExecutionHandler commandExecutionHandler) { + return new Builder<>(this.commandMeta, this.senderType, this.commandComponents, commandExecutionHandler, this.commandPermission); } /** @@ -214,8 +255,8 @@ public class Command { * @return New builder instance using the command execution handler */ @Nonnull - public Builder withSenderType(@Nonnull final Class senderType) { - return new Builder<>(senderType, this.commandComponents, this.commandExecutionHandler, this.commandPermission); + public Builder withSenderType(@Nonnull final Class senderType) { + return new Builder<>(this.commandMeta, senderType, this.commandComponents, this.commandExecutionHandler, this.commandPermission); } /** @@ -225,8 +266,8 @@ public class Command { * @return New builder instance using the command permission */ @Nonnull - public Builder withPermission(@Nonnull final String permission) { - return new Builder<>(this.senderType, this.commandComponents, this.commandExecutionHandler, permission); + public Builder withPermission(@Nonnull final String permission) { + return new Builder<>(this.commandMeta, this.senderType, this.commandComponents, this.commandExecutionHandler, permission); } /** @@ -235,9 +276,9 @@ public class Command { * @return Built command */ @Nonnull - public Command build() { + public Command build() { return new Command<>(Collections.unmodifiableList(this.commandComponents), this.commandExecutionHandler, - this.senderType, this.commandPermission); + this.senderType, this.commandPermission, this.commandMeta); } } 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 ae62ea97..570fd5da 100644 --- a/cloud-core/src/main/java/com/intellectualsites/commands/CommandManager.java +++ b/cloud-core/src/main/java/com/intellectualsites/commands/CommandManager.java @@ -30,6 +30,7 @@ import com.intellectualsites.commands.context.StandardCommandContextFactory; import com.intellectualsites.commands.execution.CommandExecutionCoordinator; import com.intellectualsites.commands.execution.CommandResult; import com.intellectualsites.commands.internal.CommandRegistrationHandler; +import com.intellectualsites.commands.meta.CommandMeta; import com.intellectualsites.commands.sender.CommandSender; import javax.annotation.Nonnull; @@ -44,19 +45,20 @@ import java.util.function.Function; * The manager is responsible for command registration, parsing delegation, etc. * * @param Command sender type + * @param Commamd meta type */ -public abstract class CommandManager { +public abstract class CommandManager { private final CommandContextFactory commandContextFactory = new StandardCommandContextFactory<>(); - private final CommandExecutionCoordinator commandExecutionCoordinator; - private final CommandRegistrationHandler commandRegistrationHandler; - private final CommandTree commandTree; + private final CommandExecutionCoordinator commandExecutionCoordinator; + private final CommandRegistrationHandler commandRegistrationHandler; + private final CommandTree commandTree; private CommandSyntaxFormatter commandSyntaxFormatter = new StandardCommandSyntaxFormatter<>(); - public CommandManager(@Nonnull final Function, CommandExecutionCoordinator> commandExecutionCoordinator, - @Nonnull final CommandRegistrationHandler commandRegistrationHandler) { + public CommandManager(@Nonnull final Function, CommandExecutionCoordinator> commandExecutionCoordinator, + @Nonnull final CommandRegistrationHandler commandRegistrationHandler) { this.commandTree = CommandTree.newTree(this, commandRegistrationHandler); this.commandExecutionCoordinator = commandExecutionCoordinator.apply(commandTree); this.commandRegistrationHandler = commandRegistrationHandler; @@ -103,7 +105,7 @@ public abstract class CommandManager { * @param command Command to register * @return The command manager instance */ - public CommandManager registerCommand(@Nonnull final Command command) { + public CommandManager registerCommand(@Nonnull final Command command) { this.commandTree.insertCommand(command); return this; } @@ -141,11 +143,12 @@ public abstract class CommandManager { * Create a new command builder * * @param name Command name + * @param meta Command meta * @return Builder instance */ @Nonnull - public Command.Builder commandBuilder(@Nonnull final String name) { - return Command.newBuilder(name); + public Command.Builder commandBuilder(@Nonnull final String name, @Nonnull final M meta) { + return Command.newBuilder(name, meta); } /** @@ -154,7 +157,7 @@ public abstract class CommandManager { * * @return Command tree */ - @Nonnull CommandTree getCommandTree() { + @Nonnull CommandTree getCommandTree() { return this.commandTree; } 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 0c8d2367..2456f4ab 100644 --- a/cloud-core/src/main/java/com/intellectualsites/commands/CommandTree.java +++ b/cloud-core/src/main/java/com/intellectualsites/commands/CommandTree.java @@ -25,13 +25,14 @@ package com.intellectualsites.commands; import com.intellectualsites.commands.components.CommandComponent; import com.intellectualsites.commands.components.StaticComponent; +import com.intellectualsites.commands.components.parser.ComponentParseResult; import com.intellectualsites.commands.context.CommandContext; import com.intellectualsites.commands.exceptions.ComponentParseException; import com.intellectualsites.commands.exceptions.InvalidSyntaxException; import com.intellectualsites.commands.exceptions.NoPermissionException; import com.intellectualsites.commands.exceptions.NoSuchCommandException; import com.intellectualsites.commands.internal.CommandRegistrationHandler; -import com.intellectualsites.commands.components.parser.ComponentParseResult; +import com.intellectualsites.commands.meta.CommandMeta; import com.intellectualsites.commands.sender.CommandSender; import javax.annotation.Nonnull; @@ -52,14 +53,17 @@ import java.util.stream.Collectors; * Tree containing all commands and command paths * * @param Command sender type + * @param Command meta type */ -public class CommandTree { +public class CommandTree { + + private final Object commandLock = new Object(); private final Node> internalTree = new Node<>(null); - private final CommandManager commandManager; + private final CommandManager commandManager; private final CommandRegistrationHandler commandRegistrationHandler; - private CommandTree(@Nonnull final CommandManager commandManager, + private CommandTree(@Nonnull final CommandManager commandManager, @Nonnull final CommandRegistrationHandler commandRegistrationHandler) { this.commandManager = commandManager; this.commandRegistrationHandler = commandRegistrationHandler; @@ -71,46 +75,48 @@ public class CommandTree { * @param commandManager Command manager * @param commandRegistrationHandler Command registration handler * @param Command sender type + * @param Command meta type * @return New command tree */ @Nonnull - public static CommandTree newTree(@Nonnull final CommandManager commandManager, - @Nonnull - final CommandRegistrationHandler commandRegistrationHandler) { + public static CommandTree newTree( + @Nonnull final CommandManager commandManager, + @Nonnull final CommandRegistrationHandler commandRegistrationHandler) { return new CommandTree<>(commandManager, commandRegistrationHandler); } - public Optional> parse(@Nonnull final CommandContext commandContext, @Nonnull final Queue args) throws + public Optional> parse(@Nonnull final CommandContext commandContext, + @Nonnull final Queue args) throws NoSuchCommandException { return parseCommand(commandContext, args, this.internalTree); } - private Optional> parseCommand(@Nonnull final CommandContext commandContext, - @Nonnull final Queue commandQueue, - @Nonnull final Node> root) { + private Optional> parseCommand(@Nonnull final CommandContext commandContext, + @Nonnull final Queue commandQueue, + @Nonnull final Node> root) { String permission; if ((permission = this.isPermitted(commandContext.getCommandSender(), root)) != null) { - throw new NoPermissionException(permission, commandContext.getCommandSender(), this.getChain(root) - .stream() - .map(Node::getValue) - .collect(Collectors.toList())); + throw new NoPermissionException(permission, commandContext.getCommandSender(), this.getChain(root) + .stream() + .map(Node::getValue) + .collect(Collectors.toList())); } final List>> children = root.getChildren(); if (children.size() == 1 && !(children.get(0).getValue() instanceof StaticComponent)) { // The value has to be a variable final Node> child = children.get(0); if ((permission = this.isPermitted(commandContext.getCommandSender(), child)) != null) { - throw new NoPermissionException(permission, commandContext.getCommandSender(), this.getChain(child) - .stream() - .map(Node::getValue) - .collect(Collectors.toList())); + throw new NoPermissionException(permission, commandContext.getCommandSender(), this.getChain(child) + .stream() + .map(Node::getValue) + .collect(Collectors.toList())); } if (child.getValue() != null) { if (commandQueue.isEmpty()) { if (child.getValue().hasDefaultValue()) { commandQueue.add(child.getValue().getDefaultValue()); } else if (!child.getValue().isRequired()) { - return Optional.ofNullable(child.getValue().getOwningCommand()); + return Optional.ofNullable(this.cast(child.getValue().getOwningCommand())); } else if (child.isLeaf()) { /* Not enough arguments */ throw new InvalidSyntaxException(this.commandManager.getCommandSyntaxFormatter() @@ -135,7 +141,7 @@ public class CommandTree { commandContext.store(child.getValue().getName(), result.getParsedValue().get()); if (child.isLeaf()) { if (commandQueue.isEmpty()) { - return Optional.ofNullable(child.getValue().getOwningCommand()); + return Optional.ofNullable(this.cast(child.getValue().getOwningCommand())); } else { /* Too many arguments. We have a unique path, so we can send the entire context */ throw new InvalidSyntaxException(this.commandManager.getCommandSyntaxFormatter() @@ -152,10 +158,11 @@ public class CommandTree { return this.parseCommand(commandContext, commandQueue, child); } } else if (result.getFailure().isPresent()) { - throw new ComponentParseException(result.getFailure().get(), commandContext.getCommandSender(), this.getChain(child) - .stream() - .map(Node::getValue) - .collect(Collectors.toList())); + throw new ComponentParseException(result.getFailure().get(), commandContext.getCommandSender(), + this.getChain(child) + .stream() + .map(Node::getValue) + .collect(Collectors.toList())); } } } @@ -164,7 +171,7 @@ public class CommandTree { /* We are at the bottom. Check if there's a command attached, in which case we're done */ if (root.getValue() != null && root.getValue().getOwningCommand() != null) { if (commandQueue.isEmpty()) { - return Optional.of(root.getValue().getOwningCommand()); + return Optional.ofNullable(this.cast(root.getValue().getOwningCommand())); } else { /* Too many arguments. We have a unique path, so we can send the entire context */ throw new InvalidSyntaxException(this.commandManager.getCommandSyntaxFormatter() @@ -291,24 +298,26 @@ public class CommandTree { * * @param command Command to insert */ - public void insertCommand(@Nonnull final Command command) { - Node> node = this.internalTree; - for (final CommandComponent component : command.getComponents()) { - Node> tempNode = node.getChild(component); - if (tempNode == null) { - tempNode = node.addChild(component); + public void insertCommand(@Nonnull final Command command) { + synchronized (this.commandLock) { + Node> node = this.internalTree; + for (final CommandComponent component : command.getComponents()) { + Node> tempNode = node.getChild(component); + if (tempNode == null) { + tempNode = node.addChild(component); + } + if (node.children.size() > 0) { + node.children.sort(Comparator.comparing(Node::getValue)); + } + tempNode.setParent(node); + node = tempNode; } - if (node.children.size() > 0) { - node.children.sort(Comparator.comparing(Node::getValue)); + if (node.getValue() != null) { + node.getValue().setOwningCommand(command); } - tempNode.setParent(node); - node = tempNode; + // Verify the command structure every time we add a new command + this.verifyAndRegister(); } - if (node.getValue() != null) { - node.getValue().setOwningCommand(command); - } - // Verify the command structure every time we add a new command - this.verifyAndRegister(); } @Nullable @@ -318,9 +327,10 @@ public class CommandTree { return sender.hasPermission(permission) ? null : permission; } if (node.isLeaf()) { - return sender.hasPermission(Objects.requireNonNull(Objects.requireNonNull(node.value, "node.value").getOwningCommand(), - "owning command").getCommandPermission()) - ? null : node.value.getOwningCommand().getCommandPermission(); + return sender.hasPermission( + Objects.requireNonNull(Objects.requireNonNull(node.value, "node.value").getOwningCommand(), + "owning command").getCommandPermission()) + ? null : node.value.getOwningCommand().getCommandPermission(); } /* if any of the children would permit the execution, then the sender has a valid @@ -372,7 +382,9 @@ public class CommandTree { // Go through all nodes from the tail upwards until a collision occurs for (final Node> commandComponentNode : chain) { if (commandComponentNode.nodeMeta.containsKey("permission") && !commandComponentNode.nodeMeta.get("permission") - .equalsIgnoreCase(node.nodeMeta.get("permission"))) { + .equalsIgnoreCase( + node.nodeMeta + .get("permission"))) { commandComponentNode.nodeMeta.put("permission", ""); } else { commandComponentNode.nodeMeta.put("permission", node.nodeMeta.get("permission")); @@ -431,6 +443,15 @@ public class CommandTree { return chain; } + @Nullable private Command cast(@Nullable final Command command) { + if (command == null) { + return null; + } + @SuppressWarnings("unchecked") + final Command casted = (Command) command; + return casted; + } + /** * Very simple tree structure diff --git a/cloud-core/src/main/java/com/intellectualsites/commands/components/CommandComponent.java b/cloud-core/src/main/java/com/intellectualsites/commands/components/CommandComponent.java index 8e08741e..a88376c9 100644 --- a/cloud-core/src/main/java/com/intellectualsites/commands/components/CommandComponent.java +++ b/cloud-core/src/main/java/com/intellectualsites/commands/components/CommandComponent.java @@ -24,6 +24,7 @@ package com.intellectualsites.commands.components; import com.intellectualsites.commands.Command; +import com.intellectualsites.commands.components.parser.ComponentParseResult; import com.intellectualsites.commands.components.parser.ComponentParser; import com.intellectualsites.commands.sender.CommandSender; @@ -45,7 +46,7 @@ public class CommandComponent implements Comparable< /** * Indicates whether or not the component is required - * or not. All c$ git ls-files | xargs wc -lomponents prior to any other required + * or not. All components prior to any other required * component must also be required, such that the predicate * (∀ c_i ∈ required)({c_0, ..., c_i-1} ⊂ required) holds true, * where {c_0, ..., c_n-1} is the set of command components. @@ -66,7 +67,7 @@ public class CommandComponent implements Comparable< */ private final String defaultValue; - private Command owningCommand; + private Command owningCommand; public CommandComponent(final boolean required, @Nonnull final String name, @Nonnull final ComponentParser parser, @Nonnull final String defaultValue) { @@ -88,13 +89,14 @@ public class CommandComponent implements Comparable< * Create a new command component * * @param clazz Argument class + * @param name Component name * @param Command sender type * @param Argument Type. Used to make the compiler happy. * @return Component builder */ @Nonnull - public static CommandComponent.Builder ofType(@Nonnull final Class clazz) { - return new Builder<>(); + public static CommandComponent.Builder ofType(@Nonnull final Class clazz, @Nonnull final String name) { + return new Builder<>(name); } /** @@ -139,7 +141,7 @@ public class CommandComponent implements Comparable< * @return Owning command */ @Nullable - public Command getOwningCommand() { + public Command getOwningCommand() { return this.owningCommand; } @@ -148,7 +150,7 @@ public class CommandComponent implements Comparable< * * @param owningCommand Owning command */ - public void setOwningCommand(@Nonnull final Command owningCommand) { + public void setOwningCommand(@Nonnull final Command owningCommand) { if (this.owningCommand != null) { throw new IllegalStateException("Cannot replace owning command"); } @@ -217,24 +219,13 @@ public class CommandComponent implements Comparable< */ public static class Builder { - protected String name; + protected final String name; protected boolean required = true; - protected ComponentParser parser; + protected ComponentParser parser = (c, i) -> ComponentParseResult.failure(new UnsupportedOperationException("No parser was specified")); protected String defaultValue = ""; - protected Builder() { - } - - /** - * Set the component name. Must be alphanumeric - * - * @param name Alphanumeric component name - * @return Builder instance - */ - @Nonnull - public Builder named(@Nonnull final String name) { + protected Builder(@Nonnull final String name) { this.name = name; - return this; } /** diff --git a/cloud-core/src/main/java/com/intellectualsites/commands/components/standard/ByteComponent.java b/cloud-core/src/main/java/com/intellectualsites/commands/components/standard/ByteComponent.java index 03e83ef3..d7e5c718 100644 --- a/cloud-core/src/main/java/com/intellectualsites/commands/components/standard/ByteComponent.java +++ b/cloud-core/src/main/java/com/intellectualsites/commands/components/standard/ByteComponent.java @@ -46,18 +46,22 @@ public class ByteComponent extends CommandComponent Builder newBuilder() { - return new Builder<>(); + public static Builder newBuilder(@Nonnull final String name) { + return new Builder<>(name); } @Nonnull public static CommandComponent required(@Nonnull final String name) { - return ByteComponent.newBuilder().named(name).asRequired().build(); + return ByteComponent.newBuilder(name).asRequired().build(); } @Nonnull public static CommandComponent optional(@Nonnull final String name) { - return ByteComponent.newBuilder().named(name).asOptional().build(); + return ByteComponent.newBuilder(name).asOptional().build(); + } + + @Nonnull public static CommandComponent optional(@Nonnull final String name, final byte defaultNum) { + return ByteComponent.newBuilder(name).asOptionalWithDefault(Byte.toString(defaultNum)).build(); } @@ -66,6 +70,10 @@ public class ByteComponent extends CommandComponent withMin(final byte min) { this.min = min; diff --git a/cloud-core/src/main/java/com/intellectualsites/commands/components/standard/IntegerComponent.java b/cloud-core/src/main/java/com/intellectualsites/commands/components/standard/IntegerComponent.java index f4902872..603ea442 100644 --- a/cloud-core/src/main/java/com/intellectualsites/commands/components/standard/IntegerComponent.java +++ b/cloud-core/src/main/java/com/intellectualsites/commands/components/standard/IntegerComponent.java @@ -45,20 +45,20 @@ public class IntegerComponent extends CommandComponent< this.max = max; } - @Nonnull public static Builder newBuilder() { - return new Builder<>(); + @Nonnull public static Builder newBuilder(@Nonnull final String name) { + return new Builder<>(name); } @Nonnull public static CommandComponent required(@Nonnull final String name) { - return IntegerComponent.newBuilder().named(name).asRequired().build(); + return IntegerComponent.newBuilder(name).asRequired().build(); } @Nonnull public static CommandComponent optional(@Nonnull final String name) { - return IntegerComponent.newBuilder().named(name).asOptional().build(); + return IntegerComponent.newBuilder(name).asOptional().build(); } @Nonnull public static CommandComponent optional(@Nonnull final String name, final int defaultNum) { - return IntegerComponent.newBuilder().named(name).asOptionalWithDefault(Integer.toString(defaultNum)).build(); + return IntegerComponent.newBuilder(name).asOptionalWithDefault(Integer.toString(defaultNum)).build(); } @@ -67,6 +67,10 @@ public class IntegerComponent extends CommandComponent< private int min = Integer.MIN_VALUE; private int max = Integer.MAX_VALUE; + protected Builder(@Nonnull final String name) { + super(name); + } + @Nonnull public Builder withMin(final int min) { this.min = min; return this; diff --git a/cloud-core/src/main/java/com/intellectualsites/commands/execution/CommandExecutionCoordinator.java b/cloud-core/src/main/java/com/intellectualsites/commands/execution/CommandExecutionCoordinator.java index e8173f21..a3322da6 100644 --- a/cloud-core/src/main/java/com/intellectualsites/commands/execution/CommandExecutionCoordinator.java +++ b/cloud-core/src/main/java/com/intellectualsites/commands/execution/CommandExecutionCoordinator.java @@ -23,6 +23,7 @@ // package com.intellectualsites.commands.execution; +import com.intellectualsites.commands.meta.CommandMeta; import com.intellectualsites.commands.CommandTree; import com.intellectualsites.commands.context.CommandContext; import com.intellectualsites.commands.sender.CommandSender; @@ -39,17 +40,18 @@ import java.util.function.Function; * not command may be executed in parallel, etc. * * @param Command sender type + * @param Command meta type */ -public abstract class CommandExecutionCoordinator { +public abstract class CommandExecutionCoordinator { - private final CommandTree commandTree; + private final CommandTree commandTree; /** * Construct a new command execution coordinator * * @param commandTree Command tree */ - public CommandExecutionCoordinator(@Nonnull final CommandTree commandTree) { + public CommandExecutionCoordinator(@Nonnull final CommandTree commandTree) { this.commandTree = commandTree; } @@ -57,9 +59,10 @@ public abstract class CommandExecutionCoordinator { * Returns a simple command execution coordinator that executes all commands immediately, on the calling thread * * @param Command sender type + * @param Command meta type * @return New coordinator instance */ - public static Function, CommandExecutionCoordinator> simpleCoordinator() { + public static Function, CommandExecutionCoordinator> simpleCoordinator() { return SimpleCoordinator::new; } @@ -72,7 +75,7 @@ public abstract class CommandExecutionCoordinator { * @return Command tree */ @Nonnull - protected CommandTree getCommandTree() { + protected CommandTree getCommandTree() { return this.commandTree; } @@ -81,10 +84,11 @@ public abstract class CommandExecutionCoordinator { * A simple command execution coordinator that executes all commands immediately, on the calling thread * * @param Command sender type + * @param Command meta type */ - public static final class SimpleCoordinator extends CommandExecutionCoordinator { + public static final class SimpleCoordinator extends CommandExecutionCoordinator { - private SimpleCoordinator(@Nonnull final CommandTree commandTree) { + private SimpleCoordinator(@Nonnull final CommandTree commandTree) { super(commandTree); } diff --git a/cloud-core/src/main/java/com/intellectualsites/commands/internal/CommandRegistrationHandler.java b/cloud-core/src/main/java/com/intellectualsites/commands/internal/CommandRegistrationHandler.java index e374ae02..502ecd18 100644 --- a/cloud-core/src/main/java/com/intellectualsites/commands/internal/CommandRegistrationHandler.java +++ b/cloud-core/src/main/java/com/intellectualsites/commands/internal/CommandRegistrationHandler.java @@ -24,6 +24,7 @@ package com.intellectualsites.commands.internal; import com.intellectualsites.commands.Command; +import com.intellectualsites.commands.meta.CommandMeta; import javax.annotation.Nonnull; @@ -31,14 +32,11 @@ import javax.annotation.Nonnull; * Utility that registers commands natively for whatever * platform the library is used in. This can do nothing, if * the target platform does not have its own concept of commands + * + * @param Command meta type */ @FunctionalInterface -public interface CommandRegistrationHandler { - - /** - * Command registration handler that does nothing - */ - NullCommandRegistrationHandler NULL_COMMAND_REGISTRATION_HANDLER = new NullCommandRegistrationHandler(); +public interface CommandRegistrationHandler { /** * Attempt to register the command @@ -47,16 +45,20 @@ public interface CommandRegistrationHandler { * @return {@code true} if the command was registered successfully, * else {@code false} */ - boolean registerCommand(@Nonnull final Command command); + boolean registerCommand(@Nonnull final Command command); + + static CommandRegistrationHandler nullCommandRegistrationHandler() { + return new NullCommandRegistrationHandler<>(); + } - final class NullCommandRegistrationHandler implements CommandRegistrationHandler { + final class NullCommandRegistrationHandler implements CommandRegistrationHandler { private NullCommandRegistrationHandler() { } @Override - public boolean registerCommand(@Nonnull final Command command) { + public boolean registerCommand(@Nonnull final Command command) { return true; } diff --git a/cloud-core/src/main/java/com/intellectualsites/commands/meta/CommandMeta.java b/cloud-core/src/main/java/com/intellectualsites/commands/meta/CommandMeta.java new file mode 100644 index 00000000..b7ef4b77 --- /dev/null +++ b/cloud-core/src/main/java/com/intellectualsites/commands/meta/CommandMeta.java @@ -0,0 +1,34 @@ +// +// MIT License +// +// Copyright (c) 2020 IntellectualSites +// +// 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.meta; + +import javax.annotation.Nonnull; + +public class CommandMeta { + + @Nonnull public static SimpleCommandMeta.Builder simple() { + return SimpleCommandMeta.builder(); + } + +} diff --git a/cloud-core/src/main/java/com/intellectualsites/commands/meta/SimpleCommandMeta.java b/cloud-core/src/main/java/com/intellectualsites/commands/meta/SimpleCommandMeta.java new file mode 100644 index 00000000..0eac867e --- /dev/null +++ b/cloud-core/src/main/java/com/intellectualsites/commands/meta/SimpleCommandMeta.java @@ -0,0 +1,149 @@ +// +// MIT License +// +// Copyright (c) 2020 IntellectualSites +// +// 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.meta; + +import javax.annotation.Nonnull; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +/** + * A simple immutable string-string map containing command meta + */ +public class SimpleCommandMeta extends CommandMeta { + + private final Map metaMap; + + protected SimpleCommandMeta(@Nonnull final Map metaMap) { + this.metaMap = Collections.unmodifiableMap(metaMap); + } + + /** + * Create a new meta builder + * + * @return Builder instance + */ + @Nonnull + public static SimpleCommandMeta.Builder builder() { + return new Builder(); + } + + /** + * Create an empty simple command meta instance + * + * @return Empty instance + */ + @Nonnull public static SimpleCommandMeta empty() { + return SimpleCommandMeta.builder().build(); + } + + + /** + * Get the value associated with a key + * + * @param key Key + * @return Optional that may contain the associated value + */ + @Nonnull + public Optional getValue(@Nonnull final String key) { + return Optional.ofNullable(this.metaMap.get(key)); + } + + /** + * Get the value if it exists, else return the default value + * + * @param key Key + * @param defaultValue Default value + * @return Value, or default value + */ + @Nonnull + public String getOrDefault(@Nonnull final String key, @Nonnull final String defaultValue) { + return this.getValue(key).orElse(defaultValue); + } + + /** + * Get a copy of the meta map + * + * @return Copy of meta map + */ + @Nonnull + public Map getAll() { + return new HashMap<>(this.metaMap); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final SimpleCommandMeta that = (SimpleCommandMeta) o; + return Objects.equals(metaMap, that.metaMap); + } + + @Override + public int hashCode() { + return Objects.hashCode(metaMap); + } + + /** + * Builder for {@link SimpleCommandMeta} + */ + public static final class Builder { + + private final Map map = new HashMap<>(); + + private Builder() { + } + + /** + * Store a new key-value pair in the meta map + * + * @param key Key + * @param value Value + * @return Builder instance + */ + @Nonnull + public Builder with(@Nonnull final String key, @Nonnull final String value) { + this.map.put(key, value); + return this; + } + + /** + * Construct a new meta instance + * + * @return Meta instance + */ + @Nonnull + public SimpleCommandMeta build() { + return new SimpleCommandMeta(this.map); + } + + } + +} diff --git a/cloud-core/src/test/java/com/intellectualsites/commands/CommandTest.java b/cloud-core/src/test/java/com/intellectualsites/commands/CommandTest.java index 19855fa0..ada07b0a 100644 --- a/cloud-core/src/test/java/com/intellectualsites/commands/CommandTest.java +++ b/cloud-core/src/test/java/com/intellectualsites/commands/CommandTest.java @@ -24,23 +24,22 @@ package com.intellectualsites.commands; import com.intellectualsites.commands.components.StaticComponent; +import com.intellectualsites.commands.meta.SimpleCommandMeta; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - class CommandTest { @Test() void noComponents() { - Assertions.assertEquals(1, Command.newBuilder("test").build().getComponents().size()); + Assertions.assertEquals(1, Command.newBuilder("test", SimpleCommandMeta.empty()).build().getComponents().size()); } @Test void ensureOrdering() { Assertions.assertThrows(IllegalArgumentException.class, () -> - Command.newBuilder("test").withComponent(StaticComponent.optional("something")) - .withComponent(StaticComponent.required("somethingelse")).build()); + Command.newBuilder("test", SimpleCommandMeta.empty()).withComponent(StaticComponent.optional("something")) + .withComponent(StaticComponent.required("somethingelse")).build()); } } diff --git a/cloud-core/src/test/java/com/intellectualsites/commands/CommandTreeTest.java b/cloud-core/src/test/java/com/intellectualsites/commands/CommandTreeTest.java index 55a6b806..8e93e06a 100644 --- a/cloud-core/src/test/java/com/intellectualsites/commands/CommandTreeTest.java +++ b/cloud-core/src/test/java/com/intellectualsites/commands/CommandTreeTest.java @@ -27,6 +27,7 @@ import com.intellectualsites.commands.components.StaticComponent; import com.intellectualsites.commands.components.standard.IntegerComponent; import com.intellectualsites.commands.context.CommandContext; import com.intellectualsites.commands.exceptions.NoPermissionException; +import com.intellectualsites.commands.meta.SimpleCommandMeta; import com.intellectualsites.commands.sender.CommandSender; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -39,23 +40,23 @@ import java.util.Optional; class CommandTreeTest { - private static CommandManager commandManager; + private static CommandManager commandManager; @BeforeAll static void newTree() { commandManager = new TestCommandManager(); - commandManager.registerCommand(commandManager.commandBuilder("test") + commandManager.registerCommand(commandManager.commandBuilder("test", SimpleCommandMeta.empty()) .withComponent(StaticComponent.required("one")).build()) - .registerCommand(commandManager.commandBuilder("test") + .registerCommand(commandManager.commandBuilder("test", SimpleCommandMeta.empty()) .withComponent(StaticComponent.required("two")).withPermission("no").build()) - .registerCommand(commandManager.commandBuilder("test") + .registerCommand(commandManager.commandBuilder("test", SimpleCommandMeta.empty()) .withComponent(StaticComponent.required("opt")) .withComponent(IntegerComponent.optional("num", 15)).build()); } @Test void parse() { - final Optional> command = commandManager.getCommandTree().parse(new CommandContext<>(new TestCommandSender()), new LinkedList<>( + final Optional> command = commandManager.getCommandTree().parse(new CommandContext<>(new TestCommandSender()), new LinkedList<>( Arrays.asList("test", "one"))); Assertions.assertTrue(command.isPresent()); Assertions.assertThrows(NoPermissionException.class, () -> commandManager.getCommandTree().parse(new CommandContext<>(new TestCommandSender()), new LinkedList<>( diff --git a/cloud-core/src/test/java/com/intellectualsites/commands/TestCommandManager.java b/cloud-core/src/test/java/com/intellectualsites/commands/TestCommandManager.java index 3a12e15a..6cab6b2d 100644 --- a/cloud-core/src/test/java/com/intellectualsites/commands/TestCommandManager.java +++ b/cloud-core/src/test/java/com/intellectualsites/commands/TestCommandManager.java @@ -25,12 +25,13 @@ package com.intellectualsites.commands; import com.intellectualsites.commands.execution.CommandExecutionCoordinator; import com.intellectualsites.commands.internal.CommandRegistrationHandler; +import com.intellectualsites.commands.meta.SimpleCommandMeta; import com.intellectualsites.commands.sender.CommandSender; -public class TestCommandManager extends CommandManager { +public class TestCommandManager extends CommandManager { protected TestCommandManager() { - super(CommandExecutionCoordinator.simpleCoordinator(), CommandRegistrationHandler.NULL_COMMAND_REGISTRATION_HANDLER); + super(CommandExecutionCoordinator.simpleCoordinator(), CommandRegistrationHandler.nullCommandRegistrationHandler()); } } diff --git a/cloud-jline/pom.xml b/cloud-jline/pom.xml index 8c8ded6b..a4046f5c 100644 --- a/cloud-jline/pom.xml +++ b/cloud-jline/pom.xml @@ -3,7 +3,7 @@ xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - Commands + cloud com.intellectualsites 1.0-SNAPSHOT @@ -17,7 +17,7 @@ com.intellectualsites - cloud + cloud-core 1.0-SNAPSHOT diff --git a/cloud-jline/src/main/java/com/intellectualsites/commands/jline/JLineCommandManager.java b/cloud-jline/src/main/java/com/intellectualsites/commands/jline/JLineCommandManager.java index a0c8cae9..0ea6579b 100644 --- a/cloud-jline/src/main/java/com/intellectualsites/commands/jline/JLineCommandManager.java +++ b/cloud-jline/src/main/java/com/intellectualsites/commands/jline/JLineCommandManager.java @@ -23,16 +23,15 @@ // package com.intellectualsites.commands.jline; -import com.intellectualsites.commands.Command; import com.intellectualsites.commands.CommandManager; import com.intellectualsites.commands.CommandTree; -import com.intellectualsites.commands.components.CommandComponent; import com.intellectualsites.commands.components.StaticComponent; +import com.intellectualsites.commands.components.parser.ComponentParseResult; import com.intellectualsites.commands.exceptions.InvalidSyntaxException; import com.intellectualsites.commands.exceptions.NoSuchCommandException; import com.intellectualsites.commands.execution.CommandExecutionCoordinator; import com.intellectualsites.commands.internal.CommandRegistrationHandler; -import com.intellectualsites.commands.components.parser.ComponentParseResult; +import com.intellectualsites.commands.meta.SimpleCommandMeta; import org.jline.reader.Candidate; import org.jline.reader.Completer; import org.jline.reader.LineReader; @@ -48,11 +47,11 @@ import java.util.function.Function; /** * Command manager for use with JLine */ -public class JLineCommandManager extends CommandManager implements Completer { +public class JLineCommandManager extends CommandManager implements Completer { - public JLineCommandManager(@Nonnull - final Function, CommandExecutionCoordinator> executionCoordinatorFunction) { - super(executionCoordinatorFunction, CommandRegistrationHandler.NULL_COMMAND_REGISTRATION_HANDLER); + public JLineCommandManager(@Nonnull final Function, + CommandExecutionCoordinator> executionCoordinatorFunction) { + super(executionCoordinatorFunction, CommandRegistrationHandler.nullCommandRegistrationHandler()); } public static void main(String[] args) throws Exception { @@ -66,30 +65,34 @@ public class JLineCommandManager extends CommandManager impl .appName("Test") .build(); boolean[] shouldStop = new boolean[]{false}; - jLineCommandManager.registerCommand(Command.newBuilder("stop").withHandler(commandContext -> - shouldStop[0] = true).build()) - .registerCommand(Command.newBuilder("echo") - .withComponent( - CommandComponent.ofType(String.class).named("string").asRequired() - .withParser(((commandContext, inputQueue) -> { - final StringBuilder stringBuilder = new StringBuilder(); - while (!inputQueue.isEmpty()) { - stringBuilder.append(inputQueue.remove()); - if (!inputQueue.isEmpty()) { - stringBuilder.append(" "); - } - } - return ComponentParseResult.success( - stringBuilder.toString()); - })).build()) - .withHandler(commandContext -> commandContext.get("string") - .ifPresent(System.out::println)) - .build()) - .registerCommand(Command.newBuilder("test") + jLineCommandManager.registerCommand( + jLineCommandManager.commandBuilder("stop", SimpleCommandMeta.empty()) + .withHandler(commandContext -> + shouldStop[0] = true) + .build()) + .registerCommand(jLineCommandManager.commandBuilder("echo", SimpleCommandMeta.empty()) + .withComponent(String.class, "string", builder -> + builder.asRequired() + .withParser(((commandContext, inputQueue) -> { + final StringBuilder stringBuilder = new StringBuilder(); + while (!inputQueue.isEmpty()) { + stringBuilder.append(inputQueue.remove()); + if (!inputQueue.isEmpty()) { + stringBuilder.append(" "); + } + } + return ComponentParseResult.success( + stringBuilder.toString()); + })).build()) + .withHandler(commandContext -> commandContext.get("string") + .ifPresent( + System.out::println)) + .build()) + .registerCommand(jLineCommandManager.commandBuilder("test", SimpleCommandMeta.empty()) .withComponent(StaticComponent.required("one")) .withHandler(commandContext -> System.out.println("Test (1)")) .build()) - .registerCommand(Command.newBuilder("test") + .registerCommand(jLineCommandManager.commandBuilder("test", SimpleCommandMeta.empty()) .withComponent(StaticComponent.required("two")) .withHandler(commandContext -> System.out.println("Test (2)")) .build()); diff --git a/cloud-jline/src/main/java/com/intellectualsites/commands/jline/JLineCommandSender.java b/cloud-jline/src/main/java/com/intellectualsites/commands/jline/JLineCommandSender.java index e4f7aaf5..def4638c 100644 --- a/cloud-jline/src/main/java/com/intellectualsites/commands/jline/JLineCommandSender.java +++ b/cloud-jline/src/main/java/com/intellectualsites/commands/jline/JLineCommandSender.java @@ -25,5 +25,13 @@ package com.intellectualsites.commands.jline; import com.intellectualsites.commands.sender.CommandSender; +import javax.annotation.Nonnull; + public class JLineCommandSender implements CommandSender { + + @Override + public boolean hasPermission(@Nonnull final String permission) { + return true; + } + } diff --git a/pom.xml b/pom.xml index 50dd58b3..00c2a3d8 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ cloud 1.0-SNAPSHOT - + cloud-jline cloud-bukkit cloud-core