Skip to content

Commit 22feb6f

Browse files
committed
feat(core): extract command execution from CommandManager
1 parent 1a34c48 commit 22feb6f

46 files changed

Lines changed: 347 additions & 233 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

cloud-annotations/src/test/java/cloud/commandframework/annotations/AnnotationParserTest.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -97,16 +97,16 @@ void setup() {
9797
@Test
9898
void testMethodConstruction() {
9999
Assertions.assertFalse(commands.isEmpty());
100-
manager.executeCommand(new TestCommandSender(), "test literal 10").join();
101-
manager.executeCommand(new TestCommandSender(), "t literal 10 o").join();
102-
manager.executeCommand(new TestCommandSender(), "proxycommand 10").join();
100+
manager.commandExecutor().executeCommand(new TestCommandSender(), "test literal 10").join();
101+
manager.commandExecutor().executeCommand(new TestCommandSender(), "t literal 10 o").join();
102+
manager.commandExecutor().executeCommand(new TestCommandSender(), "proxycommand 10").join();
103103
Assertions.assertThrows(CompletionException.class, () ->
104-
manager.executeCommand(new TestCommandSender(), "test 101").join());
105-
manager.executeCommand(new TestCommandSender(), "flagcommand -p").join();
106-
manager.executeCommand(new TestCommandSender(), "flagcommand --print --word peanut").join();
107-
manager.executeCommand(new TestCommandSender(), "parserflagcommand -s \"Hello World\"").join();
108-
manager.executeCommand(new TestCommandSender(), "parserflagcommand -s \"Hello World\" -o This is a test").join();
109-
manager.executeCommand(new TestCommandSender(), "class method").join();
104+
manager.commandExecutor().executeCommand(new TestCommandSender(), "test 101").join());
105+
manager.commandExecutor().executeCommand(new TestCommandSender(), "flagcommand -p").join();
106+
manager.commandExecutor().executeCommand(new TestCommandSender(), "flagcommand --print --word peanut").join();
107+
manager.commandExecutor().executeCommand(new TestCommandSender(), "parserflagcommand -s \"Hello World\"").join();
108+
manager.commandExecutor().executeCommand(new TestCommandSender(), "parserflagcommand -s \"Hello World\" -o This is a test").join();
109+
manager.commandExecutor().executeCommand(new TestCommandSender(), "class method").join();
110110
}
111111

112112
@Test
@@ -152,7 +152,7 @@ void testAnnotationResolver() throws Exception {
152152

153153
@Test
154154
void testParameterInjection() {
155-
manager.executeCommand(new TestCommandSender(), "injected 10").join();
155+
manager.commandExecutor().executeCommand(new TestCommandSender(), "injected 10").join();
156156
}
157157

158158
@Test
@@ -199,7 +199,7 @@ void testMultiAliasedCommands() {
199199

200200
@Test
201201
void testInjectedCommand() {
202-
manager.executeCommand(new TestCommandSender(), "injected 10").join();
202+
manager.commandExecutor().executeCommand(new TestCommandSender(), "injected 10").join();
203203
}
204204

205205
@Suggestions("cows")

cloud-annotations/src/test/java/cloud/commandframework/annotations/exception/MethodExceptionHandlerTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import cloud.commandframework.annotations.TestCommandSender;
3030
import cloud.commandframework.annotations.injection.ParameterInjector;
3131
import cloud.commandframework.context.CommandContext;
32+
import cloud.commandframework.context.StandardCommandContextFactory;
3233
import cloud.commandframework.exceptions.NoSuchCommandException;
3334
import cloud.commandframework.exceptions.handling.ExceptionContext;
3435
import cloud.commandframework.exceptions.handling.ExceptionController;
@@ -50,7 +51,7 @@ void setup() {
5051
final CommandManager<TestCommandSender> commandManager = new TestCommandManager();
5152
this.exceptionController = commandManager.exceptionController();
5253
this.annotationParser = new AnnotationParser<>(commandManager, TestCommandSender.class);
53-
this.context = commandManager.commandContextFactory().create(false, new TestCommandSender());
54+
this.context = new StandardCommandContextFactory<>(commandManager).create(false, new TestCommandSender());
5455
commandManager.parameterInjectorRegistry().registerInjector(Integer.class, ParameterInjector.constantInjector(5));
5556
}
5657

cloud-annotations/src/test/java/cloud/commandframework/annotations/feature/ArgumentDrivenCommandsTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ void testCommandConstruction() throws Exception {
7575
this.annotationParser.parse(new ArgumentDrivenCommandClass());
7676

7777
// Act
78-
this.commandManager.executeCommand(new TestCommandSender(), "test 3 literal").get();
78+
this.commandManager.commandExecutor().executeCommand(new TestCommandSender(), "test 3 literal").get();
7979
}
8080

8181
private static class TestArgumentExtractor implements ArgumentExtractor {

cloud-annotations/src/test/java/cloud/commandframework/annotations/feature/ArgumentWithoutAnnotationTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ void test() {
6464
this.annotationParser.parse(new TestClass());
6565

6666
// Assert
67-
final CommandResult<?> result = this.commandManager.executeCommand(new TestCommandSender(),
67+
final CommandResult<?> result = this.commandManager.commandExecutor().executeCommand(new TestCommandSender(),
6868
"command abc 123 true").join();
6969
final CommandContext<?> context = result.commandContext();
7070
assertThat(context.<String>get("required")).isEqualTo("abc");

cloud-annotations/src/test/java/cloud/commandframework/annotations/feature/RepeatableCommandMethodTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ void test() {
5959
this.annotationParser.parse(new TestClass());
6060

6161
// Act
62-
final CommandResult<?> result1 = this.commandManager.executeCommand(new TestCommandSender(), "test").join();
63-
final CommandResult<?> result2 = this.commandManager.executeCommand(new TestCommandSender(), "test foo").join();
62+
final CommandResult<?> result1 = this.commandManager.commandExecutor().executeCommand(new TestCommandSender(), "test").join();
63+
final CommandResult<?> result2 = this.commandManager.commandExecutor().executeCommand(new TestCommandSender(), "test foo").join();
6464

6565
// Assert
6666
assertThat(result1.commandContext().<Boolean>get("handled")).isTrue();

cloud-annotations/src/test/java/cloud/commandframework/annotations/feature/RepeatableFlagTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ void setup() {
5353
@Test
5454
void testRepeatableFlagParsing() {
5555
// Act
56-
final CommandResult<TestCommandSender> result = this.commandManager.executeCommand(
56+
final CommandResult<TestCommandSender> result = this.commandManager.commandExecutor().executeCommand(
5757
new TestCommandSender(),
5858
"test --flag one --flag two --flag three"
5959
).join();

cloud-annotations/src/test/java/cloud/commandframework/annotations/feature/RequiredSenderDeductionTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ void testCorrectSender() {
6868
final SuperSender<?> sender = new StringSender();
6969

7070
// Act
71-
this.commandManager.executeCommand(sender, "teststring").join();
71+
this.commandManager.commandExecutor().executeCommand(sender, "teststring").join();
7272
}
7373

7474
@Test
@@ -79,7 +79,7 @@ void testIncorrectSender() {
7979
// Act
8080
assertThrows(
8181
CompletionException.class,
82-
() -> this.commandManager.executeCommand(sender, "teststring").join()
82+
() -> this.commandManager.commandExecutor().executeCommand(sender, "teststring").join()
8383
);
8484
}
8585

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
//
2+
// MIT License
3+
//
4+
// Copyright (c) 2022 Alexander Söderberg & Contributors
5+
//
6+
// Permission is hereby granted, free of charge, to any person obtaining a copy
7+
// of this software and associated documentation files (the "Software"), to deal
8+
// in the Software without restriction, including without limitation the rights
9+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
// copies of the Software, and to permit persons to whom the Software is
11+
// furnished to do so, subject to the following conditions:
12+
//
13+
// The above copyright notice and this permission notice shall be included in all
14+
// copies or substantial portions of the Software.
15+
//
16+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
// SOFTWARE.
23+
//
24+
package cloud.commandframework;
25+
26+
import cloud.commandframework.context.CommandContext;
27+
import cloud.commandframework.execution.CommandExecutionCoordinator;
28+
import cloud.commandframework.execution.CommandResult;
29+
import cloud.commandframework.execution.postprocessor.CommandPostprocessor;
30+
import cloud.commandframework.execution.preprocessor.CommandPreprocessor;
31+
import java.util.concurrent.CompletableFuture;
32+
import java.util.function.Consumer;
33+
import org.apiguardian.api.API;
34+
import org.checkerframework.checker.nullness.qual.NonNull;
35+
36+
@API(status = API.Status.STABLE, since = "2.0.0")
37+
public interface CommandExecutor<C> {
38+
39+
/**
40+
* Executes a command and get a future that completes with the result. The command may be executed immediately
41+
* or at some point in the future, depending on the {@link CommandExecutionCoordinator} used in the command manager.
42+
*
43+
* <p>The command may also be filtered out by preprocessors (see {@link CommandPreprocessor}) before they are parsed,
44+
* or by the {@link CommandComponent} command components during parsing. The execution may also be filtered out
45+
* after parsing by a {@link CommandPostprocessor}. In the case that a command was filtered out at any of the
46+
* execution stages, the future will complete with {@code null}.</p>
47+
*
48+
* <p>The future may also complete exceptionally.
49+
* These exceptions will be handled using exception handlers registered in the
50+
* {@link cloud.commandframework.exceptions.handling.ExceptionController}.
51+
* The exceptions will be forwarded to the future, if the exception was transformed during the exception handling, then the
52+
* new exception will be present in the completed future.</p>
53+
*
54+
* @param commandSender Sender of the command
55+
* @param input Input provided by the sender. Prefixes should be removed before the method is being called, and
56+
* the input here will be passed directly to the command parsing pipeline, after having been tokenized.
57+
* @return future that completes with the command result, or {@code null} if the execution was cancelled at any of the
58+
* processing stages.
59+
*/
60+
default @NonNull CompletableFuture<CommandResult<C>> executeCommand(
61+
final @NonNull C commandSender,
62+
final @NonNull String input
63+
) {
64+
return this.executeCommand(commandSender, input, context -> {});
65+
}
66+
67+
/**
68+
* Executes a command and get a future that completes with the result. The command may be executed immediately
69+
* or at some point in the future, depending on the {@link CommandExecutionCoordinator} used in the command manager.
70+
*
71+
* <p>The command may also be filtered out by preprocessors (see {@link CommandPreprocessor}) before they are parsed,
72+
* or by the {@link CommandComponent} command components during parsing. The execution may also be filtered out
73+
* after parsing by a {@link CommandPostprocessor}. In the case that a command was filtered out at any of the
74+
* execution stages, the future will complete with {@code null}.</p>
75+
*
76+
* <p>The future may also complete exceptionally.
77+
* These exceptions will be handled using exception handlers registered in the
78+
* {@link cloud.commandframework.exceptions.handling.ExceptionController}.
79+
* The exceptions will be forwarded to the future, if the exception was transformed during the exception handling, then the
80+
* new exception will be present in the completed future.</p>
81+
*
82+
* @param commandSender the sender of the command
83+
* @param input the input provided by the sender. Prefixes should be removed before the method is being called, and
84+
* the input here will be passed directly to the command parsing pipeline, after having been tokenized.
85+
* @param contextConsumer consumer that accepts the context before the command is executed
86+
* @return future that completes with the command result, or {@code null} if the execution was cancelled at any of the
87+
* processing stages.
88+
*/
89+
@NonNull CompletableFuture<CommandResult<C>> executeCommand(
90+
@NonNull C commandSender,
91+
@NonNull String input,
92+
@NonNull Consumer<CommandContext<C>> contextConsumer
93+
);
94+
95+
/**
96+
* Returns the command execution coordinator.
97+
*
98+
* @return command execution coordinator
99+
*/
100+
@NonNull CommandExecutionCoordinator<C> commandExecutionCoordinator();
101+
}

0 commit comments

Comments
 (0)