Renamed project to 'Brigadier'

This commit is contained in:
Nathan Adams
2014-10-02 13:00:29 +02:00
parent 8c5338a6bd
commit ef4199e824
42 changed files with 134 additions and 134 deletions
@@ -0,0 +1,7 @@
package com.mojang.brigadier;
import com.mojang.brigadier.context.CommandContext;
public interface Command {
void run(CommandContext context);
}
@@ -0,0 +1,51 @@
package com.mojang.brigadier;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.context.CommandContextBuilder;
import com.mojang.brigadier.exceptions.CommandException;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.RootCommandNode;
public class CommandDispatcher<T> {
public static final SimpleCommandExceptionType ERROR_UNKNOWN_COMMAND = new SimpleCommandExceptionType("unknown_command", "Unknown command");
public static final String ARGUMENT_SEPARATOR = " ";
private final RootCommandNode root = new RootCommandNode();
public void register(LiteralArgumentBuilder command) {
root.addChild(command.build());
}
public void execute(String command, T source) throws CommandException {
CommandContext<T> context = parseNodes(root, command, new CommandContextBuilder<T>(source));
context.getCommand().run(context);
}
protected CommandContext<T> parseNodes(CommandNode node, String command, CommandContextBuilder<T> contextBuilder) throws CommandException {
CommandException exception = null;
for (CommandNode child : node.getChildren()) {
try {
CommandContextBuilder<T> context = contextBuilder.copy();
String remaining = child.parse(command, context);
if (child.getCommand() != null) {
context.withCommand(child.getCommand());
}
return parseNodes(child, remaining, context);
} catch (CommandException ex) {
exception = ex;
}
}
if (exception != null) {
throw exception;
}
if (command.length() > 0) {
throw ERROR_UNKNOWN_COMMAND.create();
}
return contextBuilder.build();
}
}
@@ -0,0 +1,8 @@
package com.mojang.brigadier.arguments;
import com.mojang.brigadier.context.ParsedArgument;
import com.mojang.brigadier.exceptions.CommandException;
public interface CommandArgumentType<T> {
ParsedArgument<T> parse(String command) throws CommandException;
}
@@ -0,0 +1,85 @@
package com.mojang.brigadier.arguments;
import com.google.common.base.Splitter;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.context.ParsedArgument;
import com.mojang.brigadier.exceptions.CommandException;
import com.mojang.brigadier.exceptions.ParameterizedCommandExceptionType;
public class IntegerArgumentType implements CommandArgumentType<Integer> {
public static final ParameterizedCommandExceptionType ERROR_NOT_A_NUMBER = new ParameterizedCommandExceptionType("argument-integer-invalid", "Expected an integer, found '${found}'", "found");
public static final ParameterizedCommandExceptionType ERROR_TOO_SMALL = new ParameterizedCommandExceptionType("argument-integer-low", "Integer must not be less than ${minimum}, found ${found}", "found", "minimum");
public static final ParameterizedCommandExceptionType ERROR_TOO_BIG = new ParameterizedCommandExceptionType("argument-integer-big", "Integer must not be more than ${maximum}, found ${found}", "found", "maximum");
private static final Splitter SPLITTER = Splitter.on(CommandDispatcher.ARGUMENT_SEPARATOR).limit(2);
private final int minimum;
private final int maximum;
protected IntegerArgumentType(int minimum, int maximum) {
this.minimum = minimum;
this.maximum = maximum;
}
public static IntegerArgumentType integer() {
return integer(Integer.MIN_VALUE);
}
public static IntegerArgumentType integer(int min) {
return integer(min, Integer.MAX_VALUE);
}
public static IntegerArgumentType integer(int min, int max) {
return new IntegerArgumentType(min, max);
}
public static int getInteger(CommandContext<?> context, String name) {
return context.getArgument(name, int.class).getResult();
}
@Override
public ParsedArgument<Integer> parse(String command) throws CommandException {
String raw = SPLITTER.split(command).iterator().next();
try {
int value = Integer.parseInt(raw);
if (value < minimum) {
throw ERROR_TOO_SMALL.create(value, minimum);
}
if (value > maximum) {
throw ERROR_TOO_BIG.create(value, maximum);
}
return new ParsedArgument<Integer>(raw, value);
} catch (NumberFormatException ignored) {
throw ERROR_NOT_A_NUMBER.create(raw);
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof IntegerArgumentType)) return false;
IntegerArgumentType that = (IntegerArgumentType) o;
return maximum == that.maximum && minimum == that.minimum;
}
@Override
public int hashCode() {
return 31 * minimum + maximum;
}
@Override
public String toString() {
if (minimum == Integer.MIN_VALUE && maximum == Integer.MAX_VALUE) {
return "integer()";
} else if (maximum == Integer.MAX_VALUE) {
return "integer(" + minimum + ")";
} else {
return "integer(" + minimum + ", " + maximum + ")";
}
}
}
@@ -0,0 +1,4 @@
@ParametersAreNonnullByDefault
package com.mojang.brigadier.arguments;
import javax.annotation.ParametersAreNonnullByDefault;
@@ -0,0 +1,34 @@
package com.mojang.brigadier.builder;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.RootCommandNode;
import java.util.Collection;
public abstract class ArgumentBuilder<T extends ArgumentBuilder<?>> {
private final RootCommandNode arguments = new RootCommandNode();
private Command command;
protected abstract T getThis();
public T then(ArgumentBuilder argument) {
arguments.addChild(argument.build());
return getThis();
}
public Collection<CommandNode> getArguments() {
return arguments.getChildren();
}
public T executes(Command command) {
this.command = command;
return getThis();
}
public Command getCommand() {
return command;
}
public abstract CommandNode build();
}
@@ -0,0 +1,36 @@
package com.mojang.brigadier.builder;
import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.LiteralCommandNode;
public class LiteralArgumentBuilder extends ArgumentBuilder<LiteralArgumentBuilder> {
private final String literal;
protected LiteralArgumentBuilder(String literal) {
this.literal = literal;
}
public static LiteralArgumentBuilder literal(String name) {
return new LiteralArgumentBuilder(name);
}
@Override
protected LiteralArgumentBuilder getThis() {
return this;
}
public String getLiteral() {
return literal;
}
@Override
public LiteralCommandNode build() {
LiteralCommandNode result = new LiteralCommandNode(getLiteral(), getCommand());
for (CommandNode argument : getArguments()) {
result.addChild(argument);
}
return result;
}
}
@@ -0,0 +1,42 @@
package com.mojang.brigadier.builder;
import com.mojang.brigadier.arguments.CommandArgumentType;
import com.mojang.brigadier.tree.ArgumentCommandNode;
import com.mojang.brigadier.tree.CommandNode;
public class RequiredArgumentBuilder<T> extends ArgumentBuilder<RequiredArgumentBuilder<T>> {
private final String name;
private final CommandArgumentType<T> type;
protected RequiredArgumentBuilder(String name, CommandArgumentType<T> type) {
this.name = name;
this.type = type;
}
public static <T> RequiredArgumentBuilder<T> argument(String name, CommandArgumentType<T> type) {
return new RequiredArgumentBuilder<T>(name, type);
}
@Override
protected RequiredArgumentBuilder<T> getThis() {
return this;
}
public CommandArgumentType<T> getType() {
return type;
}
public String getName() {
return name;
}
public ArgumentCommandNode<T> build() {
ArgumentCommandNode<T> result = new ArgumentCommandNode<T>(getName(), getType(), getCommand());
for (CommandNode argument : getArguments()) {
result.addChild(argument);
}
return result;
}
}
@@ -0,0 +1,4 @@
@ParametersAreNonnullByDefault
package com.mojang.brigadier.builder;
import javax.annotation.ParametersAreNonnullByDefault;
@@ -0,0 +1,63 @@
package com.mojang.brigadier.context;
import com.google.common.primitives.Primitives;
import com.mojang.brigadier.Command;
import java.util.Map;
public class CommandContext<T> {
private final T source;
private final Map<String, ParsedArgument<?>> arguments;
private final Command command;
public CommandContext(T source, Map<String, ParsedArgument<?>> arguments, Command command) {
this.source = source;
this.arguments = arguments;
this.command = command;
}
public Command getCommand() {
return command;
}
public T getSource() {
return source;
}
@SuppressWarnings("unchecked")
public <V> ParsedArgument<V> getArgument(String name, Class<V> clazz) {
ParsedArgument<?> argument = arguments.get(name);
if (argument == null) {
throw new IllegalArgumentException("No such argument '" + name + "' exists on this command");
}
if (Primitives.wrap(clazz).isAssignableFrom(argument.getResult().getClass())) {
return (ParsedArgument<V>) argument;
} else {
throw new IllegalArgumentException("Argument '" + name + "' is defined as " + argument.getResult().getClass().getSimpleName() + ", not " + clazz);
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CommandContext)) return false;
CommandContext that = (CommandContext) o;
if (!arguments.equals(that.arguments)) return false;
if (command != null ? !command.equals(that.command) : that.command != null) return false;
if (!source.equals(that.source)) return false;
return true;
}
@Override
public int hashCode() {
int result = source.hashCode();
result = 31 * result + arguments.hashCode();
result = 31 * result + (command != null ? command.hashCode() : 0);
return result;
}
}
@@ -0,0 +1,41 @@
package com.mojang.brigadier.context;
import com.google.common.collect.Maps;
import com.mojang.brigadier.Command;
import java.util.Map;
public class CommandContextBuilder<T> {
private final Map<String, ParsedArgument<?>> arguments = Maps.newHashMap();
private final T source;
private Command command;
public CommandContextBuilder(T source) {
this.source = source;
}
public CommandContextBuilder<T> withArgument(String name, ParsedArgument<?> argument) {
this.arguments.put(name, argument);
return this;
}
public Map<String, ParsedArgument<?>> getArguments() {
return arguments;
}
public CommandContextBuilder<T> withCommand(Command command) {
this.command = command;
return this;
}
public CommandContextBuilder<T> copy() {
CommandContextBuilder<T> copy = new CommandContextBuilder<T>(source);
copy.command = this.command;
copy.arguments.putAll(this.arguments);
return copy;
}
public CommandContext<T> build() {
return new CommandContext<T>(source, arguments, command);
}
}
@@ -0,0 +1,39 @@
package com.mojang.brigadier.context;
public class ParsedArgument<T> {
private final String raw;
private final T result;
public ParsedArgument(String raw, T result) {
this.raw = raw;
this.result = result;
}
public String getRaw() {
return raw;
}
public T getResult() {
return result;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ParsedArgument)) return false;
ParsedArgument that = (ParsedArgument) o;
if (!raw.equals(that.raw)) return false;
if (!result.equals(that.result)) return false;
return true;
}
@Override
public int hashCode() {
int result1 = raw.hashCode();
result1 = 31 * result1 + result.hashCode();
return result1;
}
}
@@ -0,0 +1,4 @@
@ParametersAreNonnullByDefault
package com.mojang.brigadier.context;
import javax.annotation.ParametersAreNonnullByDefault;
@@ -0,0 +1,26 @@
package com.mojang.brigadier.exceptions;
import java.util.Map;
public class CommandException extends Exception {
private final CommandExceptionType type;
private final Map<String, Object> data;
public CommandException(CommandExceptionType type, Map<String, Object> data) {
this.type = type;
this.data = data;
}
@Override
public String getMessage() {
return type.getErrorMessage(this);
}
public CommandExceptionType getType() {
return type;
}
public Map<String, Object> getData() {
return data;
}
}
@@ -0,0 +1,6 @@
package com.mojang.brigadier.exceptions;
public interface CommandExceptionType {
String getTypeName();
String getErrorMessage(CommandException exception);
}
@@ -0,0 +1,58 @@
package com.mojang.brigadier.exceptions;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMap;
import org.apache.commons.lang3.text.StrSubstitutor;
public class ParameterizedCommandExceptionType implements CommandExceptionType {
private static final Joiner JOINER = Joiner.on(", ");
private final String name;
private final String message;
private final String[] keys;
public ParameterizedCommandExceptionType(String name, String message, String... keys) {
this.name = name;
this.message = message;
this.keys = keys;
}
@Override
public String getTypeName() {
return name;
}
@Override
public String getErrorMessage(CommandException exception) {
return new StrSubstitutor(exception.getData()).replace(message);
}
public CommandException create(Object... values) {
if (values.length != keys.length) {
throw new IllegalArgumentException("Invalid values! (Expected: " + JOINER.join(keys) + ")");
}
ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
for (int i = 0; i < keys.length; i++) {
builder = builder.put(keys[i], values[i]);
}
return new CommandException(this, builder.build());
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CommandExceptionType)) return false;
CommandExceptionType that = (CommandExceptionType) o;
return getTypeName().equals(that.getTypeName());
}
@Override
public int hashCode() {
return getTypeName().hashCode();
}
}
@@ -0,0 +1,42 @@
package com.mojang.brigadier.exceptions;
import com.google.common.collect.ImmutableMap;
public class SimpleCommandExceptionType implements CommandExceptionType {
private final String name;
private final String message;
public SimpleCommandExceptionType(String name, String message) {
this.name = name;
this.message = message;
}
@Override
public String getTypeName() {
return name;
}
@Override
public String getErrorMessage(CommandException exception) {
return message;
}
public CommandException create() {
return new CommandException(this, ImmutableMap.<String, Object>of());
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CommandExceptionType)) return false;
CommandExceptionType that = (CommandExceptionType) o;
return getTypeName().equals(that.getTypeName());
}
@Override
public int hashCode() {
return getTypeName().hashCode();
}
}
@@ -0,0 +1,4 @@
@ParametersAreNonnullByDefault
package com.mojang.brigadier.exceptions;
import javax.annotation.ParametersAreNonnullByDefault;
@@ -0,0 +1,4 @@
@ParametersAreNonnullByDefault
package com.mojang.brigadier;
import javax.annotation.ParametersAreNonnullByDefault;
@@ -0,0 +1,65 @@
package com.mojang.brigadier.tree;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.arguments.CommandArgumentType;
import com.mojang.brigadier.context.CommandContextBuilder;
import com.mojang.brigadier.context.ParsedArgument;
import com.mojang.brigadier.exceptions.CommandException;
public class ArgumentCommandNode<T> extends CommandNode {
private final String name;
private final CommandArgumentType<T> type;
public ArgumentCommandNode(String name, CommandArgumentType<T> type, Command command) {
super(command);
this.name = name;
this.type = type;
}
public String getName() {
return name;
}
public CommandArgumentType<T> getType() {
return type;
}
@Override
protected Object getMergeKey() {
return name;
}
@Override
public String parse(String command, CommandContextBuilder<?> contextBuilder) throws CommandException {
ParsedArgument<T> parsed = type.parse(command);
int start = parsed.getRaw().length();
contextBuilder.withArgument(name, parsed);
if (command.length() > start) {
return command.substring(start + 1);
} else {
return "";
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ArgumentCommandNode)) return false;
ArgumentCommandNode that = (ArgumentCommandNode) o;
if (!name.equals(that.name)) return false;
if (!type.equals(that.type)) return false;
return super.equals(o);
}
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + type.hashCode();
result = 31 * super.hashCode();
return result;
}
}
@@ -0,0 +1,63 @@
package com.mojang.brigadier.tree;
import com.google.common.collect.Maps;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.context.CommandContextBuilder;
import com.mojang.brigadier.exceptions.CommandException;
import java.util.Collection;
import java.util.Map;
public abstract class CommandNode {
private final Map<Object, CommandNode> children = Maps.newLinkedHashMap();
private Command command;
protected CommandNode(Command command) {
this.command = command;
}
public Command getCommand() {
return command;
}
public Collection<CommandNode> getChildren() {
return children.values();
}
public void addChild(CommandNode node) {
CommandNode child = children.get(node.getMergeKey());
if (child != null) {
// We've found something to merge onto
if (node.getCommand() != null) {
child.command = node.getCommand();
}
for (CommandNode grandchild : node.getChildren()) {
child.addChild(grandchild);
}
} else {
children.put(node.getMergeKey(), node);
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CommandNode)) return false;
CommandNode that = (CommandNode) o;
if (!children.equals(that.children)) return false;
if (command != null ? !command.equals(that.command) : that.command != null) return false;
return true;
}
@Override
public int hashCode() {
return 31 * children.hashCode() + (command != null ? command.hashCode() : 0);
}
protected abstract Object getMergeKey();
public abstract String parse(String command, CommandContextBuilder<?> contextBuilder) throws CommandException;
}
@@ -0,0 +1,57 @@
package com.mojang.brigadier.tree;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.context.CommandContextBuilder;
import com.mojang.brigadier.exceptions.CommandException;
import com.mojang.brigadier.exceptions.ParameterizedCommandExceptionType;
public class LiteralCommandNode extends CommandNode {
public static final ParameterizedCommandExceptionType ERROR_INCORRECT_LITERAL = new ParameterizedCommandExceptionType("incorrect_literal", "Expected literal ${expected}", "expected");
private final String literal;
public LiteralCommandNode(String literal, Command command) {
super(command);
this.literal = literal;
}
public String getLiteral() {
return literal;
}
@Override
protected Object getMergeKey() {
return literal;
}
@Override
public String parse(String command, CommandContextBuilder<?> contextBuilder) throws CommandException {
String expected = literal + (command.length() > literal.length() ? CommandDispatcher.ARGUMENT_SEPARATOR : "");
if (!command.startsWith(expected)) {
throw ERROR_INCORRECT_LITERAL.create(expected);
}
int start = expected.length();
return command.substring(start);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof LiteralCommandNode)) return false;
LiteralCommandNode that = (LiteralCommandNode) o;
if (!literal.equals(that.literal)) return false;
return super.equals(o);
}
@Override
public int hashCode() {
int result = literal.hashCode();
result = 31 * result + super.hashCode();
return result;
}
}
@@ -0,0 +1,27 @@
package com.mojang.brigadier.tree;
import com.mojang.brigadier.context.CommandContextBuilder;
import com.mojang.brigadier.exceptions.CommandException;
public class RootCommandNode extends CommandNode {
public RootCommandNode() {
super(null);
}
@Override
protected Object getMergeKey() {
throw new UnsupportedOperationException("Cannot add a RootCommandNode as a child to any other CommandNode");
}
@Override
public String parse(String command, CommandContextBuilder<?> contextBuilder) throws CommandException {
return command;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof RootCommandNode)) return false;
return super.equals(o);
}
}
@@ -0,0 +1,4 @@
@ParametersAreNonnullByDefault
package com.mojang.brigadier.tree;
import javax.annotation.ParametersAreNonnullByDefault;