Binding improvements

WIP towards deprecating parsers and unifying the command bindings
Allow registering dynamic bindings
- Supports nesting bindings
This commit is contained in:
Jesse Boyd 2019-04-01 21:35:55 +11:00
parent 6e6a3f9035
commit ff67f6343f
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
15 changed files with 487 additions and 163 deletions

View File

@ -1,13 +1,12 @@
package com.boydti.fawe.command;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.internal.command.WorldEditBinding;
import com.sk89q.worldedit.util.command.parametric.BindingHelper;
public class FaweBinding extends WorldEditBinding {
public class FaweBinding extends BindingHelper {
private final WorldEdit worldEdit;
public FaweBinding(WorldEdit worldEdit) {
super(worldEdit);
this.worldEdit = worldEdit;
}

View File

@ -42,7 +42,7 @@ import java.net.URI;
import java.net.URL;
import javax.annotation.Nullable;
public class FawePrimitiveBinding extends BindingHelper {
public class FawePrimitiveBinding {
@BindingMatch(type = {Long.class, long.class},
behavior = BindingBehavior.CONSUMES,
consumedCount = 1,

View File

@ -4,8 +4,6 @@ import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.util.command.parametric.ParameterData;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

View File

@ -35,4 +35,4 @@ public class CircleBrush implements Brush {
Vector3 random = affine.apply(normal);
return random.cross(normal).normalize();
}
}
}

View File

@ -98,7 +98,6 @@ public class FaweSchematicHandler extends SchematicHandler {
if (tag instanceof CompressedCompoundTag) {
CompressedCompoundTag cTag = (CompressedCompoundTag) tag;
if (cTag instanceof CompressedSchematicTag) {
System.out.println("Write directly");
Clipboard clipboard = (Clipboard) cTag.getSource();
try (OutputStream stream = new FileOutputStream(tmp); NBTOutputStream output = new NBTOutputStream(new BufferedOutputStream(new PGZIPOutputStream(stream)))) {
new SpongeSchematicWriter(output).write(clipboard);

View File

@ -19,7 +19,6 @@ public class CompressedSchematicTag extends CompressedCompoundTag<Clipboard> {
@Override
public DataInputStream adapt(Clipboard src) throws IOException {
System.out.println("Decompress");
FastByteArrayOutputStream blocksOut = new FastByteArrayOutputStream();
try (LZ4BlockOutputStream lz4out = new LZ4BlockOutputStream(blocksOut)) {
NBTOutputStream nbtOut = new NBTOutputStream(lz4out);

View File

@ -64,7 +64,7 @@ import java.util.List;
/**
* Binds standard WorldEdit classes such as {@link Player} and {@link LocalSession}.
*/
public class WorldEditBinding extends BindingHelper {
public class WorldEditBinding {
private final WorldEdit worldEdit;

View File

@ -32,12 +32,14 @@ import java.lang.annotation.Annotation;
import javax.annotation.Nullable;
import static com.sk89q.worldedit.util.command.parametric.BindingHelper.validate;
/**
* Handles basic Java types such as {@link String}s, {@link Byte}s, etc.
*
* <p>Handles both the object and primitive types.</p>
*/
public final class PrimitiveBindings extends BindingHelper {
public final class PrimitiveBindings {
/**
* Gets a type from a {@link ArgumentStack}.
@ -206,89 +208,4 @@ public final class PrimitiveBindings extends BindingHelper {
}
return null;
}
/**
* Validate a number value using relevant modifiers.
*
* @param number the number
* @param modifiers the list of modifiers to scan
* @throws ParameterException on a validation error
*/
private static void validate(double number, Annotation[] modifiers)
throws ParameterException {
for (Annotation modifier : modifiers) {
if (modifier instanceof Range) {
Range range = (Range) modifier;
if (number < range.min()) {
throw new ParameterException(
String.format(
"A valid value is greater than or equal to %s " +
"(you entered %s)", range.min(), number));
} else if (number > range.max()) {
throw new ParameterException(
String.format(
"A valid value is less than or equal to %s " +
"(you entered %s)", range.max(), number));
}
}
}
}
/**
* Validate a number value using relevant modifiers.
*
* @param number the number
* @param modifiers the list of modifiers to scan
* @throws ParameterException on a validation error
*/
private static void validate(int number, Annotation[] modifiers)
throws ParameterException {
for (Annotation modifier : modifiers) {
if (modifier instanceof Range) {
Range range = (Range) modifier;
if (number < range.min()) {
throw new ParameterException(
String.format(
"A valid value is greater than or equal to %s " +
"(you entered %s)", range.min(), number));
} else if (number > range.max()) {
throw new ParameterException(
String.format(
"A valid value is less than or equal to %s " +
"(you entered %s)", range.max(), number));
}
}
}
}
/**
* Validate a string value using relevant modifiers.
*
* @param string the string
* @param modifiers the list of modifiers to scan
* @throws ParameterException on a validation error
*/
private static void validate(String string, Annotation[] modifiers)
throws ParameterException {
if (string == null) {
return;
}
for (Annotation modifier : modifiers) {
if (modifier instanceof Validate) {
Validate validate = (Validate) modifier;
if (!validate.regex().isEmpty()) {
if (!string.matches(validate.regex())) {
throw new ParameterException(
String.format(
"The given text doesn't match the right " +
"format (technically speaking, the 'format' is %s)",
validate.regex()));
}
}
}
}
}
}

View File

@ -24,11 +24,17 @@ import com.sk89q.worldedit.util.command.parametric.ArgumentStack;
import com.sk89q.worldedit.util.command.parametric.BindingBehavior;
import com.sk89q.worldedit.util.command.parametric.BindingHelper;
import com.sk89q.worldedit.util.command.parametric.BindingMatch;
import com.sk89q.worldedit.util.command.parametric.ParameterException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import static com.sk89q.worldedit.util.command.parametric.BindingHelper.validate;
/**
* Standard bindings that should be available to most configurations.
*/
public final class StandardBindings extends BindingHelper {
public final class StandardBindings {
/**
* Gets a {@link CommandContext} from a {@link ArgumentStack}.
@ -42,5 +48,48 @@ public final class StandardBindings extends BindingHelper {
context.markConsumed(); // Consume entire stack
return context.getContext();
}
@BindingMatch(
type = Annotation[].class,
behavior = BindingBehavior.PROVIDES,
consumedCount = 0,
provideModifiers = true,
provideType = true)
public Annotation[] getModifiers(ArgumentStack context, Annotation[] modifiers, Type type) throws ParameterException {
return modifiers;
}
@BindingMatch(
type = Type.class,
behavior = BindingBehavior.PROVIDES,
consumedCount = 0,
provideModifiers = true,
provideType = true)
public Type getType(ArgumentStack context, Annotation[] modifiers, Type type) throws ParameterException {
return type;
}
@BindingMatch(
type = Enum.class,
behavior = BindingBehavior.CONSUMES,
consumedCount = 1,
provideModifiers = true,
provideType = true)
public Enum getEnum(ArgumentStack context, Annotation[] modifiers, Type type) throws ParameterException {
String input = context.next();
Enum value;
try {
value = Enum.valueOf((Class<Enum>) type, input);
} catch (IllegalArgumentException ignore) {
try {
value = Enum.valueOf((Class<Enum>) type, input.toUpperCase());
} catch (IllegalArgumentException e) {
throw new ParameterException("Invalid input " + input + " for type " + type);
}
}
validate(value.ordinal(), modifiers);
validate(input, modifiers);
return value;
}
}

View File

@ -22,6 +22,7 @@ package com.sk89q.worldedit.util.command.parametric;
import com.boydti.fawe.util.StringMan;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.worldedit.util.command.binding.Range;
import com.sk89q.worldedit.util.command.binding.Validate;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
@ -48,16 +49,17 @@ import java.util.List;
* <p>Methods may throw any exception. Exceptions may be converted using a
* {@link ExceptionConverter} registered with the {@link ParametricBuilder}.</p>
*/
@Deprecated
public class BindingHelper implements Binding {
private final List<BoundMethod> bindings;
private final List<BindingMap.BoundMethod> bindings;
private final Type[] types;
/**
* Create a new instance.
*/
public BindingHelper() {
List<BoundMethod> bindings = new ArrayList<>();
List<BindingMap.BoundMethod> bindings = new ArrayList<>();
List<Type> types = new ArrayList<>();
for (Method method : this.getClass().getMethods()) {
@ -88,7 +90,7 @@ public class BindingHelper implements Binding {
"A @BindingMatch needs either a type or classifier set");
}
BoundMethod handler = new BoundMethod(info, type, classifier, method);
BindingMap.BoundMethod handler = new BindingMap.BoundMethod(info, type, classifier, method, this);
bindings.add(handler);
}
}
@ -110,8 +112,8 @@ public class BindingHelper implements Binding {
* @param parameter the parameter
* @return a binding
*/
private BoundMethod match(ParameterData parameter) {
for (BoundMethod binding : bindings) {
private BindingMap.BoundMethod match(ParameterData parameter) {
for (BindingMap.BoundMethod binding : bindings) {
Annotation classifer = parameter.getClassifier();
Type type = parameter.getType();
@ -147,7 +149,7 @@ public class BindingHelper implements Binding {
@Override
public Object bind(ParameterData parameter, ArgumentStack scoped,
boolean onlyConsume) throws ParameterException, CommandException, InvocationTargetException {
BoundMethod binding = match(parameter);
BindingMap.BoundMethod binding = match(parameter);
List<Object> args = new ArrayList<>();
args.add(scoped);
@ -212,39 +214,88 @@ public class BindingHelper implements Binding {
}
return new ArrayList<>();
}
private static class BoundMethod implements Comparable<BoundMethod> {
private final BindingMatch annotation;
private final Type type;
private final Class<? extends Annotation> classifier;
private final Method method;
BoundMethod(BindingMatch annotation, Type type,
Class<? extends Annotation> classifier, Method method) {
this.annotation = annotation;
this.type = type;
this.classifier = classifier;
this.method = method;
}
@Override
public int compareTo(BoundMethod o) {
if (classifier != null && o.classifier == null) {
return -1;
} else if (classifier == null && o.classifier != null) {
return 1;
} else if (classifier != null && o.classifier != null) {
if (type != null && o.type == null) {
return -1;
} else if (type == null && o.type != null) {
return 1;
} else {
return 0;
/**
* Validate a number value using relevant modifiers.
*
* @param number the number
* @param modifiers the list of modifiers to scan
* @throws ParameterException on a validation error
*/
public static void validate(double number, Annotation[] modifiers)
throws ParameterException {
for (Annotation modifier : modifiers) {
if (modifier instanceof Range) {
Range range = (Range) modifier;
if (number < range.min()) {
throw new ParameterException(
String.format(
"A valid value is greater than or equal to %s " +
"(you entered %s)", range.min(), number));
} else if (number > range.max()) {
throw new ParameterException(
String.format(
"A valid value is less than or equal to %s " +
"(you entered %s)", range.max(), number));
}
} else {
return 0;
}
}
}
/**
* Validate a number value using relevant modifiers.
*
* @param number the number
* @param modifiers the list of modifiers to scan
* @throws ParameterException on a validation error
*/
public static void validate(int number, Annotation[] modifiers)
throws ParameterException {
for (Annotation modifier : modifiers) {
if (modifier instanceof Range) {
Range range = (Range) modifier;
if (number < range.min()) {
throw new ParameterException(
String.format(
"A valid value is greater than or equal to %s " +
"(you entered %s)", range.min(), number));
} else if (number > range.max()) {
throw new ParameterException(
String.format(
"A valid value is less than or equal to %s " +
"(you entered %s)", range.max(), number));
}
}
}
}
/**
* Validate a string value using relevant modifiers.
*
* @param string the string
* @param modifiers the list of modifiers to scan
* @throws ParameterException on a validation error
*/
public static void validate(String string, Annotation[] modifiers)
throws ParameterException {
if (string == null) {
return;
}
for (Annotation modifier : modifiers) {
if (modifier instanceof Validate) {
Validate validate = (Validate) modifier;
if (!validate.regex().isEmpty()) {
if (!string.matches(validate.regex())) {
throw new ParameterException(
String.format(
"The given text doesn't match the right " +
"format (technically speaking, the 'format' is %s)",
validate.regex()));
}
}
}
}
}
}

View File

@ -0,0 +1,304 @@
package com.sk89q.worldedit.util.command.parametric;
import com.boydti.fawe.util.ArrayUtil;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.StringMan;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.worldedit.util.command.CommandMapping;
import com.sk89q.worldedit.util.command.MissingParameterException;
import com.sk89q.worldedit.util.command.SimpleDispatcher;
import com.sk89q.worldedit.util.command.binding.Range;
import com.sk89q.worldedit.util.command.parametric.ArgumentStack;
import com.sk89q.worldedit.util.command.parametric.Binding;
import com.sk89q.worldedit.util.command.parametric.BindingBehavior;
import com.sk89q.worldedit.util.command.parametric.BindingMatch;
import com.sk89q.worldedit.util.command.parametric.ParameterData;
import com.sk89q.worldedit.util.command.parametric.ParameterException;
import com.sk89q.worldedit.util.command.parametric.ParametricBuilder;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* A binding helper that uses the {@link BindingMatch} annotation to make
* writing bindings extremely easy.
*
* <p>Methods must have the following and only the following parameters:</p>
*
* <ul>
* <li>A {@link ArgumentStack}</li>
* <li>A {@link Annotation} <strong>if there is a classifier set</strong></li>
* <li>A {@link Annotation}[]
* <strong>if there {@link BindingMatch#provideModifiers()} is true</strong></li>
* </ul>
*
* <p>Methods may throw any exception. Exceptions may be converted using a
* {@link ExceptionConverter} registered with the {@link ParametricBuilder}.</p>
*/
public class BindingMap implements Binding {
private final Set<Type> types;
private final Map<Type, Binding> legacy;
private final Map<Type, List<BoundMethod>> bindings;
private final Map<Type, SimpleDispatcher> dynamicBindings;
private final ParametricBuilder builder;
/**
* Create a new instance.
* @param builder
*/
public BindingMap(ParametricBuilder builder) {
this.dynamicBindings = new HashMap<>();
this.legacy = new HashMap<>();
this.bindings = new HashMap<>();
this.builder = builder;
this.types = new HashSet<>();
}
public void add(Object object, Type... requiredTypes) {
Method[] methods = object.getClass().getDeclaredMethods();
for (Method method : methods) {
method.setAccessible(true);
BindingMatch info = method.getAnnotation(BindingMatch.class);
if (info != null) {
Class<? extends Annotation> classifier = null;
// Set classifier
if (!info.classifier().equals(Annotation.class)) {
classifier = info.classifier();
}
for (Type type : info.type()) {
if (type == Void.class) {
type = method.getReturnType();
}
BoundMethod handler = new BoundMethod(info, type, classifier, method, object);
List<BoundMethod> list = bindings.get(type);
if (list == null) bindings.put(type, list = new ArrayList<>());
list.add(handler);
types.add(type);
}
}
Command definition = method.getAnnotation(Command.class);
Class<?> type = method.getReturnType();
if (definition != null && type != null) {
SimpleDispatcher dispatcher = dynamicBindings.get(type);
if (dispatcher == null) dynamicBindings.put(type, dispatcher = new SimpleDispatcher());
builder.registerMethodAsCommands(method, dispatcher, object, null);
types.add(type);
}
}
if (requiredTypes != null && requiredTypes.length > 0) {
for (Type type : requiredTypes) {
legacy.put(type, (Binding) object);
}
}
}
/**
* Match a {@link BindingMatch} according to the given parameter.
*
* @param pd the parameter
* @return a binding
*/
private BoundMethod match(ParameterData pd) {
Type type = pd.getType();
while (type != null) {
List<BoundMethod> methods = bindings.get(type);
if (methods != null) {
for (BoundMethod binding : methods) {
if (binding.classifier != null) {
if (pd.getClassifier() != null && pd.getClassifier().annotationType().equals(binding.classifier)) {
if (binding.type == null || binding.type.equals(type)) {
return binding;
}
}
} else if (binding.type.equals(type)) {
return binding;
}
}
}
type = (type instanceof Class) ? ((Class) type).getSuperclass() : null;
}
throw new RuntimeException("Unknown type " + pd.getType());
}
private SimpleDispatcher matchDynamic(ParameterData pd) {
return dynamicBindings.get(pd.getType());
}
@Override
public int getConsumedCount(ParameterData parameter) {
return match(parameter).annotation.consumedCount();
}
@Override
public BindingBehavior getBehavior(ParameterData parameter) {
BoundMethod matched = match(parameter);
if (matched != null) return matched.annotation.behavior();
SimpleDispatcher dynamic = matchDynamic(parameter);
return dynamic != null ? BindingBehavior.CONSUMES : null;
}
@Override
public Type[] getTypes() {
return types.toArray(new Type[0]);
}
@Override
public Object bind(ParameterData parameter, ArgumentStack scoped, boolean onlyConsume) throws ParameterException, CommandException, InvocationTargetException {
BoundMethod binding = match(parameter);
List<Object> args = new ArrayList<>();
args.add(scoped);
if (binding.classifier != null) {
args.add(parameter.getClassifier());
}
if (binding.annotation.provideModifiers()) {
args.add(parameter.getModifiers());
}
if (binding.annotation.provideType()) {
args.add(parameter.getType());
}
if (onlyConsume && binding.annotation.behavior() == BindingBehavior.PROVIDES) {
return null; // Nothing to consume, nothing to do
}
if (binding.annotation.behavior() != BindingBehavior.PROVIDES) {
SimpleDispatcher dynamic = matchDynamic(parameter);
if (dynamic != null) {
scoped.mark();
String rest = scoped.remaining();
scoped.reset();
int start = rest.indexOf('{');
if (start > 0) {
int end = StringMan.findMatchingBracket(rest, start);
if (end > start) {
String alias = rest.substring(0, start);
CommandMapping cmd = dynamic.get(alias);
if (cmd != null) {
String arguments = rest.substring(start + 1, end);
CommandLocals locals = scoped.getContext().getLocals();
Object result = cmd.getCallable().call(arguments, locals, new String[0]);
int remaining = rest.length() - end;
while (rest.length() > remaining) {
scoped.next();
try {
scoped.mark();
rest = scoped.remaining();
scoped.reset();
} catch (MissingParameterException ignore) { rest = ""; }
}
return result;
}
}
}
}
}
Object[] argsArray = new Object[args.size()];
args.toArray(argsArray);
try {
return binding.method.invoke(binding.object, argsArray);
} catch (IllegalArgumentException e) {
throw new RuntimeException(
"Processing of classifier " + parameter.getClassifier() +
" and type " + parameter.getType() + " failed for method\n" +
binding.method + "\nbecause the parameters for that method are wrong", e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
if (e.getCause() instanceof ParameterException) {
throw (ParameterException) e.getCause();
} else if (e.getCause() instanceof CommandException) {
throw (CommandException) e.getCause();
}
throw e;
}
}
@Override
public List<String> getSuggestions(ParameterData parameter, String prefix) {
Binding legacySuggestions = legacy.get(parameter.getType());
if (legacySuggestions != null) {
List<String> result = legacySuggestions.getSuggestions(parameter, prefix);
if (result != null) return result;
}
if (prefix.isEmpty()) {
char bracket = parameter.isOptional() ? '[' : '<';
char endBracket = StringMan.getMatchingBracket(bracket);
StringBuilder result = new StringBuilder();
result.append("\u00A75");
result.append(bracket);
result.append("\u00A7r");
if (parameter.getFlag() != null) {
result.append('-').append(parameter.getFlag()).append("\u00A75 \u00A7r");
}
result.append(parameter.getName());
if (parameter.getDefaultValue() != null) {
result.append('=').append(StringMan.join(parameter.getDefaultValue(), " "));
}
Range range = parameter.getModifier(Range.class);
if (range != null) {
result.append('|').append(StringMan.prettyFormat(range.min())).append(",").append(StringMan.prettyFormat(range.max()));
}
result.append("\u00A75");
result.append(endBracket);
result.append("\u00A7r");
return Collections.singletonList(result.toString());
}
return new ArrayList<>();
}
protected static class BoundMethod implements Comparable<BoundMethod> {
protected final BindingMatch annotation;
protected final Type type;
protected final Class<? extends Annotation> classifier;
protected final Method method;
protected final Object object;
BoundMethod(BindingMatch annotation, Type type,
Class<? extends Annotation> classifier, Method method, Object object) {
this.annotation = annotation;
this.type = type;
this.classifier = classifier;
this.method = method;
this.object = object;
}
@Override
public int compareTo(BoundMethod o) {
if (classifier != null && o.classifier == null) {
return -1;
} else if (classifier == null && o.classifier != null) {
return 1;
} else if (classifier != null && o.classifier != null) {
if (type != null && o.type == null) {
return -1;
} else if (type == null && o.type != null) {
return 1;
} else {
return 0;
}
} else {
return 0;
}
}
}
}

View File

@ -45,7 +45,7 @@ public @interface BindingMatch {
* @return the type, or {@link Class} if not set
*/
Class<?>[] type() default Class.class;
/**
* The binding behavior.
*
@ -68,4 +68,9 @@ public @interface BindingMatch {
*/
boolean provideModifiers() default false;
/**
* If the type should be passed to the method
*/
boolean provideType() default false;
}

View File

@ -33,10 +33,8 @@ public class FunctionParametricCallable extends AParametricCallable {
List<Object[]> paramParsables = new ArrayList<>();
{
Map<Type, Binding> bindings = builder.getBindings();
Map<String, Type> unqualified = new HashMap<>();
for (Map.Entry<Type, Binding> entry : bindings.entrySet()) {
Type type = entry.getKey();
for (Type type : builder.getBindings().getTypes()) {
String typeStr = type.getTypeName();
unqualified.put(typeStr, type);
unqualified.put(typeStr.substring(typeStr.lastIndexOf('.') + 1), type);
@ -117,7 +115,7 @@ public class FunctionParametricCallable extends AParametricCallable {
// No special @annotation binding... let's check for the type
if (parameter.getBinding() == null) {
parameter.setBinding(builder.getBindings().get(type));
parameter.setBinding(builder.getBindings());
// Don't know how to parse for this type of value
if (parameter.getBinding() == null) {

View File

@ -65,7 +65,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
*/
public class ParametricBuilder {
private final Map<Type, Binding> bindings = new HashMap<>();
private final BindingMap bindings;
private final Paranamer paranamer = new FaweParanamer();
private final List<InvokeListener> invokeListeners = new ArrayList<>();
private final List<ExceptionConverter> exceptionConverters = new ArrayList<>();
@ -79,8 +79,9 @@ public class ParametricBuilder {
* {@link StandardBindings} and default bindings.</p>
*/
public ParametricBuilder() {
addBinding(new FawePrimitiveBinding());
addBinding(new StandardBindings());
this.bindings = new BindingMap(this);
this.bindings.add(new FawePrimitiveBinding());
this.bindings.add(new StandardBindings());
}
/**
@ -103,14 +104,17 @@ public class ParametricBuilder {
* @param binding the binding
* @param type a list of types (if specified) to override the binding's types
*/
@Deprecated
public void addBinding(Binding binding, Type... type) {
if (type == null || type.length == 0) {
type = binding.getTypes();
}
this.bindings.add(binding);
}
for (Type t : type) {
bindings.put(t, binding);
}
/**
* Add a binding (accepts @Command or @BindingMatch methods)
* @param binding
*/
public void addBinding(Object binding) {
this.bindings.add(binding);
}
/**
@ -175,21 +179,22 @@ public class ParametricBuilder {
*/
public void registerMethodsAsCommands(Dispatcher dispatcher, Object object, CallableProcessor processor) throws ParametricException {
for (Method method : object.getClass().getDeclaredMethods()) {
Command definition = method.getAnnotation(Command.class);
if (definition != null) {
definition = Commands.translate(method.getDeclaringClass(), definition);
CommandCallable callable = build(object, method, definition);
if (processor != null) {
callable = new ProcessedCallable(callable, processor);
}
else if (object instanceof CallableProcessor) {
callable = new ProcessedCallable(callable, (CallableProcessor) object);
}
if (object instanceof MethodCommands) {
((MethodCommands) object).register(method, callable, dispatcher);
}
dispatcher.registerCommand(callable, definition.aliases());
registerMethodAsCommands(method, dispatcher, object, processor);
}
}
public void registerMethodAsCommands(Method method, Dispatcher dispatcher, Object object, CallableProcessor processor) throws ParametricException {
Command definition = method.getAnnotation(Command.class);
if (definition != null) {
definition = Commands.translate(method.getDeclaringClass(), definition);
CommandCallable callable = build(object, method, definition);
if (processor != null) {
callable = new ProcessedCallable(callable, processor);
}
else if (object instanceof CallableProcessor) {
callable = new ProcessedCallable(callable, (CallableProcessor) object);
}
dispatcher.registerCommand(callable, definition.aliases());
}
}
@ -230,7 +235,7 @@ public class ParametricBuilder {
*
* @return the map of bindings
*/
public Map<Type, Binding> getBindings() {
public BindingMap getBindings() {
return bindings;
}

View File

@ -113,7 +113,7 @@ public class ParametricCallable extends AParametricCallable {
}
// Special annotation bindings
} else if (parameter.getBinding() == null) {
parameter.setBinding(builder.getBindings().get(annotation.annotationType()));
parameter.setBinding(builder.getBindings());
parameter.setClassifier(annotation);
}
}
@ -127,7 +127,7 @@ public class ParametricCallable extends AParametricCallable {
// No special @annotation binding... let's check for the type
if (parameter.getBinding() == null) {
parameter.setBinding(builder.getBindings().get(type));
parameter.setBinding(builder.getBindings());
// Don't know how to parse for this type of value
if (parameter.getBinding() == null) {