forked from SteamWar/SteamWar
Initial copy from other repository (nothing is fixed here)
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.command;
|
||||
|
||||
import de.steamwar.command.mapper.BooleanMapper;
|
||||
import de.steamwar.command.mapper.NumberMapper;
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.annotation.Repeatable;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.function.ToIntFunction;
|
||||
|
||||
@UtilityClass
|
||||
public class CommandUtils {
|
||||
|
||||
final Map<String, AbstractTypeMapper<?, ?>> MAPPER_FUNCTIONS = new HashMap<>();
|
||||
|
||||
final Map<String, AbstractTypeValidator<?, ?>> VALIDATOR_FUNCTIONS = new HashMap<>();
|
||||
|
||||
final Map<String, AbstractTypeSupplier<?, ?>> SUPPLIER_FUNCTIONS = new HashMap<>();
|
||||
|
||||
static final AbstractTypeMapper<Object, String> STRING_MAPPER = new AbstractTypeMapper<>() {
|
||||
@Override
|
||||
public String map(Object sender, PreviousArguments previousArguments, String s) {
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> tabComplete(Object sender, PreviousArguments previousArguments, String s) {
|
||||
return Collections.singletonList(s);
|
||||
}
|
||||
};
|
||||
|
||||
static {
|
||||
addMapper(boolean.class, Boolean.class, new BooleanMapper());
|
||||
addMapper(int.class, Integer.class, new NumberMapper(Integer::parseInt, false));
|
||||
addMapper(long.class, Long.class, new NumberMapper(Long::parseLong, false));
|
||||
addMapper(float.class, Float.class, new NumberMapper(Float::parseFloat, true));
|
||||
addMapper(double.class, Double.class, new NumberMapper(Double::parseDouble, true));
|
||||
MAPPER_FUNCTIONS.put(String.class.getTypeName(), STRING_MAPPER);
|
||||
}
|
||||
|
||||
private static void addMapper(Class<?> clazz, Class<?> alternativeClazz, AbstractTypeMapper<?, ?> mapper) {
|
||||
MAPPER_FUNCTIONS.put(clazz.getTypeName(), mapper);
|
||||
MAPPER_FUNCTIONS.put(alternativeClazz.getTypeName(), mapper);
|
||||
}
|
||||
|
||||
public static <K, T> void addMapper(Class<T> clazz, AbstractTypeMapper<K, T> mapper) {
|
||||
addMapper(clazz.getTypeName(), mapper);
|
||||
}
|
||||
|
||||
public static <T> void addMapper(String name, AbstractTypeMapper<T, ?> mapper) {
|
||||
MAPPER_FUNCTIONS.putIfAbsent(name, mapper);
|
||||
}
|
||||
|
||||
public static <T> void addValidator(Class<T> clazz, AbstractTypeValidator<T, ?> validator) {
|
||||
addValidator(clazz.getTypeName(), validator);
|
||||
}
|
||||
|
||||
public static <T> void addValidator(String name, AbstractTypeValidator<T, ?> validator) {
|
||||
VALIDATOR_FUNCTIONS.putIfAbsent(name, validator);
|
||||
}
|
||||
|
||||
public static <T> void addSupplier(Class<T> clazz, AbstractTypeSupplier<T, ?> supplier) {
|
||||
addSupplier(clazz.getTypeName(), supplier);
|
||||
}
|
||||
|
||||
public static <T> void addSupplier(String name, AbstractTypeSupplier<T, ?> supplier) {
|
||||
SUPPLIER_FUNCTIONS.putIfAbsent(name, supplier);
|
||||
}
|
||||
|
||||
public static List<Annotation> getAnnotations(AnnotatedElement annotatedElement) {
|
||||
List<Annotation> annotationList = new ArrayList<>();
|
||||
for (Annotation annotation : annotatedElement.getAnnotations()) {
|
||||
try {
|
||||
Method method = annotation.annotationType().getMethod("value");
|
||||
Class<?> returnType = method.getReturnType();
|
||||
if (!returnType.isArray()) {
|
||||
annotationList.add(annotation);
|
||||
continue;
|
||||
}
|
||||
Class<?> innerReturnType = returnType.getComponentType();
|
||||
if (!(innerReturnType.isAnnotation() && innerReturnType.isAnnotationPresent(Repeatable.class))) {
|
||||
annotationList.add(annotation);
|
||||
continue;
|
||||
}
|
||||
Repeatable repeatable = innerReturnType.getAnnotation(Repeatable.class);
|
||||
Class<? extends Annotation> containerType = repeatable.value();
|
||||
if (containerType == returnType) {
|
||||
throw new UnsupportedOperationException("Repeatable annotation must have a container annotation");
|
||||
}
|
||||
try {
|
||||
Annotation[] innerAnnotations = (Annotation[]) method.invoke(annotation);
|
||||
Collections.addAll(annotationList, innerAnnotations);
|
||||
} catch (Exception e) {
|
||||
annotationList.add(annotation);
|
||||
}
|
||||
} catch (NoSuchMethodException e) {
|
||||
annotationList.add(annotation);
|
||||
}
|
||||
}
|
||||
annotationList.removeIf(anno -> !anno.annotationType().isAnnotationPresent(Handler.Implementation.class));
|
||||
return annotationList;
|
||||
}
|
||||
|
||||
public static <T extends Handler> List<Annotation> getAnnotations(AnnotatedElement annotatedElement, Class<T> type) {
|
||||
List<Annotation> annotations = getAnnotations(annotatedElement);
|
||||
annotations.removeIf(annotation -> {
|
||||
Handler.Implementation implementation = annotation.annotationType().getAnnotation(Handler.Implementation.class);
|
||||
return implementation == null || !type.isAssignableFrom(implementation.value());
|
||||
});
|
||||
return annotations;
|
||||
}
|
||||
|
||||
public static ToIntFunction<Number> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user