Merge pull request 'CMDAPIChangesForTeamCommand' (#40) from CMDAPIChangesForTeamCommand into master
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Reviewed-on: #40 Reviewed-by: Lixfel <lixfel@steamwar.de>
Dieser Commit ist enthalten in:
Commit
a560ddd689
@ -21,13 +21,12 @@ package de.steamwar.command;
|
|||||||
|
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Parameter;
|
import java.lang.reflect.Parameter;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.*;
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public abstract class AbstractSWCommand<T> {
|
public abstract class AbstractSWCommand<T> {
|
||||||
@ -65,50 +64,14 @@ public abstract class AbstractSWCommand<T> {
|
|||||||
System.out.println(message.get());
|
System.out.println(message.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void sendMessage(T sender, String message, Object[] args) {}
|
protected void sendMessage(T sender, String message, Object[] args) {
|
||||||
|
|
||||||
private String[] quote(String[] args) {
|
|
||||||
List<String> list = new ArrayList<>();
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
boolean quote = false;
|
|
||||||
for (String arg : args) {
|
|
||||||
if (arg.startsWith("\"") && arg.endsWith("\"")) {
|
|
||||||
list.add(arg);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (arg.startsWith("\"")) {
|
|
||||||
quote = true;
|
|
||||||
builder.append(arg);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (arg.endsWith("\"")) {
|
|
||||||
quote = false;
|
|
||||||
builder.append(" ").append(arg);
|
|
||||||
list.add(builder.toString());
|
|
||||||
builder = new StringBuilder();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (quote) {
|
|
||||||
builder.append(" ").append(arg);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
list.add(arg);
|
|
||||||
}
|
|
||||||
if (quote) {
|
|
||||||
builder.append("\"");
|
|
||||||
}
|
|
||||||
if (builder.length() > 0) {
|
|
||||||
list.add(builder.toString());
|
|
||||||
}
|
|
||||||
return list.toArray(new String[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final void execute(T sender, String alias, String[] args) {
|
protected final void execute(T sender, String alias, String[] args) {
|
||||||
initialize();
|
initialize();
|
||||||
String[] finalArgs = quote(args);
|
|
||||||
List<Runnable> errors = new ArrayList<>();
|
List<Runnable> errors = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
if (!commandList.stream().anyMatch(s -> s.invoke(errors::add, sender, alias, finalArgs))) {
|
if (!commandList.stream().anyMatch(s -> s.invoke(errors::add, sender, alias, args))) {
|
||||||
errors.forEach(Runnable::run);
|
errors.forEach(Runnable::run);
|
||||||
}
|
}
|
||||||
} catch (CommandFrameworkException e) {
|
} catch (CommandFrameworkException e) {
|
||||||
@ -119,15 +82,14 @@ public abstract class AbstractSWCommand<T> {
|
|||||||
|
|
||||||
protected final List<String> tabComplete(T sender, String alias, String[] args) throws IllegalArgumentException {
|
protected final List<String> tabComplete(T sender, String alias, String[] args) throws IllegalArgumentException {
|
||||||
initialize();
|
initialize();
|
||||||
String[] finalArgs = quote(args);
|
|
||||||
String string = args[args.length - 1].toLowerCase();
|
String string = args[args.length - 1].toLowerCase();
|
||||||
return commandList.stream()
|
return commandList.stream()
|
||||||
.filter(s -> !s.noTabComplete)
|
.filter(s -> !s.noTabComplete)
|
||||||
.map(s -> s.tabComplete(sender, finalArgs))
|
.map(s -> s.tabComplete(sender, args))
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.flatMap(Collection::stream)
|
.flatMap(Collection::stream)
|
||||||
.filter(s -> !s.isEmpty())
|
.filter(s -> !s.isEmpty())
|
||||||
.filter(s -> s.toLowerCase().startsWith(string))
|
.filter(s -> s.toLowerCase().startsWith(string) || string.startsWith(s.toLowerCase()))
|
||||||
.distinct()
|
.distinct()
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
@ -183,38 +145,52 @@ public abstract class AbstractSWCommand<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean validateMethod(Method method) {
|
private boolean validateMethod(Method method) {
|
||||||
if (!checkType(method.getAnnotations(), method.getReturnType(), annotation -> {
|
if (!checkType(method.getAnnotations(), method.getReturnType(), false, annotation -> {
|
||||||
CommandMetaData.Method methodMetaData = annotation.annotationType().getAnnotation(CommandMetaData.Method.class);
|
CommandMetaData.Method methodMetaData = annotation.annotationType().getAnnotation(CommandMetaData.Method.class);
|
||||||
if (methodMetaData == null) return null;
|
if (methodMetaData == null) return (aClass, varArg) -> true;
|
||||||
if (method.getParameterCount() > methodMetaData.maxParameterCount() || method.getParameterCount() < methodMetaData.minParameterCount()) return new Class[0];
|
if (method.getParameterCount() > methodMetaData.maxParameterCount() || method.getParameterCount() < methodMetaData.minParameterCount())
|
||||||
return methodMetaData.value();
|
return (aClass, varArg) -> false;
|
||||||
|
return (aClass, varArg) -> {
|
||||||
|
Class<?>[] types = methodMetaData.value();
|
||||||
|
if (types == null) return true;
|
||||||
|
for (Class<?> type : types) {
|
||||||
|
if (type.isAssignableFrom(aClass)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
}, "The method '" + method + "'")) return false;
|
}, "The method '" + method + "'")) return false;
|
||||||
boolean valid = true;
|
boolean valid = true;
|
||||||
for (Parameter parameter : method.getParameters()) {
|
for (Parameter parameter : method.getParameters()) {
|
||||||
Class<?> type = parameter.getType();
|
if (!checkType(parameter.getAnnotations(), parameter.getType(), parameter.isVarArgs(), annotation -> {
|
||||||
if (parameter.isVarArgs()) type = type.getComponentType();
|
|
||||||
if (!checkType(parameter.getAnnotations(), type, annotation -> {
|
|
||||||
CommandMetaData.Parameter parameterMetaData = annotation.annotationType().getAnnotation(CommandMetaData.Parameter.class);
|
CommandMetaData.Parameter parameterMetaData = annotation.annotationType().getAnnotation(CommandMetaData.Parameter.class);
|
||||||
if (parameterMetaData == null) return null;
|
if (parameterMetaData == null) return (aClass, varArg) -> true;
|
||||||
return parameterMetaData.value();
|
Class<?> handler = parameterMetaData.handler();
|
||||||
|
if (BiPredicate.class.isAssignableFrom(handler)) {
|
||||||
|
try {
|
||||||
|
return (BiPredicate<Class<?>, Boolean>) handler.getConstructor().newInstance();
|
||||||
|
} catch (InstantiationException | IllegalAccessException | InvocationTargetException |
|
||||||
|
NoSuchMethodException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (aClass, varArg) -> {
|
||||||
|
if (varArg) aClass = aClass.getComponentType();
|
||||||
|
Class<?>[] types = parameterMetaData.value();
|
||||||
|
if (types == null) return true;
|
||||||
|
for (Class<?> current : types) {
|
||||||
|
if (current.isAssignableFrom(aClass)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
}, "The parameter '" + parameter + "'")) valid = false;
|
}, "The parameter '" + parameter + "'")) valid = false;
|
||||||
}
|
}
|
||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkType(Annotation[] annotations, Class<?> clazz, Function<Annotation, Class<?>[]> toApplicableTypes, String warning) {
|
private boolean checkType(Annotation[] annotations, Class<?> clazz, boolean varArg, Function<Annotation, BiPredicate<Class<?>, Boolean>> toApplicableTypes, String warning) {
|
||||||
boolean valid = true;
|
boolean valid = true;
|
||||||
for (Annotation annotation : annotations) {
|
for (Annotation annotation : annotations) {
|
||||||
Class<?>[] types = toApplicableTypes.apply(annotation);
|
BiPredicate<Class<?>, Boolean> predicate = toApplicableTypes.apply(annotation);
|
||||||
if (types == null) continue;
|
if (!predicate.test(clazz, varArg)) {
|
||||||
boolean applicable = false;
|
|
||||||
for (Class<?> type : types) {
|
|
||||||
if (type.isAssignableFrom(clazz)) {
|
|
||||||
applicable = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!applicable) {
|
|
||||||
commandSystemWarning(() -> warning + " is using an unsupported annotation of type '" + annotation.annotationType().getName() + "'");
|
commandSystemWarning(() -> warning + " is using an unsupported annotation of type '" + annotation.annotationType().getName() + "'");
|
||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
@ -341,7 +317,9 @@ public abstract class AbstractSWCommand<T> {
|
|||||||
@CommandMetaData.Method(value = AbstractTypeMapper.class, maxParameterCount = 0)
|
@CommandMetaData.Method(value = AbstractTypeMapper.class, maxParameterCount = 0)
|
||||||
protected @interface Cached {
|
protected @interface Cached {
|
||||||
long cacheDuration() default 5;
|
long cacheDuration() default 5;
|
||||||
|
|
||||||
TimeUnit timeUnit() default TimeUnit.SECONDS;
|
TimeUnit timeUnit() default TimeUnit.SECONDS;
|
||||||
|
|
||||||
boolean global() default false;
|
boolean global() default false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -401,7 +379,7 @@ public abstract class AbstractSWCommand<T> {
|
|||||||
*/
|
*/
|
||||||
boolean allowISE() default false;
|
boolean allowISE() default false;
|
||||||
|
|
||||||
int[] falseValues() default { 0 };
|
int[] falseValues() default {0};
|
||||||
|
|
||||||
class Handler<T> implements AbstractTypeMapper<T, Object> {
|
class Handler<T> implements AbstractTypeMapper<T, Object> {
|
||||||
|
|
||||||
@ -439,11 +417,6 @@ public abstract class AbstractSWCommand<T> {
|
|||||||
return inner.map(sender, previousArguments, s);
|
return inner.map(sender, previousArguments, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean validate(T sender, Object value, MessageSender messageSender) {
|
|
||||||
return inner.validate(sender, value, messageSender);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<String> tabCompletes(T sender, PreviousArguments previousArguments, String s) {
|
public Collection<String> tabCompletes(T sender, PreviousArguments previousArguments, String s) {
|
||||||
return inner.tabCompletes(sender, previousArguments, s);
|
return inner.tabCompletes(sender, previousArguments, s);
|
||||||
@ -469,7 +442,7 @@ public abstract class AbstractSWCommand<T> {
|
|||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target({ElementType.PARAMETER})
|
@Target({ElementType.PARAMETER})
|
||||||
@CommandMetaData.ImplicitValidator(handler = ErrorMessage.Handler.class, order = 1)
|
@CommandMetaData.ImplicitValidator(handler = ErrorMessage.Handler.class, order = Integer.MAX_VALUE)
|
||||||
protected @interface ErrorMessage {
|
protected @interface ErrorMessage {
|
||||||
/**
|
/**
|
||||||
* Error message to be displayed when the parameter is invalid.
|
* Error message to be displayed when the parameter is invalid.
|
||||||
@ -506,23 +479,17 @@ public abstract class AbstractSWCommand<T> {
|
|||||||
protected @interface AllowNull {
|
protected @interface AllowNull {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This annotation is used to mark a String to be quotable with multiple words.
|
|
||||||
*/
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target({ElementType.PARAMETER})
|
|
||||||
@CommandMetaData.Parameter({String.class})
|
|
||||||
protected @interface Quotable {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target({ElementType.PARAMETER})
|
@Target({ElementType.PARAMETER})
|
||||||
@CommandMetaData.Parameter({int.class, Integer.class, long.class, Long.class, float.class, Float.class, double.class, Double.class})
|
@CommandMetaData.Parameter({int.class, Integer.class, long.class, Long.class, float.class, Float.class, double.class, Double.class})
|
||||||
@CommandMetaData.ImplicitValidator(handler = Min.Handler.class, order = 2)
|
@CommandMetaData.ImplicitValidator(handler = Min.Handler.class, order = 2)
|
||||||
protected @interface Min {
|
protected @interface Min {
|
||||||
int intValue() default Integer.MIN_VALUE;
|
int intValue() default Integer.MIN_VALUE;
|
||||||
|
|
||||||
long longValue() default Long.MIN_VALUE;
|
long longValue() default Long.MIN_VALUE;
|
||||||
|
|
||||||
float floatValue() default Float.MIN_VALUE;
|
float floatValue() default Float.MIN_VALUE;
|
||||||
|
|
||||||
double doubleValue() default Double.MIN_VALUE;
|
double doubleValue() default Double.MIN_VALUE;
|
||||||
|
|
||||||
boolean inclusive() default true;
|
boolean inclusive() default true;
|
||||||
@ -539,6 +506,7 @@ public abstract class AbstractSWCommand<T> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean validate(T sender, Number value, MessageSender messageSender) {
|
public boolean validate(T sender, Number value, MessageSender messageSender) {
|
||||||
|
if (value == null) return true;
|
||||||
return (comparator.apply(value).intValue()) >= this.value;
|
return (comparator.apply(value).intValue()) >= this.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -550,8 +518,11 @@ public abstract class AbstractSWCommand<T> {
|
|||||||
@CommandMetaData.ImplicitValidator(handler = Max.Handler.class, order = 2)
|
@CommandMetaData.ImplicitValidator(handler = Max.Handler.class, order = 2)
|
||||||
protected @interface Max {
|
protected @interface Max {
|
||||||
int intValue() default Integer.MAX_VALUE;
|
int intValue() default Integer.MAX_VALUE;
|
||||||
|
|
||||||
long longValue() default Long.MAX_VALUE;
|
long longValue() default Long.MAX_VALUE;
|
||||||
|
|
||||||
float floatValue() default Float.MAX_VALUE;
|
float floatValue() default Float.MAX_VALUE;
|
||||||
|
|
||||||
double doubleValue() default Double.MAX_VALUE;
|
double doubleValue() default Double.MAX_VALUE;
|
||||||
|
|
||||||
boolean inclusive() default true;
|
boolean inclusive() default true;
|
||||||
@ -568,6 +539,7 @@ public abstract class AbstractSWCommand<T> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean validate(T sender, Number value, MessageSender messageSender) {
|
public boolean validate(T sender, Number value, MessageSender messageSender) {
|
||||||
|
if (value == null) return true;
|
||||||
return (comparator.apply(value).intValue()) <= this.value;
|
return (comparator.apply(value).intValue()) <= this.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -586,4 +558,85 @@ public abstract class AbstractSWCommand<T> {
|
|||||||
throw new IllegalArgumentException(type + " annotation is not supported for " + clazz);
|
throw new IllegalArgumentException(type + " annotation is not supported for " + clazz);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ElementType.PARAMETER})
|
||||||
|
@CommandMetaData.ImplicitTypeMapper(handler = Length.Handler.class)
|
||||||
|
protected @interface Length {
|
||||||
|
int min() default 0;
|
||||||
|
|
||||||
|
int max() default Integer.MAX_VALUE;
|
||||||
|
|
||||||
|
class Handler<T> implements AbstractTypeMapper<T, Object> {
|
||||||
|
|
||||||
|
private int min;
|
||||||
|
private int max;
|
||||||
|
private AbstractTypeMapper<T, Object> inner;
|
||||||
|
|
||||||
|
public Handler(Length length, AbstractTypeMapper<T, Object> inner) {
|
||||||
|
this.min = length.min();
|
||||||
|
this.max = length.max();
|
||||||
|
this.inner = inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object map(T sender, PreviousArguments previousArguments, String s) {
|
||||||
|
if (s.length() < min || s.length() > max) return null;
|
||||||
|
return inner.map(sender, previousArguments, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<String> tabCompletes(T sender, PreviousArguments previousArguments, String s) {
|
||||||
|
List<String> tabCompletes = inner.tabCompletes(sender, previousArguments, s)
|
||||||
|
.stream()
|
||||||
|
.filter(str -> str.length() >= min)
|
||||||
|
.map(str -> str.substring(0, Math.min(str.length(), max)))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (s.length() < min) {
|
||||||
|
tabCompletes.add(0, s);
|
||||||
|
}
|
||||||
|
return tabCompletes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String normalize(T sender, String s) {
|
||||||
|
return inner.normalize(sender, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ElementType.PARAMETER})
|
||||||
|
@CommandMetaData.Parameter(handler = ArrayLength.Type.class)
|
||||||
|
@CommandMetaData.ImplicitValidator(handler = ArrayLength.Handler.class, order = 1)
|
||||||
|
protected @interface ArrayLength {
|
||||||
|
int min() default 0;
|
||||||
|
|
||||||
|
int max() default Integer.MAX_VALUE;
|
||||||
|
|
||||||
|
class Type implements BiPredicate<Class<?>, Boolean> {
|
||||||
|
@Override
|
||||||
|
public boolean test(Class<?> clazz, Boolean isVarArgs) {
|
||||||
|
return clazz.isArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Handler<T> implements AbstractValidator<T, Object> {
|
||||||
|
|
||||||
|
private int min;
|
||||||
|
private int max;
|
||||||
|
|
||||||
|
public Handler(ArrayLength arrayLength) {
|
||||||
|
this.min = arrayLength.min();
|
||||||
|
this.max = arrayLength.max();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean validate(T sender, Object value, MessageSender messageSender) {
|
||||||
|
if (value == null) return true;
|
||||||
|
int length = Array.getLength(value);
|
||||||
|
return length >= min && length <= max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,10 +19,7 @@
|
|||||||
|
|
||||||
package de.steamwar.command;
|
package de.steamwar.command;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.*;
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
public @interface CommandMetaData {
|
public @interface CommandMetaData {
|
||||||
|
|
||||||
@ -43,7 +40,8 @@ public @interface CommandMetaData {
|
|||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.ANNOTATION_TYPE)
|
@Target(ElementType.ANNOTATION_TYPE)
|
||||||
@interface Parameter {
|
@interface Parameter {
|
||||||
Class<?>[] value();
|
Class<?>[] value() default {};
|
||||||
|
Class<?> handler() default void.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -181,6 +181,7 @@ class CommandPart<T> {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return new CheckArgumentResult(false, null);
|
return new CheckArgumentResult(false, null);
|
||||||
}
|
}
|
||||||
|
boolean success = true;
|
||||||
for (AbstractValidator<T, Object> validator : validators) {
|
for (AbstractValidator<T, Object> validator : validators) {
|
||||||
try {
|
try {
|
||||||
if (!validator.validate(sender, value, (s, objects) -> {
|
if (!validator.validate(sender, value, (s, objects) -> {
|
||||||
@ -188,13 +189,14 @@ class CommandPart<T> {
|
|||||||
command.sendMessage(sender, s, objects);
|
command.sendMessage(sender, s, objects);
|
||||||
});
|
});
|
||||||
})) {
|
})) {
|
||||||
return new CheckArgumentResult(false, null);
|
success = false;
|
||||||
|
value = null;
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
throw CommandFrameworkException.commandPartExceptions("validating", e, args[index], (varArgType != null ? varArgType : parameter.getType()), parameter.getDeclaringExecutable(), parameterIndex);
|
throw CommandFrameworkException.commandPartExceptions("validating", e, args[index], (varArgType != null ? varArgType : parameter.getType()), parameter.getDeclaringExecutable(), parameterIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new CheckArgumentResult(true, value);
|
return new CheckArgumentResult(success, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class<?> getType() {
|
public Class<?> getType() {
|
||||||
|
@ -61,15 +61,7 @@ public class SWCommandUtils {
|
|||||||
addMapper(double.class, Double.class, createMapper(numberMapper(Double::parseDouble), numberCompleter(Double::parseDouble, true)));
|
addMapper(double.class, Double.class, createMapper(numberMapper(Double::parseDouble), numberCompleter(Double::parseDouble, true)));
|
||||||
addMapper(int.class, Integer.class, createMapper(numberMapper(Integer::parseInt), numberCompleter(Integer::parseInt, false)));
|
addMapper(int.class, Integer.class, createMapper(numberMapper(Integer::parseInt), numberCompleter(Integer::parseInt, false)));
|
||||||
addMapper(long.class, Long.class, createMapper(numberMapper(Long::parseLong), numberCompleter(Long::parseLong, false)));
|
addMapper(long.class, Long.class, createMapper(numberMapper(Long::parseLong), numberCompleter(Long::parseLong, false)));
|
||||||
MAPPER_FUNCTIONS.put(String.class.getTypeName(), createMapper(s -> {
|
MAPPER_FUNCTIONS.put(String.class.getTypeName(), createMapper(s -> s, Collections::singletonList));
|
||||||
if (s.startsWith("\"") && s.endsWith("\"")) {
|
|
||||||
return s.substring(1, s.length() - 1);
|
|
||||||
}
|
|
||||||
if (s.startsWith("'") && s.endsWith("'")) {
|
|
||||||
return s.substring(1, s.length() - 1);
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}, Collections::singletonList));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends AbstractTypeMapper<K, V>, K, V> void init(SWTypeMapperCreator<T, K, V> swTypeMapperCreator) {
|
public static <T extends AbstractTypeMapper<K, V>, K, V> void init(SWTypeMapperCreator<T, K, V> swTypeMapperCreator) {
|
||||||
|
@ -150,9 +150,6 @@ public class SubCommand<T> {
|
|||||||
|
|
||||||
CommandPart<T> commandPart = new CommandPart<>(command, typeMapper, varArgType, optionalValue != null ? optionalValue.value() : null, parameter, i);
|
CommandPart<T> commandPart = new CommandPart<>(command, typeMapper, varArgType, optionalValue != null ? optionalValue.value() : null, parameter, i);
|
||||||
commandPart.setOnlyUseIfNoneIsGiven(optionalValue != null && optionalValue.onlyUINIG());
|
commandPart.setOnlyUseIfNoneIsGiven(optionalValue != null && optionalValue.onlyUINIG());
|
||||||
if (parameter.getAnnotation(AbstractSWCommand.Quotable.class) == null) {
|
|
||||||
commandPart.addValidator((AbstractValidator<T, Object>) STRING_SPACE_FILTER);
|
|
||||||
}
|
|
||||||
handleImplicitTypeValidator(parameter, commandPart, localValidator);
|
handleImplicitTypeValidator(parameter, commandPart, localValidator);
|
||||||
if (parameter.getAnnotation(AbstractSWCommand.AllowNull.class) == null) {
|
if (parameter.getAnnotation(AbstractSWCommand.AllowNull.class) == null) {
|
||||||
commandPart.addValidator((AbstractValidator<T, Object>) NULL_FILTER);
|
commandPart.addValidator((AbstractValidator<T, Object>) NULL_FILTER);
|
||||||
@ -270,9 +267,4 @@ public class SubCommand<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static final AbstractValidator<?, Object> NULL_FILTER = (sender, value, messageSender) -> value != null;
|
private static final AbstractValidator<?, Object> NULL_FILTER = (sender, value, messageSender) -> value != null;
|
||||||
|
|
||||||
private static final AbstractValidator<?, Object> STRING_SPACE_FILTER = (sender, value, messageSender) -> {
|
|
||||||
if (!(value instanceof String)) return true;
|
|
||||||
return !((String) value).contains(" ");
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,17 @@ public class ArgumentCommand extends TestSWCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Register
|
@Register
|
||||||
public void argument(String sender, @Quotable String arg) {
|
public void argument(String sender, String arg) {
|
||||||
throw new ExecutionIdentifier("RunArgument with String");
|
throw new ExecutionIdentifier("RunArgument with String");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Register
|
||||||
|
public void minLengthArgument(String sender, @Length(min = 3) @StaticValue({"he", "hello"}) String arg) {
|
||||||
|
throw new ExecutionIdentifier("RunLengthArgument with String");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Register
|
||||||
|
public void minAndMaxLengthArgument(String sender, @Length(min = 3, max = 3) @StaticValue({"wo", "world"}) String arg) {
|
||||||
|
throw new ExecutionIdentifier("RunLengthArgument with String");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,34 +94,11 @@ public class ArgumentCommandTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testString() {
|
|
||||||
ArgumentCommand cmd = new ArgumentCommand();
|
|
||||||
try {
|
|
||||||
cmd.execute("test", "", new String[]{"Hello World"});
|
|
||||||
assert false;
|
|
||||||
} catch (Exception e) {
|
|
||||||
assertCMDFramework(e, ExecutionIdentifier.class, "RunArgument with String");
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
cmd.execute("test", "", new String[]{"\"Hello World\""});
|
|
||||||
assert false;
|
|
||||||
} catch (Exception e) {
|
|
||||||
assertCMDFramework(e, ExecutionIdentifier.class, "RunArgument with String");
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
cmd.execute("test", "", new String[]{"\"Hello", "World\""});
|
|
||||||
assert false;
|
|
||||||
} catch (Exception e) {
|
|
||||||
assertCMDFramework(e, ExecutionIdentifier.class, "RunArgument with String");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTabComplete() {
|
public void testTabComplete() {
|
||||||
ArgumentCommand cmd = new ArgumentCommand();
|
ArgumentCommand cmd = new ArgumentCommand();
|
||||||
List<String> strings = cmd.tabComplete("test", "", new String[]{""});
|
List<String> strings = cmd.tabComplete("test", "", new String[]{""});
|
||||||
assertTabCompletes(strings, "true", "false");
|
assertTabCompletes(strings, "true", "false", "hello", "wor");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -129,5 +106,20 @@ public class ArgumentCommandTest {
|
|||||||
ArgumentCommand cmd = new ArgumentCommand();
|
ArgumentCommand cmd = new ArgumentCommand();
|
||||||
List<String> strings = cmd.tabComplete("test", "", new String[]{"t"});
|
List<String> strings = cmd.tabComplete("test", "", new String[]{"t"});
|
||||||
assertTabCompletes(strings, "true", "t");
|
assertTabCompletes(strings, "true", "t");
|
||||||
|
|
||||||
|
strings = cmd.tabComplete("test", "", new String[]{"h"});
|
||||||
|
assertTabCompletes(strings, "h", "hello");
|
||||||
|
|
||||||
|
strings = cmd.tabComplete("test", "", new String[]{"hel"});
|
||||||
|
assertTabCompletes(strings, "hel", "hello");
|
||||||
|
|
||||||
|
strings = cmd.tabComplete("test", "", new String[]{"w"});
|
||||||
|
assertTabCompletes(strings, "w", "wor");
|
||||||
|
|
||||||
|
strings = cmd.tabComplete("test", "", new String[]{"wor"});
|
||||||
|
assertTabCompletes(strings, "wor");
|
||||||
|
|
||||||
|
strings = cmd.tabComplete("test", "", new String[]{"worl"});
|
||||||
|
assertTabCompletes(strings, "wor", "worl");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren