Skip to content
This repository was archived by the owner on Feb 19, 2019. It is now read-only.

Commit 5ea8b0d

Browse files
committed
Create separate class for command input parsing
1 parent 7a39f2c commit 5ea8b0d

19 files changed

+167
-75
lines changed

src/example/java/me/zero/example/command/ExampleCommandManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import clientapi.ClientAPI;
2020
import clientapi.command.Command;
21-
import clientapi.command.executor.argument.*;
21+
import clientapi.command.executor.parser.impl.*;
2222
import clientapi.command.handler.CommandHandler;
2323
import clientapi.command.handler.listener.ChatCommandListener;
2424
import clientapi.manage.Manager;

src/main/java/clientapi/command/ChildCommand.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@
1616

1717
package clientapi.command;
1818

19+
import clientapi.command.executor.parser.CommandArgument;
1920
import clientapi.command.exception.*;
2021
import clientapi.command.executor.ExecutionContext;
21-
import clientapi.command.executor.argument.ArgumentParser;
22+
import clientapi.command.executor.parser.ArgumentParser;
2223

2324
import java.lang.reflect.InvocationTargetException;
2425
import java.lang.reflect.Method;

src/main/java/clientapi/command/Command.java

Lines changed: 7 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import clientapi.command.exception.CommandInitException;
2121
import clientapi.command.exception.UnknownSubCommandException;
2222
import clientapi.command.executor.ExecutionContext;
23+
import clientapi.command.executor.parser.CommandInputParser;
2324
import clientapi.util.ClientAPIUtils;
2425

2526
import java.lang.reflect.Method;
@@ -75,12 +76,10 @@ private void setup(String[] headers, String description) {
7576
int optionals = 0;
7677
for (int i = 0; i < parameters; i++) {
7778
if (method.getParameterTypes()[i].isAssignableFrom(Optional.class)) {
78-
if (i != parameters - 1) {
79+
if (i != parameters - 1)
7980
throw new RuntimeException(new CommandInitException(this, "Optionals must be defined as the last parameter"));
80-
}
81-
if (++optionals > 1) {
81+
if (++optionals > 1)
8282
throw new RuntimeException(new CommandInitException(this, "More than one optional parameter is not supported"));
83-
}
8483
}
8584
}
8685

@@ -94,18 +93,18 @@ private void setup(String[] headers, String description) {
9493

9594
@Override
9695
public final void execute(ExecutionContext context, String[] arguments) throws CommandException {
97-
ChildCommand sub = findChild(arguments);
98-
if (sub == null)
96+
Optional<ChildCommand> sub = CommandInputParser.INSTANCE.findChild(this, arguments);
97+
if (!sub.isPresent())
9998
throw new UnknownSubCommandException(this, arguments);
10099

101100
// If the child was found by it's header, then remove the first argument.
102-
if (sub.getHeaders().length > 0 && arguments.length > 0) {
101+
if (sub.get().getHeaders().length > 0 && arguments.length > 0) {
103102
String[] newArgs = new String[arguments.length - 1];
104103
System.arraycopy(arguments, 1, newArgs, 0, arguments.length - 1);
105104
arguments = newArgs;
106105
}
107106

108-
sub.execute(context, arguments);
107+
sub.get().execute(context, arguments);
109108
}
110109

111110
@Override
@@ -124,28 +123,4 @@ public final String getDescription() {
124123
public final List<ChildCommand> getChildren() {
125124
return this.children;
126125
}
127-
128-
/**
129-
* Finds a child command from the specified arguments
130-
*
131-
* @param arguments The arguments
132-
* @return The child command, {@code null} if not found
133-
*/
134-
private ChildCommand findChild(String[] arguments) {
135-
String header = arguments.length == 0 ? null : arguments[0];
136-
137-
// Find the command by the header defined by the first argument
138-
ChildCommand child = this.children.stream().filter(c -> (header == null && c.getHeaders().length == 0) || ClientAPIUtils.containsIgnoreCase(c.getHeaders(), header)).findFirst().orElse(null);
139-
if (child != null) {
140-
return child;
141-
}
142-
143-
// Find the command by the length of the arguments
144-
child = this.children.stream().filter(c -> c.getHeaders().length == 0 && arguments.length == c.getArguments().size()).findFirst().orElse(null);
145-
if (child != null) {
146-
return child;
147-
}
148-
149-
return null;
150-
}
151126
}

src/main/java/clientapi/command/exception/ParserException.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import clientapi.command.ChildCommand;
2020
import clientapi.command.Command;
21-
import clientapi.command.executor.argument.ArgumentParser;
21+
import clientapi.command.executor.parser.ArgumentParser;
2222

2323
import java.lang.reflect.Type;
2424

src/main/java/clientapi/command/executor/argument/ArgumentParser.java renamed to src/main/java/clientapi/command/executor/parser/ArgumentParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package clientapi.command.executor.argument;
17+
package clientapi.command.executor.parser;
1818

1919
import clientapi.command.executor.ExecutionContext;
2020

src/main/java/clientapi/command/CommandArgument.java renamed to src/main/java/clientapi/command/executor/parser/CommandArgument.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package clientapi.command;
17+
package clientapi.command.executor.parser;
1818

1919
import clientapi.util.interfaces.Nameable;
2020

@@ -31,7 +31,7 @@ public final class CommandArgument implements Nameable {
3131
private final String name;
3232
private final Type type;
3333

34-
CommandArgument(String name, Type type) {
34+
public CommandArgument(String name, Type type) {
3535
this.name = name;
3636
this.type = type;
3737
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package clientapi.command.executor.parser;
2+
3+
import clientapi.command.ChildCommand;
4+
import clientapi.command.Command;
5+
import clientapi.util.ClientAPIUtils;
6+
7+
import java.util.ArrayList;
8+
import java.util.List;
9+
import java.util.Optional;
10+
import java.util.regex.Matcher;
11+
import java.util.regex.Pattern;
12+
13+
/**
14+
* Used to parse raw text into the individual arguments that will be used for execution
15+
*
16+
* @author Brady
17+
* @since 4/14/2018 6:10 PM
18+
*/
19+
public enum CommandInputParser {
20+
21+
INSTANCE;
22+
23+
private static final Pattern REGEX = Pattern.compile("\"([^\"]+)\"|'([^']+)'|([^\\s]+)");
24+
25+
/**
26+
* Parses raw text command execution input
27+
*
28+
* @param raw The raw input
29+
* @return An optional containing the parsed input if the input is valid
30+
*/
31+
public final Optional<ParsedCommandInput> parseCommandInput(String raw) {
32+
// Create a matcher to parse the message
33+
Matcher matcher = REGEX.matcher(raw);
34+
35+
// Collect all of the matches from the raw data
36+
List<String> matches = new ArrayList<>();
37+
while (matcher.find())
38+
matches.add(matcher.group());
39+
40+
// If there were no matches, then the input was invalid
41+
if (matches.size() == 0)
42+
return Optional.empty();
43+
44+
String[] args = new String[matches.size() - 1];
45+
for (int i = 1; i < matches.size(); i++)
46+
args[i - 1] = matches.get(i).replace("\"", "").replace("\'", "");
47+
48+
return Optional.of(new ParsedCommandInput(matches.get(0), args));
49+
}
50+
51+
/**
52+
* Finds a child command that matches
53+
*
54+
* @param command The command
55+
* @param arguments The arguments
56+
* @return The child command if one that matches the arguments is found
57+
*/
58+
public final Optional<ChildCommand> findChild(Command command, String[] arguments) {
59+
String header = arguments.length == 0 ? null : arguments[0];
60+
61+
// Find the command by the header defined by the first argument
62+
ChildCommand child = command.getChildren().stream()
63+
.filter(c -> header == null ? c.getHeaders().length == 0 : ClientAPIUtils.containsIgnoreCase(c.getHeaders(), header))
64+
.findFirst().orElse(null);
65+
66+
if (child != null)
67+
return Optional.of(child);
68+
69+
// Find the command by the length of the arguments
70+
return command.getChildren().stream()
71+
.filter(c -> c.getHeaders().length == 0 && arguments.length == c.getArguments().size())
72+
.findFirst();
73+
}
74+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package clientapi.command.executor.parser;
2+
3+
import java.util.List;
4+
5+
/**
6+
* Used to hold parsed input data. Contains the name of the
7+
* targetted command and the arguments for execution as raw text.
8+
*
9+
* @author Brady
10+
* @since 4/14/2018 6:10 PM
11+
*/
12+
public final class ParsedCommandInput {
13+
14+
/**
15+
* The specified command header
16+
*/
17+
private final String command;
18+
19+
/**
20+
* The execution arguments expressed as raw text
21+
*/
22+
private final String[] arguments;
23+
24+
ParsedCommandInput(String command, String[] arguments) {
25+
this.command = command;
26+
this.arguments = arguments;
27+
}
28+
29+
/**
30+
* @return The specified command header
31+
*/
32+
public final String getCommand() {
33+
return this.command;
34+
}
35+
36+
/**
37+
* @return The execution arguments expressed as raw text
38+
*/
39+
public final String[] getArguments() {
40+
return this.arguments;
41+
}
42+
}

src/main/java/clientapi/command/executor/argument/BlockParser.java renamed to src/main/java/clientapi/command/executor/parser/impl/BlockParser.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@
1414
* limitations under the License.
1515
*/
1616

17-
package clientapi.command.executor.argument;
17+
package clientapi.command.executor.parser.impl;
1818

1919
import clientapi.command.executor.ExecutionContext;
20+
import clientapi.command.executor.parser.ArgumentParser;
2021
import net.minecraft.block.Block;
2122

2223
import java.lang.reflect.Type;

src/main/java/clientapi/command/executor/argument/BooleanParser.java renamed to src/main/java/clientapi/command/executor/parser/impl/BooleanParser.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@
1414
* limitations under the License.
1515
*/
1616

17-
package clientapi.command.executor.argument;
17+
package clientapi.command.executor.parser.impl;
1818

1919
import clientapi.command.executor.ExecutionContext;
20+
import clientapi.command.executor.parser.ArgumentParser;
2021

2122
import java.lang.reflect.Type;
2223

0 commit comments

Comments
 (0)