diff --git a/src/de/steamwar/command/AbstractSWCommand.java b/src/de/steamwar/command/AbstractSWCommand.java
deleted file mode 100644
index 65f6643..0000000
--- a/src/de/steamwar/command/AbstractSWCommand.java
+++ /dev/null
@@ -1,711 +0,0 @@
-/*
- * This file is a part of the SteamWar software.
- *
- * Copyright (C) 2020 SteamWar.de-Serverteam
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package de.steamwar.command;
-
-import java.lang.annotation.*;
-import java.lang.reflect.Array;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Parameter;
-import java.util.*;
-import java.util.concurrent.TimeUnit;
-import java.util.function.BiConsumer;
-import java.util.function.BiPredicate;
-import java.util.function.Function;
-import java.util.function.Supplier;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-public abstract class AbstractSWCommand {
-
- private static final Map>, List>> dependencyMap = new HashMap<>();
-
- private Class> clazz; // This is used in createMappings()
-
- private boolean initialized = false;
- protected final List> commandList = new ArrayList<>();
- protected final List> helpCommandList = new ArrayList<>();
-
- private final Map> localTypeMapper = new HashMap<>();
- private final Map> localValidators = new HashMap<>();
-
- protected AbstractSWCommand(Class clazz, String command) {
- this(clazz, command, new String[0]);
- }
-
- protected AbstractSWCommand(Class clazz, String command, String... aliases) {
- this.clazz = clazz;
-
- PartOf partOf = this.getClass().getAnnotation(PartOf.class);
- if (partOf != null) {
- dependencyMap.computeIfAbsent((Class>) partOf.value(), k -> new ArrayList<>()).add(this);
- return;
- }
-
- createAndSafeCommand(command, aliases);
- unregister();
- register();
- }
-
- protected abstract void createAndSafeCommand(String command, String[] aliases);
-
- public abstract void unregister();
-
- public abstract void register();
-
- protected void commandSystemError(T sender, CommandFrameworkException e) {
- e.printStackTrace();
- }
-
- protected void commandSystemWarning(Supplier message) {
- System.out.println(message.get());
- }
-
- protected void sendMessage(T sender, String message, Object[] args) {
- }
-
- protected void initialisePartOf(AbstractSWCommand parent) {
- }
-
- protected final void execute(T sender, String alias, String[] args) {
- initialize();
- List errors = new ArrayList<>();
- try {
- if (commandList.stream().noneMatch(s -> s.invoke(errors::add, sender, alias, args))) {
- errors.forEach(Runnable::run);
- } else return;
- if (errors.isEmpty() && helpCommandList.stream().noneMatch(s -> s.invoke(errors::add, sender, alias, args))) {
- errors.forEach(Runnable::run);
- }
- } catch (CommandFrameworkException e) {
- commandSystemError(sender, e);
- throw e;
- }
- }
-
- protected final List tabComplete(T sender, String alias, String[] args) throws IllegalArgumentException {
- initialize();
- String string = args[args.length - 1].toLowerCase();
- return Stream.concat(commandList.stream(), helpCommandList.stream())
- .filter(s -> !s.noTabComplete)
- .map(s -> s.tabComplete(sender, args))
- .filter(Objects::nonNull)
- .flatMap(Collection::stream)
- .filter(s -> !s.isEmpty())
- .filter(s -> s.toLowerCase().startsWith(string) || string.startsWith(s.toLowerCase()))
- .distinct()
- .collect(Collectors.toList());
- }
-
- private synchronized void initialize() {
- if (initialized) return;
- List methods = methods().stream()
- .filter(this::validateMethod)
- .collect(Collectors.toList());
- for (Method method : methods) {
- Cached cached = method.getAnnotation(Cached.class);
- this.>add(Mapper.class, method, (anno, typeMapper) -> {
- TabCompletionCache.add(typeMapper, cached);
- (anno.local() ? ((Map) localTypeMapper) : SWCommandUtils.getMAPPER_FUNCTIONS()).put(anno.value(), typeMapper);
- });
- this.>add(ClassMapper.class, method, (anno, typeMapper) -> {
- TabCompletionCache.add(typeMapper, cached);
- (anno.local() ? ((Map) localTypeMapper) : SWCommandUtils.getMAPPER_FUNCTIONS()).put(anno.value().getName(), typeMapper);
- });
- this.>add(Validator.class, method, (anno, validator) -> {
- (anno.local() ? ((Map) localValidators) : SWCommandUtils.getVALIDATOR_FUNCTIONS()).put(anno.value(), validator);
- });
- this.>add(ClassValidator.class, method, (anno, validator) -> {
- (anno.local() ? ((Map) localValidators) : SWCommandUtils.getVALIDATOR_FUNCTIONS()).put(anno.value().getName(), validator);
- });
- }
- for (Method method : methods) {
- add(Register.class, method, true, (anno, parameters) -> {
- for (int i = 1; i < parameters.length; i++) {
- Parameter parameter = parameters[i];
- Class> clazz = parameter.getType();
- if (parameter.isVarArgs()) clazz = clazz.getComponentType();
- Mapper mapper = parameter.getAnnotation(Mapper.class);
- if (clazz.isEnum() && mapper == null && !SWCommandUtils.getMAPPER_FUNCTIONS().containsKey(clazz.getTypeName())) {
- continue;
- }
- String name = mapper != null ? mapper.value() : clazz.getTypeName();
- if (!SWCommandUtils.getMAPPER_FUNCTIONS().containsKey(name) && !localTypeMapper.containsKey(name)) {
- commandSystemWarning(() -> "The parameter '" + parameter.toString() + "' is using an unsupported Mapper of type '" + name + "'");
- return;
- }
- }
- commandList.add(new SubCommand<>(this, method, anno.value(), localTypeMapper, localValidators, anno.description(), anno.noTabComplete()));
- });
- }
-
- if (dependencyMap.containsKey(this.getClass())) {
- dependencyMap.get(this.getClass()).forEach(abstractSWCommand -> {
- abstractSWCommand.localTypeMapper.putAll((Map) localTypeMapper);
- abstractSWCommand.localValidators.putAll((Map) localValidators);
- abstractSWCommand.initialisePartOf(this);
- abstractSWCommand.initialize();
- commandList.addAll((Collection) abstractSWCommand.commandList);
- });
- }
-
- Collections.sort(commandList);
- commandList.removeIf(subCommand -> {
- if (subCommand.isHelp) {
- helpCommandList.add(subCommand);
- return true;
- } else {
- return false;
- }
- });
- initialized = true;
- }
-
- private boolean validateMethod(Method method) {
- if (!checkType(method.getAnnotations(), method.getReturnType(), false, annotation -> {
- CommandMetaData.Method methodMetaData = annotation.annotationType().getAnnotation(CommandMetaData.Method.class);
- if (methodMetaData == null) return (aClass, varArg) -> true;
- if (method.getParameterCount() > methodMetaData.maxParameterCount() || method.getParameterCount() < methodMetaData.minParameterCount())
- 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;
- boolean valid = true;
- for (Parameter parameter : method.getParameters()) {
- if (!checkType(parameter.getAnnotations(), parameter.getType(), parameter.isVarArgs(), annotation -> {
- CommandMetaData.Parameter parameterMetaData = annotation.annotationType().getAnnotation(CommandMetaData.Parameter.class);
- if (parameterMetaData == null) return (aClass, varArg) -> true;
- Class> handler = parameterMetaData.handler();
- if (BiPredicate.class.isAssignableFrom(handler)) {
- try {
- return (BiPredicate, 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;
- }
- return valid;
- }
-
- private boolean checkType(Annotation[] annotations, Class> clazz, boolean varArg, Function, Boolean>> toApplicableTypes, String warning) {
- boolean valid = true;
- for (Annotation annotation : annotations) {
- BiPredicate, Boolean> predicate = toApplicableTypes.apply(annotation);
- if (!predicate.test(clazz, varArg)) {
- commandSystemWarning(() -> warning + " is using an unsupported annotation of type '" + annotation.annotationType().getName() + "'");
- valid = false;
- }
- }
- return valid;
- }
-
- private void add(Class annotation, Method method, boolean firstParameter, BiConsumer consumer) {
- T[] anno = SWCommandUtils.getAnnotation(method, annotation);
- if (anno == null || anno.length == 0) return;
-
- Parameter[] parameters = method.getParameters();
- if (firstParameter && !clazz.isAssignableFrom(parameters[0].getType())) {
- commandSystemWarning(() -> "The method '" + method.toString() + "' is lacking the first parameter of type '" + clazz.getTypeName() + "'");
- return;
- }
- Arrays.stream(anno).forEach(t -> consumer.accept(t, parameters));
- }
-
- private void add(Class annotation, Method method, BiConsumer consumer) {
- add(annotation, method, false, (anno, parameters) -> {
- try {
- method.setAccessible(true);
- consumer.accept(anno, (K) method.invoke(this));
- } catch (Exception e) {
- throw new SecurityException(e.getMessage(), e);
- }
- });
- }
-
- // TODO: Implement this when Message System is ready
- /*
- public void addDefaultHelpMessage(String message) {
- defaultHelpMessages.add(message);
- }
- */
-
- private List methods() {
- List methods = new ArrayList<>();
- Class> current = getClass();
- while (current != AbstractSWCommand.class) {
- methods.addAll(Arrays.asList(current.getDeclaredMethods()));
- current = current.getSuperclass();
- }
- return methods;
- }
-
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.TYPE})
- public @interface PartOf {
- Class> value();
- }
-
- // --- Annotation for the command ---
-
- /**
- * Annotation for registering a method as a command
- */
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.METHOD})
- @Repeatable(Register.Registeres.class)
- @CommandMetaData.Method(value = void.class, minParameterCount = 1)
- protected @interface Register {
-
- /**
- * Identifier of subcommand
- */
- String[] value() default {};
-
- @Deprecated
- boolean help() default false;
-
- String[] description() default {};
-
- boolean noTabComplete() default false;
-
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.METHOD})
- @CommandMetaData.Method(value = void.class, minParameterCount = 1)
- @interface Registeres {
- Register[] value();
- }
- }
-
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.PARAMETER, ElementType.METHOD})
- @CommandMetaData.Method(value = AbstractTypeMapper.class, maxParameterCount = 0)
- @CommandMetaData.ImplicitTypeMapper(handler = Mapper.Handler.class)
- protected @interface Mapper {
- String value();
-
- boolean local() default false;
-
- class Handler implements AbstractTypeMapper {
-
- private AbstractTypeMapper inner;
-
- public Handler(AbstractSWCommand.Mapper mapper, Map> localTypeMapper) {
- inner = (AbstractTypeMapper) SWCommandUtils.getTypeMapper(mapper.value(), localTypeMapper);
- }
-
- @Override
- public Object map(T sender, PreviousArguments previousArguments, String s) {
- return inner.map(sender, previousArguments, s);
- }
-
- @Override
- public boolean validate(T sender, Object value, MessageSender messageSender) {
- return inner.validate(sender, value, messageSender);
- }
-
- @Override
- public Collection tabCompletes(T sender, PreviousArguments previousArguments, String s) {
- return inner.tabCompletes(sender, previousArguments, s);
- }
- }
- }
-
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.METHOD})
- @CommandMetaData.Method(value = AbstractTypeMapper.class, maxParameterCount = 0)
- protected @interface ClassMapper {
- Class> value();
-
- boolean local() default false;
- }
-
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.METHOD})
- @CommandMetaData.Method(value = AbstractTypeMapper.class, maxParameterCount = 0)
- protected @interface Cached {
- long cacheDuration() default 5;
-
- TimeUnit timeUnit() default TimeUnit.SECONDS;
-
- boolean global() default false;
- }
-
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.PARAMETER, ElementType.METHOD})
- @CommandMetaData.Method(value = AbstractValidator.class, maxParameterCount = 0)
- @CommandMetaData.ImplicitValidator(handler = Validator.Handler.class, order = 0)
- protected @interface Validator {
- String value() default "";
-
- boolean local() default false;
-
- boolean invert() default false;
-
- class Handler implements AbstractValidator {
-
- private AbstractValidator inner;
- private boolean invert;
-
- public Handler(AbstractSWCommand.Validator validator, Class> clazz, Map> localValidator) {
- inner = (AbstractValidator) SWCommandUtils.getValidator(validator, clazz, localValidator);
- invert = validator.invert();
- }
-
- @Override
- public boolean validate(T sender, Object value, MessageSender messageSender) {
- return inner.validate(sender, value, messageSender) ^ invert;
- }
- }
- }
-
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.METHOD})
- @CommandMetaData.Method(value = AbstractValidator.class, maxParameterCount = 0)
- protected @interface ClassValidator {
- Class> value();
-
- boolean local() default false;
- }
-
- // --- Implicit TypeMapper ---
-
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.PARAMETER})
- @CommandMetaData.Parameter({String.class, int.class, Integer.class, long.class, Long.class, boolean.class, Boolean.class})
- @CommandMetaData.ImplicitTypeMapper(handler = StaticValue.Handler.class)
- protected @interface StaticValue {
- String[] value();
-
- /**
- * This is the short form for 'allowImplicitSwitchExpressions'
- * and can be set to true if you want to allow int as well as boolean as annotated parameter types.
- * The value array needs to be at least 2 long for this flag to be considered.
- * While using an int, the value will represent the index into the value array.
- * While using a boolean, the {@link #falseValues()} defines which indices are
- * considered {@code false} or {@code true}.
- */
- boolean allowISE() default false;
-
- int[] falseValues() default {0};
-
- class Handler implements AbstractTypeMapper {
-
- private AbstractTypeMapper inner;
-
- public Handler(StaticValue staticValue, Class> clazz) {
- if (clazz == String.class) {
- inner = SWCommandUtils.createMapper(staticValue.value());
- return;
- }
- if (!staticValue.allowISE()) {
- throw new IllegalArgumentException("The parameter type '" + clazz.getTypeName() + "' is not supported by the StaticValue annotation");
- }
- if (clazz == boolean.class || clazz == Boolean.class) {
- List tabCompletes = new ArrayList<>(Arrays.asList(staticValue.value()));
- Set falseValues = new HashSet<>();
- for (int i : staticValue.falseValues()) falseValues.add(i);
- inner = SWCommandUtils.createMapper(s -> {
- int index = tabCompletes.indexOf(s);
- return index == -1 ? null : !falseValues.contains(index);
- }, (commandSender, s) -> tabCompletes);
- } else if (clazz == int.class || clazz == Integer.class || clazz == long.class || clazz == Long.class) {
- List tabCompletes = new ArrayList<>(Arrays.asList(staticValue.value()));
- inner = SWCommandUtils.createMapper(s -> {
- Number index = tabCompletes.indexOf(s);
- return index.longValue() == -1 ? null : index;
- }, (commandSender, s) -> tabCompletes);
- } else {
- throw new IllegalArgumentException("The parameter type '" + clazz.getTypeName() + "' is not supported by the StaticValue annotation");
- }
- }
-
- @Override
- public Object map(T sender, PreviousArguments previousArguments, String s) {
- return inner.map(sender, previousArguments, s);
- }
-
- @Override
- public Collection tabCompletes(T sender, PreviousArguments previousArguments, String s) {
- return inner.tabCompletes(sender, previousArguments, s);
- }
- }
- }
-
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.PARAMETER})
- protected @interface OptionalValue {
- /**
- * Will pe parsed against the TypeMapper specified by the parameter or annotation.
- */
- String value();
-
- /**
- * The method name stands for 'onlyUseIfNoneIsGiven'.
- */
- boolean onlyUINIG() default false;
- }
-
- // --- Implicit Validator ---
-
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.PARAMETER})
- @CommandMetaData.ImplicitValidator(handler = ErrorMessage.Handler.class, order = Integer.MAX_VALUE)
- protected @interface ErrorMessage {
- /**
- * Error message to be displayed when the parameter is invalid.
- */
- String value();
-
- /**
- * This is the short form for 'allowEmptyArrays'.
- */
- boolean allowEAs() default true;
-
- class Handler implements AbstractValidator {
-
- private AbstractSWCommand.ErrorMessage errorMessage;
-
- public Handler(AbstractSWCommand.ErrorMessage errorMessage) {
- this.errorMessage = errorMessage;
- }
-
- @Override
- public boolean validate(T sender, Object value, MessageSender messageSender) {
- if (value == null) messageSender.send(errorMessage.value());
- if (!errorMessage.allowEAs() && value != null && value.getClass().isArray() && Array.getLength(value) == 0) {
- messageSender.send(errorMessage.value());
- return false;
- }
- return value != null;
- }
- }
- }
-
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.PARAMETER})
- protected @interface AllowNull {
- }
-
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.PARAMETER})
- @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)
- protected @interface Min {
- int intValue() default Integer.MIN_VALUE;
-
- long longValue() default Long.MIN_VALUE;
-
- float floatValue() default Float.MIN_VALUE;
-
- double doubleValue() default Double.MIN_VALUE;
-
- boolean inclusive() default true;
-
- class Handler implements AbstractValidator {
-
- private int value;
- private Function comparator;
-
- public Handler(AbstractSWCommand.Min min, Class> clazz) {
- this.value = min.inclusive() ? 0 : 1;
- this.comparator = createComparator("Min", clazz, min.intValue(), min.longValue(), min.floatValue(), min.doubleValue());
- }
-
- @Override
- public boolean validate(T sender, Number value, MessageSender messageSender) {
- if (value == null) return true;
- return (comparator.apply(value).intValue()) >= this.value;
- }
- }
- }
-
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.PARAMETER})
- @CommandMetaData.Parameter({int.class, Integer.class, long.class, Long.class, float.class, Float.class, double.class, Double.class})
- @CommandMetaData.ImplicitValidator(handler = Max.Handler.class, order = 2)
- protected @interface Max {
- int intValue() default Integer.MAX_VALUE;
-
- long longValue() default Long.MAX_VALUE;
-
- float floatValue() default Float.MAX_VALUE;
-
- double doubleValue() default Double.MAX_VALUE;
-
- boolean inclusive() default true;
-
- class Handler implements AbstractValidator {
-
- private int value;
- private Function comparator;
-
- public Handler(AbstractSWCommand.Max max, Class> clazz) {
- this.value = max.inclusive() ? 0 : -1;
- this.comparator = createComparator("Max", clazz, max.intValue(), max.longValue(), max.floatValue(), max.doubleValue());
- }
-
- @Override
- public boolean validate(T sender, Number value, MessageSender messageSender) {
- if (value == null) return true;
- return (comparator.apply(value).intValue()) <= this.value;
- }
- }
- }
-
- private static Function createComparator(String type, Class> clazz, int iValue, long lValue, float fValue, double dValue) {
- if (clazz == int.class || clazz == Integer.class) {
- return number -> Integer.compare(number.intValue(), iValue);
- } else if (clazz == long.class || clazz == Long.class) {
- return number -> Long.compare(number.longValue(), lValue);
- } else if (clazz == float.class || clazz == Float.class) {
- return number -> Float.compare(number.floatValue(), fValue);
- } else if (clazz == double.class || clazz == Double.class) {
- return number -> Double.compare(number.doubleValue(), dValue);
- } else {
- 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 implements AbstractTypeMapper {
-
- private int min;
- private int max;
- private AbstractTypeMapper inner;
-
- public Handler(Length length, AbstractTypeMapper 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 tabCompletes(T sender, PreviousArguments previousArguments, String s) {
- List 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.ImplicitTypeMapper(handler = ArrayLength.HandlerTypeMapper.class)
- @CommandMetaData.ImplicitValidator(handler = ArrayLength.HandlerValidator.class, order = 1)
- protected @interface ArrayLength {
- int min() default 0;
-
- int max() default Integer.MAX_VALUE;
-
- class Type implements BiPredicate, Boolean> {
- @Override
- public boolean test(Class> clazz, Boolean isVarArgs) {
- return clazz.isArray();
- }
- }
-
- class HandlerTypeMapper implements AbstractTypeMapper {
-
- private int max;
- private AbstractTypeMapper inner;
-
- public HandlerTypeMapper(ArrayLength arrayLength, AbstractTypeMapper inner) {
- this.max = arrayLength.max();
- this.inner = inner;
- }
-
- @Override
- public Object map(T sender, PreviousArguments previousArguments, String s) {
- return inner.map(sender, previousArguments, s);
- }
-
- @Override
- public Collection tabCompletes(T sender, PreviousArguments previousArguments, String s) {
- Object[] mapped = previousArguments.getMappedArg(0);
- if (mapped.length >= max) return Collections.emptyList();
- return inner.tabCompletes(sender, previousArguments, s);
- }
-
- @Override
- public String normalize(T sender, String s) {
- return inner.normalize(sender, s);
- }
- }
-
- class HandlerValidator implements AbstractValidator {
-
- private int min;
- private int max;
-
- public HandlerValidator(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;
- }
- }
- }
-}
diff --git a/src/de/steamwar/command/AbstractTypeMapper.java b/src/de/steamwar/command/AbstractTypeMapper.java
deleted file mode 100644
index 040f303..0000000
--- a/src/de/steamwar/command/AbstractTypeMapper.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * This file is a part of the SteamWar software.
- *
- * Copyright (C) 2020 SteamWar.de-Serverteam
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package de.steamwar.command;
-
-import java.util.Collection;
-
-public interface AbstractTypeMapper extends AbstractValidator {
- /**
- * The CommandSender can be null!
- */
- @Deprecated
- default T map(K sender, String[] previousArguments, String s) {
- throw new IllegalArgumentException("This method is deprecated and should not be used anymore!");
- }
-
- /**
- * The CommandSender can be null!
- */
- default T map(K sender, PreviousArguments previousArguments, String s) {
- return map(sender, previousArguments.userArgs, s);
- }
-
- @Override
- default boolean validate(K sender, T value, MessageSender messageSender) {
- return true;
- }
-
- @Deprecated
- default Collection tabCompletes(K sender, String[] previousArguments, String s) {
- throw new IllegalArgumentException("This method is deprecated and should not be used anymore!");
- }
-
- default Collection tabCompletes(K sender, PreviousArguments previousArguments, String s) {
- return tabCompletes(sender, previousArguments.userArgs, s);
- }
-
- /**
- * Normalize the cache key by sender and user provided argument.
- * Note: The CommandSender can be null!
- * Returning null and the empty string are equivalent.
- */
- default String normalize(K sender, String s) {
- return null;
- }
-}
diff --git a/src/de/steamwar/command/AbstractValidator.java b/src/de/steamwar/command/AbstractValidator.java
deleted file mode 100644
index 7dc0b72..0000000
--- a/src/de/steamwar/command/AbstractValidator.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * This file is a part of the SteamWar software.
- *
- * Copyright (C) 2022 SteamWar.de-Serverteam
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package de.steamwar.command;
-
-import lombok.RequiredArgsConstructor;
-
-import java.util.function.BooleanSupplier;
-import java.util.function.Function;
-import java.util.function.Predicate;
-
-@FunctionalInterface
-public interface AbstractValidator {
-
- /**
- * Validates the given value.
- *
- * @param sender The sender of the command.
- * @param value The value to validate or null if mapping returned null.
- * @param messageSender The message sender to send messages to the player. Never send messages directly to the player.
- * @return The result of the validation.
- */
- boolean validate(K sender, T value, MessageSender messageSender);
-
- @Deprecated
- default Validator validate(C value, MessageSender messageSender) {
- return new Validator<>(value, messageSender);
- }
-
- @Deprecated
- @RequiredArgsConstructor
- class Validator {
- private final C value;
- private final MessageSender messageSender;
-
- private boolean valid = true;
-
- public Validator map(Function mapper) {
- return new Validator<>(mapper.apply(value), messageSender).set(valid);
- }
-
- public Validator set(boolean value) {
- this.valid = value;
- return this;
- }
-
- public Validator and(Predicate predicate) {
- valid &= predicate.test(value);
- return this;
- }
-
- public Validator or(Predicate predicate) {
- valid |= predicate.test(value);
- return this;
- }
-
- public Validator errorMessage(String s, Object... args) {
- if (!valid) messageSender.send(s, args);
- return this;
- }
-
- public boolean result() {
- return valid;
- }
- }
-
- @FunctionalInterface
- interface MessageSender {
- void send(String s, Object... args);
-
- default boolean send(boolean condition, String s, Object... args) {
- if (condition) send(s, args);
- return condition;
- }
-
- default boolean send(BooleanSupplier condition, String s, Object... args) {
- return send(condition.getAsBoolean(), s, args);
- }
- }
-}
diff --git a/src/de/steamwar/command/CommandFrameworkException.java b/src/de/steamwar/command/CommandFrameworkException.java
deleted file mode 100644
index ea3d835..0000000
--- a/src/de/steamwar/command/CommandFrameworkException.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * This file is a part of the SteamWar software.
- *
- * Copyright (C) 2020 SteamWar.de-Serverteam
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package de.steamwar.command;
-
-import java.io.PrintStream;
-import java.io.PrintWriter;
-import java.lang.reflect.Executable;
-import java.lang.reflect.InvocationTargetException;
-import java.util.Arrays;
-import java.util.function.Function;
-import java.util.stream.Stream;
-
-public class CommandFrameworkException extends RuntimeException {
-
- private Function causeMessage;
- private Throwable cause;
- private Function stackTraceExtractor;
- private String extraStackTraces;
-
- private String message;
-
- static CommandFrameworkException commandPartExceptions(String type, Throwable cause, String current, Class> clazzType, Executable executable, int index) {
- return new CommandFrameworkException(e -> {
- return CommandFrameworkException.class.getTypeName() + ": Error while " + type + " (" + current + ") to type " + clazzType.getTypeName() + " with parameter index " + index;
- }, cause, exception -> {
- StackTraceElement[] stackTraceElements = exception.getStackTrace();
- int last = 0;
- for (int i = 0; i < stackTraceElements.length; i++) {
- if (stackTraceElements[i].getClassName().equals(CommandPart.class.getTypeName())) {
- last = i;
- break;
- }
- }
- return Arrays.stream(stackTraceElements).limit(last - 1);
- }, executable.getDeclaringClass().getTypeName() + "." + executable.getName() + "(Unknown Source)");
- }
-
- CommandFrameworkException(InvocationTargetException invocationTargetException, String alias, String[] args) {
- this(e -> {
- StringBuilder st = new StringBuilder();
- st.append(e.getCause().getClass().getTypeName());
- if (e.getCause().getMessage() != null) {
- st.append(": ").append(e.getCause().getMessage());
- }
- if (alias != null && !alias.isEmpty()) {
- st.append("\n").append("Performed command: " + alias + " " + String.join(" ", args));
- }
- return st.toString();
- }, invocationTargetException, e -> {
- StackTraceElement[] stackTraceElements = e.getCause().getStackTrace();
- return Arrays.stream(stackTraceElements).limit(stackTraceElements.length - e.getStackTrace().length);
- }, null);
- }
-
- private CommandFrameworkException(Function causeMessage, T cause, Function> stackTraceExtractor, String extraStackTraces) {
- super(causeMessage.apply(cause), cause);
- this.causeMessage = causeMessage;
- this.cause = cause;
- this.stackTraceExtractor = stackTraceExtractor;
- this.extraStackTraces = extraStackTraces;
- }
-
- public synchronized String getBuildStackTrace() {
- if (message != null) {
- return message;
- }
- StringBuilder st = new StringBuilder();
- st.append(causeMessage.apply(cause)).append("\n");
- ((Stream) stackTraceExtractor.apply(cause)).forEach(stackTraceElement -> {
- st.append("\tat ").append(stackTraceElement.toString()).append("\n");
- });
- if (extraStackTraces != null) {
- st.append("\tat ").append(extraStackTraces).append("\n");
- }
- message = st.toString();
- return message;
- }
-
- @Override
- public void printStackTrace() {
- printStackTrace(System.err);
- }
-
- @Override
- public void printStackTrace(PrintStream s) {
- s.print(getBuildStackTrace());
- }
-
- @Override
- public void printStackTrace(PrintWriter s) {
- s.print(getBuildStackTrace());
- }
-}
diff --git a/src/de/steamwar/command/CommandMetaData.java b/src/de/steamwar/command/CommandMetaData.java
deleted file mode 100644
index 33909ac..0000000
--- a/src/de/steamwar/command/CommandMetaData.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * This file is a part of the SteamWar software.
- *
- * Copyright (C) 2022 SteamWar.de-Serverteam
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package de.steamwar.command;
-
-import java.lang.annotation.*;
-
-public @interface CommandMetaData {
-
- /**
- * This annotation is only for internal use.
- */
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.ANNOTATION_TYPE)
- @interface Method {
- Class>[] value();
- int minParameterCount() default 0;
- int maxParameterCount() default Integer.MAX_VALUE;
- }
-
- /**
- * This annotation denotes what types are allowed as parameter types the annotation annotated with can use.
- */
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.ANNOTATION_TYPE)
- @interface Parameter {
- Class>[] value() default {};
- Class> handler() default void.class;
- }
-
- /**
- * This annotation can be used in conjunction with a class that implements {@link AbstractTypeMapper} to
- * create a custom type mapper for a parameter. The class must have one of two constructors with the following
- * types:
- *
- *
Annotation this annotation annotates
- *
{@link Class}
- *
{@link AbstractTypeMapper}, optional, if not present only one per parameter
- *
{@link java.util.Map} with types {@link String} and {@link AbstractValidator}
- *
- */
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.ANNOTATION_TYPE)
- @interface ImplicitTypeMapper {
- /**
- * The validator class that should be used.
- */
- Class> handler();
- }
-
- /**
- * This annotation can be used in conjunction with a class that implements {@link AbstractValidator} to
- * create a custom validator short hands for commands. The validator class must have one constructor with
- * one of the following types:
- *
- *
Annotation this annotation annotates
- *
{@link Class}
- *
{@link java.util.Map} with types {@link String} and {@link AbstractValidator}
- *
- */
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.ANNOTATION_TYPE)
- @interface ImplicitValidator {
- /**
- * The validator class that should be used.
- */
- Class> handler();
-
- /**
- * Defines when this validator should be processed. Negative numbers denote that this will be
- * processed before {@link AbstractSWCommand.Validator} and positive numbers
- * denote that this will be processed after {@link AbstractSWCommand.Validator}.
- */
- int order();
- }
-}
diff --git a/src/de/steamwar/command/CommandParseException.java b/src/de/steamwar/command/CommandParseException.java
deleted file mode 100644
index 3d81ea6..0000000
--- a/src/de/steamwar/command/CommandParseException.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * This file is a part of the SteamWar software.
- *
- * Copyright (C) 2020 SteamWar.de-Serverteam
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package de.steamwar.command;
-
-public class CommandParseException extends RuntimeException {
-
- public CommandParseException() {
- }
-}
diff --git a/src/de/steamwar/command/CommandPart.java b/src/de/steamwar/command/CommandPart.java
deleted file mode 100644
index 02991b4..0000000
--- a/src/de/steamwar/command/CommandPart.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * This file is a part of the SteamWar software.
- *
- * Copyright (C) 2020 SteamWar.de-Serverteam
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package de.steamwar.command;
-
-import lombok.AllArgsConstructor;
-import lombok.Setter;
-
-import java.lang.reflect.Array;
-import java.lang.reflect.Parameter;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.function.Consumer;
-
-class CommandPart {
-
- private static final String[] EMPTY_STRING_ARRAY = new String[0];
- private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
-
- @AllArgsConstructor
- private static class CheckArgumentResult {
- private final boolean success;
- private final Object value;
- }
-
- private AbstractSWCommand command;
- private AbstractTypeMapper typeMapper;
- private List> validators = new ArrayList<>();
- private Class> varArgType;
- private String optional;
-
- private CommandPart next = null;
-
- @Setter
- private boolean ignoreAsArgument = false;
-
- @Setter
- private boolean onlyUseIfNoneIsGiven = false;
-
- private Parameter parameter;
- private int parameterIndex;
-
- public CommandPart(AbstractSWCommand command, AbstractTypeMapper typeMapper, Class> varArgType, String optional, Parameter parameter, int parameterIndex) {
- this.command = command;
- this.typeMapper = typeMapper;
- this.varArgType = varArgType;
- this.optional = optional;
- this.parameter = parameter;
- this.parameterIndex = parameterIndex;
-
- if (optional != null && varArgType != null) {
- throw new IllegalArgumentException("A vararg part can't have an optional part! In method " + parameter.getDeclaringExecutable() + " with parameter " + parameterIndex);
- }
- }
-
- void addValidator(AbstractValidator validator) {
- if (validator == null) return;
- validators.add(validator);
- }
-
- public void setNext(CommandPart next) {
- if (varArgType != null) {
- throw new IllegalArgumentException("There can't be a next part if this is a vararg part! In method " + parameter.getDeclaringExecutable() + " with parameter " + parameterIndex);
- }
- this.next = next;
- }
-
- public boolean isHelp() {
- if (next == null) {
- if (varArgType == null) {
- return false;
- }
- if (varArgType != String.class) {
- return false;
- }
- return typeMapper == SWCommandUtils.STRING_MAPPER;
- } else {
- return next.isHelp();
- }
- }
-
- public void generateArgumentArray(Consumer errors, List