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