Merge pull request #3

* Start implementing command preprocessors

* Call the preprocessing step and also add a command suggestions processor

* Merge branch 'master' into preprocessing

* Improve command pre-processing
This commit is contained in:
Alexander Söderberg 2020-09-12 20:29:58 +02:00 committed by GitHub
parent 75f65c2da2
commit e01fd6af37
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 534 additions and 20 deletions

View file

@ -23,20 +23,29 @@
//
package com.intellectualsites.commands;
import com.google.common.reflect.TypeToken;
import com.intellectualsites.commands.components.CommandSyntaxFormatter;
import com.intellectualsites.commands.components.StandardCommandSyntaxFormatter;
import com.intellectualsites.commands.context.CommandContext;
import com.intellectualsites.commands.context.CommandContextFactory;
import com.intellectualsites.commands.context.StandardCommandContextFactory;
import com.intellectualsites.commands.execution.CommandExecutionCoordinator;
import com.intellectualsites.commands.execution.CommandResult;
import com.intellectualsites.commands.execution.CommandSuggestionProcessor;
import com.intellectualsites.commands.execution.FilteringCommandSuggestionProcessor;
import com.intellectualsites.commands.execution.preprocessor.CommandPreprocessingContext;
import com.intellectualsites.commands.execution.preprocessor.CommandPreprocessor;
import com.intellectualsites.commands.execution.preprocessor.AcceptingCommandPreprocessor;
import com.intellectualsites.commands.internal.CommandRegistrationHandler;
import com.intellectualsites.commands.meta.CommandMeta;
import com.intellectualsites.commands.sender.CommandSender;
import com.intellectualsites.services.ServicePipeline;
import com.intellectualsites.services.State;
import javax.annotation.Nonnull;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.StringTokenizer;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
@ -51,12 +60,14 @@ import java.util.function.Function;
public abstract class CommandManager<C extends CommandSender, M extends CommandMeta> {
private final CommandContextFactory<C> commandContextFactory = new StandardCommandContextFactory<>();
private final ServicePipeline servicePipeline = ServicePipeline.builder().build();
private final CommandExecutionCoordinator<C, M> commandExecutionCoordinator;
private final CommandRegistrationHandler<M> commandRegistrationHandler;
private final CommandTree<C, M> commandTree;
private CommandSyntaxFormatter<C> commandSyntaxFormatter = new StandardCommandSyntaxFormatter<>();
private CommandSuggestionProcessor<C> commandSuggestionProcessor = new FilteringCommandSuggestionProcessor<>();
/**
* Create a new command manager instance
@ -70,6 +81,8 @@ public abstract class CommandManager<C extends CommandSender, M extends CommandM
this.commandTree = CommandTree.newTree(this, commandRegistrationHandler);
this.commandExecutionCoordinator = commandExecutionCoordinator.apply(commandTree);
this.commandRegistrationHandler = commandRegistrationHandler;
this.servicePipeline.registerServiceType(new TypeToken<CommandPreprocessor<C>>() {
}, new AcceptingCommandPreprocessor<>());
}
/**
@ -80,9 +93,20 @@ public abstract class CommandManager<C extends CommandSender, M extends CommandM
* @return Command result
*/
@Nonnull
public CompletableFuture<CommandResult> executeCommand(@Nonnull final C commandSender, @Nonnull final String input) {
return this.commandExecutionCoordinator.coordinateExecution(this.commandContextFactory.create(commandSender),
tokenize(input));
public CompletableFuture<CommandResult<C>> executeCommand(@Nonnull final C commandSender, @Nonnull final String input) {
final CommandContext<C> context = this.commandContextFactory.create(commandSender);
final LinkedList<String> inputQueue = this.tokenize(input);
try {
if (this.preprocessContext(context, inputQueue) == State.ACCEPTED) {
return this.commandExecutionCoordinator.coordinateExecution(context, inputQueue);
}
} catch (final Exception e) {
final CompletableFuture<CommandResult<C>> future = new CompletableFuture<>();
future.completeExceptionally(e);
return future;
}
/* Wasn't allowed to execute the command */
return CompletableFuture.completedFuture(null);
}
/**
@ -95,13 +119,21 @@ public abstract class CommandManager<C extends CommandSender, M extends CommandM
*/
@Nonnull
public List<String> suggest(@Nonnull final C commandSender, @Nonnull final String input) {
return this.commandTree.getSuggestions(this.commandContextFactory.create(commandSender), tokenize(input));
final CommandContext<C> context = this.commandContextFactory.create(commandSender);
final LinkedList<String> inputQueue = this.tokenize(input);
if (this.preprocessContext(context, inputQueue) == State.ACCEPTED) {
return this.commandSuggestionProcessor.apply(new CommandPreprocessingContext<>(context, inputQueue),
this.commandTree.getSuggestions(
context, inputQueue));
} else {
return Collections.emptyList();
}
}
@Nonnull
private Queue<String> tokenize(@Nonnull final String input) {
private LinkedList<String> tokenize(@Nonnull final String input) {
final StringTokenizer stringTokenizer = new StringTokenizer(input, " ");
final Queue<String> tokens = new LinkedList<>();
final LinkedList<String> tokens = new LinkedList<>();
while (stringTokenizer.hasMoreElements()) {
tokens.add(stringTokenizer.nextToken());
}
@ -194,4 +226,52 @@ public abstract class CommandManager<C extends CommandSender, M extends CommandM
@Nonnull
public abstract M createDefaultCommandMeta();
/**
* Register a new command preprocessor. The order they are registered in is respected, and they
* are called in LIFO order
*
* @param processor Processor to register
*/
public void registerCommandPreProcessor(@Nonnull final CommandPreprocessor<C> processor) {
this.servicePipeline.registerServiceImplementation(new TypeToken<CommandPreprocessor<C>>() {
}, processor,
Collections.emptyList());
}
/**
* Preprocess a command context instance
*
* @param context Command context
* @param inputQueue Command input as supplied by sender
* @return {@link State#ACCEPTED} if the command should be parsed and executed, else {@link State#REJECTED}
*/
public State preprocessContext(@Nonnull final CommandContext<C> context, @Nonnull final LinkedList<String> inputQueue) {
this.servicePipeline.pump(new CommandPreprocessingContext<>(context, inputQueue))
.through(new TypeToken<CommandPreprocessor<C>>() {
})
.getResult();
return context.<String>get(AcceptingCommandPreprocessor.PROCESSED_INDICATOR_KEY).orElse("").isEmpty()
? State.REJECTED
: State.ACCEPTED;
}
/**
* Get the command suggestions processor instance currently used in this command manager
*
* @return Command suggestions processor
*/
@Nonnull
public CommandSuggestionProcessor<C> getCommandSuggestionProcessor() {
return this.commandSuggestionProcessor;
}
/**
* Set the command suggestions processor for this command manager
*
* @param commandSuggestionProcessor New command suggestions processor
*/
public void setCommandSuggestionProcessor(@Nonnull final CommandSuggestionProcessor<C> commandSuggestionProcessor) {
this.commandSuggestionProcessor = commandSuggestionProcessor;
}
}

View file

@ -23,9 +23,9 @@
//
package com.intellectualsites.commands.components;
import com.intellectualsites.commands.context.CommandContext;
import com.intellectualsites.commands.components.parser.ComponentParseResult;
import com.intellectualsites.commands.components.parser.ComponentParser;
import com.intellectualsites.commands.context.CommandContext;
import com.intellectualsites.commands.sender.CommandSender;
import javax.annotation.Nonnull;
@ -33,7 +33,6 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Queue;
import java.util.Set;
@ -109,10 +108,7 @@ public final class StaticComponent<C extends CommandSender> extends CommandCompo
@Nonnull
@Override
public List<String> suggestions(@Nonnull final CommandContext<C> commandContext, @Nonnull final String input) {
if (this.name.toLowerCase(Locale.ENGLISH).startsWith(input)) {
return Collections.singletonList(this.name);
}
return Collections.emptyList();
return Collections.singletonList(this.name);
}
}

View file

@ -34,7 +34,7 @@ import java.util.List;
* a command that doesn't exist
*/
@SuppressWarnings("unused")
public class NoSuchCommandException extends CommandParseException {
public final class NoSuchCommandException extends CommandParseException {
private final String suppliedCommand;
@ -52,6 +52,19 @@ public class NoSuchCommandException extends CommandParseException {
this.suppliedCommand = command;
}
@Override
public String getMessage() {
final StringBuilder builder = new StringBuilder();
for (final CommandComponent<?, ?> commandComponent : this.getCurrentChain()) {
if (commandComponent == null) {
continue;
}
builder.append(" ").append(commandComponent.getName());
}
return String.format("Unrecognized command input '%s' following chain%s", this.suppliedCommand, builder.toString());
}
/**
* Get the supplied command
*

View file

@ -74,7 +74,7 @@ public abstract class CommandExecutionCoordinator<C extends CommandSender, M ext
* @param input Command input
* @return Future that completes with the result
*/
public abstract CompletableFuture<CommandResult> coordinateExecution(@Nonnull CommandContext<C> commandContext,
public abstract CompletableFuture<CommandResult<C>> coordinateExecution(@Nonnull CommandContext<C> commandContext,
@Nonnull Queue<String> input);
/**
@ -102,13 +102,13 @@ public abstract class CommandExecutionCoordinator<C extends CommandSender, M ext
}
@Override
public CompletableFuture<CommandResult> coordinateExecution(@Nonnull final CommandContext<C> commandContext,
public CompletableFuture<CommandResult<C>> coordinateExecution(@Nonnull final CommandContext<C> commandContext,
@Nonnull final Queue<String> input) {
final CompletableFuture<CommandResult> completableFuture = new CompletableFuture<>();
final CompletableFuture<CommandResult<C>> completableFuture = new CompletableFuture<>();
try {
this.getCommandTree().parse(commandContext, input).ifPresent(
command -> command.getCommandExecutionHandler().execute(commandContext));
completableFuture.complete(new CommandResult());
completableFuture.complete(new CommandResult<>(commandContext));
} catch (final Exception e) {
completableFuture.completeExceptionally(e);
}

View file

@ -23,8 +23,36 @@
//
package com.intellectualsites.commands.execution;
import com.intellectualsites.commands.context.CommandContext;
import com.intellectualsites.commands.sender.CommandSender;
import javax.annotation.Nonnull;
/**
* The result of a command execution
*
* @param <C> Command sender type
*/
public class CommandResult {
public class CommandResult<C extends CommandSender> {
private final CommandContext<C> commandContext;
/**
* Construct a new command result instance
*
* @param context Command context
*/
public CommandResult(@Nonnull final CommandContext<C> context) {
this.commandContext = context;
}
/**
* Get the command context
*
* @return Command context
*/
@Nonnull public CommandContext<C> getCommandContext() {
return this.commandContext;
}
}

View file

@ -0,0 +1,40 @@
//
// MIT License
//
// Copyright (c) 2020 Alexander Söderberg
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
package com.intellectualsites.commands.execution;
import com.intellectualsites.commands.execution.preprocessor.CommandPreprocessingContext;
import com.intellectualsites.commands.sender.CommandSender;
import java.util.List;
import java.util.function.BiFunction;
/**
* Processor that formats command suggestions
*
* @param <C> Command sender type
*/
public interface CommandSuggestionProcessor<C extends CommandSender> extends
BiFunction<CommandPreprocessingContext<C>, List<String>, List<String>> {
}

View file

@ -0,0 +1,58 @@
//
// MIT License
//
// Copyright (c) 2020 Alexander Söderberg
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
package com.intellectualsites.commands.execution;
import com.intellectualsites.commands.execution.preprocessor.CommandPreprocessingContext;
import com.intellectualsites.commands.sender.CommandSender;
import javax.annotation.Nonnull;
import java.util.LinkedList;
import java.util.List;
/**
* Command suggestions processor that checks the input queue head and filters based on that
*
* @param <C> Command sender type
*/
public final class FilteringCommandSuggestionProcessor<C extends CommandSender> implements CommandSuggestionProcessor<C> {
@Nonnull
@Override
public List<String> apply(@Nonnull final CommandPreprocessingContext<C> context, @Nonnull final List<String> strings) {
final String input;
if (context.getInputQueue().isEmpty()) {
input = "";
} else {
input = context.getInputQueue().peek();
}
final List<String> suggestions = new LinkedList<>();
for (final String suggestion : strings) {
if (suggestion.startsWith(input)) {
suggestions.add(suggestion);
}
}
return suggestions;
}
}

View file

@ -0,0 +1,48 @@
//
// MIT License
//
// Copyright (c) 2020 Alexander Söderberg
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
package com.intellectualsites.commands.execution.preprocessor;
import com.intellectualsites.commands.sender.CommandSender;
import javax.annotation.Nonnull;
/**
* {@link CommandPreprocessor} that does nothing besides indicating that the context
* has been properly processed
*
* @param <C> Command sender type
*/
public final class AcceptingCommandPreprocessor<C extends CommandSender> implements CommandPreprocessor<C> {
/**
* Key used to access the context meta that indicates that the context has been fully processed
*/
public static final String PROCESSED_INDICATOR_KEY = "__COMMAND_PRE_PROCESSED__";
@Override
public void accept(@Nonnull final CommandPreprocessingContext<C> context) {
context.getCommandContext().store(PROCESSED_INDICATOR_KEY, "true");
}
}

View file

@ -0,0 +1,94 @@
//
// MIT License
//
// Copyright (c) 2020 Alexander Söderberg
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
package com.intellectualsites.commands.execution.preprocessor;
import com.intellectualsites.commands.context.CommandContext;
import com.intellectualsites.commands.sender.CommandSender;
import javax.annotation.Nonnull;
import java.util.LinkedList;
import java.util.Objects;
/**
* Context for {@link CommandPreprocessor command preprocessors}
*
* @param <C> Command sender type
*/
public final class CommandPreprocessingContext<C extends CommandSender> {
private final CommandContext<C> commandContext;
private final LinkedList<String> inputQueue;
/**
* Construct a new command preprocessing context
*
* @param commandContext Command context
* @param inputQueue Command input as supplied by sender
*/
public CommandPreprocessingContext(@Nonnull final CommandContext<C> commandContext,
@Nonnull final LinkedList<String> inputQueue) {
this.commandContext = commandContext;
this.inputQueue = inputQueue;
}
/**
* Get the command context
*
* @return Command context
*/
@Nonnull
public CommandContext<C> getCommandContext() {
return this.commandContext;
}
/**
* Get the original input queue. All changes will persist and will be
* used during parsing
*
* @return Input queue
*/
@Nonnull
public LinkedList<String> getInputQueue() {
return this.inputQueue;
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final CommandPreprocessingContext<?> that = (CommandPreprocessingContext<?>) o;
return Objects.equals(getCommandContext(), that.getCommandContext())
&& Objects.equals(getInputQueue(), that.getInputQueue());
}
@Override
public int hashCode() {
return Objects.hash(getCommandContext(), getInputQueue());
}
}

View file

@ -0,0 +1,40 @@
//
// MIT License
//
// Copyright (c) 2020 Alexander Söderberg
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
package com.intellectualsites.commands.execution.preprocessor;
import com.intellectualsites.commands.sender.CommandSender;
import com.intellectualsites.services.types.ConsumerService;
/**
* Command preprocessor that gets to act on command input
* before it's sent to the command parser.
* <p>
* Command preprocessors may filter out invalid commands by using
* {@link ConsumerService#interrupt()}
*
* @param <C> Command sender type
* {@inheritDoc}
*/
public interface CommandPreprocessor<C extends CommandSender> extends ConsumerService<CommandPreprocessingContext<C>> {
}

View file

@ -0,0 +1,28 @@
//
// MIT License
//
// Copyright (c) 2020 Alexander Söderberg
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
/**
* Command preprocessor system
*/
package com.intellectualsites.commands.execution.preprocessor;

View file

@ -0,0 +1,88 @@
//
// MIT License
//
// Copyright (c) 2020 Alexander Söderberg
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
package com.intellectualsites.commands;
import com.intellectualsites.commands.components.standard.EnumComponent;
import com.intellectualsites.commands.execution.preprocessor.CommandPreprocessingContext;
import com.intellectualsites.commands.execution.preprocessor.CommandPreprocessor;
import com.intellectualsites.commands.meta.SimpleCommandMeta;
import com.intellectualsites.commands.sender.CommandSender;
import com.intellectualsites.services.types.ConsumerService;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import javax.annotation.Nonnull;
public class CommandPreProcessorTest {
private static CommandManager<CommandSender, SimpleCommandMeta> manager;
@BeforeAll
static void newTree() {
manager = new TestCommandManager();
manager.registerCommand(manager.commandBuilder("test", SimpleCommandMeta.empty())
.withComponent(EnumComponent.required(SampleEnum.class, "enum"))
.withHandler(
commandContext -> System.out.printf("enum = %s | integer = %d\n",
commandContext.<SampleEnum>get(
"enum").orElse(
SampleEnum.VALUE1),
commandContext.<Integer>get(
"int").orElseThrow(
() -> new NullPointerException(
"int"))))
.build());
manager.registerCommandPreProcessor(new SamplePreprocessor());
}
@Test
void testPreprocessing() {
Assertions.assertEquals(10, manager.executeCommand(new TestCommandSender(), "10 test value1")
.join().getCommandContext().<Integer>get("int").orElse(0));
manager.executeCommand(new TestCommandSender(), "aa test value1").join();
}
enum SampleEnum {
VALUE1
}
static final class SamplePreprocessor implements CommandPreprocessor<CommandSender> {
@Override
public void accept(@Nonnull final CommandPreprocessingContext<CommandSender> context) {
try {
final int num = Integer.parseInt(context.getInputQueue().removeFirst());
context.getCommandContext().store("int", num);
} catch (final Exception ignored) {
/* Will prevent execution */
ConsumerService.interrupt();
}
}
}
}