diff --git a/CommandFramework/CommandFrameworkAnnotationProcessor/build.gradle.kts b/CommandFramework/CommandFrameworkAnnotationProcessor/build.gradle.kts
new file mode 100644
index 00000000..c0457098
--- /dev/null
+++ b/CommandFramework/CommandFrameworkAnnotationProcessor/build.gradle.kts
@@ -0,0 +1,32 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2024 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 .
+ */
+
+plugins {
+ steamwar.java
+}
+
+java {
+ sourceCompatibility = JavaVersion.VERSION_11
+ targetCompatibility = JavaVersion.VERSION_11
+}
+
+dependencies {
+ implementation(project(":CommandFramework:CommandFrameworkBase", "default"))
+ annotationProcessor(project(":CommandFramework:CommandFrameworkBase", "default"))
+}
\ No newline at end of file
diff --git a/CommandFramework/CommandFrameworkAnnotationProcessor/src/META-INF/services/javax.annotation.processing.Processor b/CommandFramework/CommandFrameworkAnnotationProcessor/src/META-INF/services/javax.annotation.processing.Processor
new file mode 100644
index 00000000..a8e2a61b
--- /dev/null
+++ b/CommandFramework/CommandFrameworkAnnotationProcessor/src/META-INF/services/javax.annotation.processing.Processor
@@ -0,0 +1,5 @@
+de.steamwar.command.annotationprocessor.impl.CachedAnnotationProcessor
+de.steamwar.command.annotationprocessor.impl.MapperAnnotationProcessor
+de.steamwar.command.annotationprocessor.impl.RegisterAnnotationProcessor
+de.steamwar.command.annotationprocessor.impl.SupplierAnnotationProcessor
+de.steamwar.command.annotationprocessor.impl.ValidatorAnnotationProcessor
\ No newline at end of file
diff --git a/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/HandlerForExecutableElement.java b/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/HandlerForExecutableElement.java
new file mode 100644
index 00000000..5810b2bf
--- /dev/null
+++ b/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/HandlerForExecutableElement.java
@@ -0,0 +1,65 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2025 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 javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.Types;
+import java.util.List;
+
+public class HandlerForExecutableElement implements Handler.MethodWrapper {
+
+ private final ExecutableElement method;
+ private final Types types;
+ private final Elements elements;
+
+ public HandlerForExecutableElement(ExecutableElement method, Types types, Elements elements) {
+ this.method = method;
+ this.types = types;
+ this.elements = elements;
+ }
+
+ @Override
+ public String getName() {
+ return method.getSimpleName().toString();
+ }
+
+ @Override
+ public int getParameterCount() {
+ return method.getParameters().size();
+ }
+
+ @Override
+ public Handler.TypeWrapper getReturnType() {
+ return new HandlerForTypeMirror(method.getReturnType(), types, elements);
+ }
+
+ @Override
+ public Handler.ParameterWrapper[] getParameters() {
+ Handler.ParameterWrapper[] parameters = new Handler.ParameterWrapper[method.getParameters().size()];
+ List extends VariableElement> variableElements = method.getParameters();
+ for (int i = 0; i < parameters.length; i++) {
+ VariableElement variableElement = variableElements.get(i);
+ parameters[i] = new HandlerForVariableElement(variableElement, types, elements, i == parameters.length - 1 && method.isVarArgs());
+ }
+ return parameters;
+ }
+}
diff --git a/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/HandlerForTypeMirror.java b/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/HandlerForTypeMirror.java
new file mode 100644
index 00000000..d5622056
--- /dev/null
+++ b/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/HandlerForTypeMirror.java
@@ -0,0 +1,107 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2025 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 javax.lang.model.type.ArrayType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.Types;
+
+public class HandlerForTypeMirror implements Handler.TypeWrapper {
+
+ private final TypeMirror type;
+ private final Types types;
+ private final Elements elements;
+
+ public HandlerForTypeMirror(TypeMirror type, Types types, Elements elements) {
+ this.type = type;
+ this.types = types;
+ this.elements = elements;
+ }
+
+ @Override
+ public boolean isAssignableTo(Class> clazz) {
+ return types.isAssignable(types.erasure(type), types.erasure(elements.getTypeElement(clazz.getTypeName()).asType()));
+ }
+
+ @Override
+ public boolean isAssignableTo(Handler.TypeWrapper type) {
+ if (type instanceof ForClass) {
+ return isAssignableTo(((ForClass) type).getClazz());
+ } else if (type instanceof HandlerForTypeMirror) {
+ return types.isAssignable(types.erasure(this.type), types.erasure(((HandlerForTypeMirror) type).type));
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isPrimitive() {
+ return type.getKind().isPrimitive();
+ }
+
+ @Override
+ public boolean isArray() {
+ return type instanceof ArrayType;
+ }
+
+ @Override
+ public boolean isEnum() {
+ System.out.println(type);
+ return false;
+ }
+
+ @Override
+ public boolean is(Class> clazz) {
+ if (type.getKind() == TypeKind.VOID && clazz == Void.TYPE) {
+ return true;
+ } else if (type.getKind().isPrimitive() && clazz.isPrimitive()) {
+ return type.toString().equals(clazz.getTypeName());
+ } else if (!type.getKind().isPrimitive() && !clazz.isPrimitive()) {
+ return types.isSameType(types.erasure(type), types.erasure(elements.getTypeElement(clazz.getTypeName()).asType()));
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public boolean is(Handler.TypeWrapper type) {
+ if (type instanceof ForClass) {
+ return is(((ForClass) type).getClazz());
+ } else if (type instanceof HandlerForTypeMirror) {
+ return types.isSameType(types.erasure(this.type), types.erasure(((HandlerForTypeMirror) type).type));
+ }
+ return false;
+ }
+
+ @Override
+ public Handler.TypeWrapper getComponentType() {
+ if (type instanceof ArrayType) {
+ return new HandlerForTypeMirror(((ArrayType) type).getComponentType(), types, elements);
+ } else {
+ return new HandlerForTypeMirror(null, types, elements);
+ }
+ }
+
+ @Override
+ public String getName() {
+ return type.toString();
+ }
+}
diff --git a/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/HandlerForVariableElement.java b/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/HandlerForVariableElement.java
new file mode 100644
index 00000000..abc670fa
--- /dev/null
+++ b/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/HandlerForVariableElement.java
@@ -0,0 +1,77 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2025 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 de.steamwar.command.handler.RegisterHandler;
+
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.Types;
+import java.lang.annotation.Annotation;
+import java.util.Collections;
+import java.util.List;
+
+public class HandlerForVariableElement implements Handler.ParameterWrapper {
+
+ private final VariableElement parameter;
+ private final Types types;
+ private final Elements elements;
+ private final boolean varArgs;
+
+ public HandlerForVariableElement(VariableElement variableElement, Types types, Elements elements, boolean varArgs) {
+ this.parameter = variableElement;
+ this.types = types;
+ this.elements = elements;
+ this.varArgs = varArgs;
+ }
+
+ @Override
+ public Handler.TypeWrapper getType() {
+ return new HandlerForTypeMirror(parameter.asType(), types, elements);
+ }
+
+ @Override
+ public boolean isVarArgs() {
+ return varArgs;
+ }
+
+ @Override
+ public boolean isAnnotationPresent(Class extends Annotation> annotation) {
+ return parameter.getAnnotation(annotation) != null;
+ }
+
+ @Override
+ public A getAnnotation(Class annotation) {
+ return parameter.getAnnotation(annotation);
+ }
+
+ @Override
+ public String getName() {
+ return parameter.getSimpleName().toString();
+ }
+
+ @Override
+ public List getAnnotations() {
+ parameter.getAnnotationMirrors().forEach(annotationMirror -> {
+ System.out.println(annotationMirror);
+ });
+ return Collections.emptyList();
+ }
+}
diff --git a/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/annotationprocessor/AbstractAnnotationProcessor.java b/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/annotationprocessor/AbstractAnnotationProcessor.java
new file mode 100644
index 00000000..e0dfbab9
--- /dev/null
+++ b/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/annotationprocessor/AbstractAnnotationProcessor.java
@@ -0,0 +1,176 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2025 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.annotationprocessor;
+
+import de.steamwar.command.Handler;
+import de.steamwar.command.HandlerForExecutableElement;
+import de.steamwar.command.HandlerForVariableElement;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.Messager;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.RoundEnvironment;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.*;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.Types;
+import javax.tools.Diagnostic;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public abstract class AbstractAnnotationProcessor extends AbstractProcessor {
+
+ private Messager messager;
+ private Types types;
+ private Elements elements;
+
+ public abstract Class extends Annotation> getAnnotationClass();
+
+ @Override
+ public synchronized void init(ProcessingEnvironment processingEnv) {
+ super.init(processingEnv);
+ this.messager = processingEnv.getMessager();
+ this.types = processingEnv.getTypeUtils();
+ this.elements = processingEnv.getElementUtils();
+ }
+
+ @Override
+ public Set getSupportedAnnotationTypes() {
+ return Collections.singleton(this.getAnnotationClass().getCanonicalName());
+ }
+
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latestSupported();
+ }
+
+ @Override
+ public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ List elements = roundEnv.getElementsAnnotatedWith(getAnnotationClass())
+ .stream()
+ .filter(element -> element.getKind() == ElementKind.METHOD)
+ .map(ExecutableElement.class::cast)
+ .collect(Collectors.toList());
+ if (elements.isEmpty()) return false;
+ elements.forEach(element -> {
+ checkMethodAnnotation(element, element.getAnnotation(getAnnotationClass()));
+
+ List extends VariableElement> parameters = element.getParameters();
+ for (int index = 0; index < parameters.size(); index++) {
+ VariableElement parameter = parameters.get(index);
+ for (AnnotationMirror annotationMirror : parameter.getAnnotationMirrors()) {
+ Class> clazz = getClass(annotationMirror.getAnnotationType().toString());
+ if (clazz == null) return;
+ checkParameterAnnotation(element, parameter, index, parameter.getAnnotation((Class extends Annotation>) clazz));
+ }
+ }
+ });
+ return false;
+ }
+
+ private Class> getClass(String name) {
+ try {
+ return Class.forName(name);
+ } catch (ClassNotFoundException e) {
+ // Ignore
+ }
+ if (!name.contains(".")) return null;
+ Class> outerClass = getClass(name.substring(0, name.lastIndexOf('.')));
+ if (outerClass == null) return null;
+ name = name.substring(name.lastIndexOf('.') + 1);
+ for (Class> declaredClass : outerClass.getDeclaredClasses()) {
+ if (declaredClass.getSimpleName().equals(name)) {
+ return declaredClass;
+ }
+ }
+ return null;
+ }
+
+ private Handler getHandler(Annotation annotation, Element element) {
+ Handler.Implementation implementation = annotation.annotationType().getAnnotation(Handler.Implementation.class);
+ if (implementation == null) return null;
+ try {
+ return implementation.value().getConstructor().newInstance();
+ } catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
+ InvocationTargetException e) {
+ messager.printMessage(Diagnostic.Kind.ERROR, "Handler " + implementation.value().getName() + " cannot be used to check the argument validity", element);
+ return null;
+ }
+ }
+
+ private void checkMethodAnnotation(ExecutableElement method, Annotation annotation) {
+ Handler handler = getHandler(annotation, method);
+ if (handler == null) return;
+ if (!(handler instanceof Handler.HandlerMethod)) {
+ messager.printMessage(Diagnostic.Kind.ERROR, "Handler " + handler.getClass().getName() + " is not a HandlerMethod", method);
+ return;
+ }
+ Handler.HandlerMethod handlerMethod = (Handler.HandlerMethod) handler;
+ try {
+ handlerMethod.check(annotation, new HandlerForExecutableElement(method, types, elements), DataCheckableImpl.INSTANCE);
+ } catch (Handler.HandlerException e) {
+ messager.printMessage(Diagnostic.Kind.ERROR, e.getMessage(), method);
+ }
+ }
+
+ private void checkParameterAnnotation(ExecutableElement method, VariableElement parameter, int index, Annotation annotation) {
+ Handler handler = getHandler(annotation, parameter);
+ if (handler == null) return;
+ if (!(handler instanceof Handler.HandlerParameter)) {
+ messager.printMessage(Diagnostic.Kind.ERROR, "Handler " + handler.getClass().getName() + " is not a HandlerParameter", method);
+ return;
+ }
+ Handler.HandlerParameter handlerParameter = (Handler.HandlerParameter) handler;
+ try {
+ handlerParameter.check(annotation, new HandlerForExecutableElement(method, types, elements), new HandlerForVariableElement(parameter, types, elements, index == method.getParameters().size() - 1 && method.isVarArgs()), index, DataCheckableImpl.INSTANCE);
+ } catch (Handler.HandlerException e) {
+ messager.printMessage(Diagnostic.Kind.ERROR, e.getMessage(), parameter);
+ }
+ }
+
+ private static final class DataCheckableImpl implements Handler.DataCheckable {
+
+ private static final DataCheckableImpl INSTANCE = new DataCheckableImpl();
+
+ @Override
+ public boolean hasExecutorMapper(Class> clazz) {
+ return true;
+ }
+
+ @Override
+ public boolean hasMapper(String key) {
+ return true;
+ }
+
+ @Override
+ public boolean hasValidator(String key) {
+ return true;
+ }
+
+ @Override
+ public boolean hasSupplier(String key) {
+ return true;
+ }
+ }
+}
diff --git a/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/annotationprocessor/impl/CachedAnnotationProcessor.java b/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/annotationprocessor/impl/CachedAnnotationProcessor.java
new file mode 100644
index 00000000..8c82c418
--- /dev/null
+++ b/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/annotationprocessor/impl/CachedAnnotationProcessor.java
@@ -0,0 +1,33 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2025 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.annotationprocessor.impl;
+
+import de.steamwar.command.annotationprocessor.AbstractAnnotationProcessor;
+import de.steamwar.command.annotations.Cached;
+
+import java.lang.annotation.Annotation;
+
+public class CachedAnnotationProcessor extends AbstractAnnotationProcessor {
+
+ @Override
+ public Class extends Annotation> getAnnotationClass() {
+ return Cached.class;
+ }
+}
diff --git a/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/annotationprocessor/impl/MapperAnnotationProcessor.java b/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/annotationprocessor/impl/MapperAnnotationProcessor.java
new file mode 100644
index 00000000..02f24506
--- /dev/null
+++ b/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/annotationprocessor/impl/MapperAnnotationProcessor.java
@@ -0,0 +1,33 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2025 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.annotationprocessor.impl;
+
+import de.steamwar.command.annotationprocessor.AbstractAnnotationProcessor;
+import de.steamwar.command.annotations.Mapper;
+
+import java.lang.annotation.Annotation;
+
+public class MapperAnnotationProcessor extends AbstractAnnotationProcessor {
+
+ @Override
+ public Class extends Annotation> getAnnotationClass() {
+ return Mapper.class;
+ }
+}
diff --git a/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/annotationprocessor/impl/RegisterAnnotationProcessor.java b/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/annotationprocessor/impl/RegisterAnnotationProcessor.java
new file mode 100644
index 00000000..b25c06b3
--- /dev/null
+++ b/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/annotationprocessor/impl/RegisterAnnotationProcessor.java
@@ -0,0 +1,33 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2025 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.annotationprocessor.impl;
+
+import de.steamwar.command.annotationprocessor.AbstractAnnotationProcessor;
+import de.steamwar.command.annotations.Register;
+
+import java.lang.annotation.Annotation;
+
+public class RegisterAnnotationProcessor extends AbstractAnnotationProcessor {
+
+ @Override
+ public Class extends Annotation> getAnnotationClass() {
+ return Register.class;
+ }
+}
diff --git a/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/annotationprocessor/impl/SupplierAnnotationProcessor.java b/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/annotationprocessor/impl/SupplierAnnotationProcessor.java
new file mode 100644
index 00000000..844c33d0
--- /dev/null
+++ b/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/annotationprocessor/impl/SupplierAnnotationProcessor.java
@@ -0,0 +1,33 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2025 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.annotationprocessor.impl;
+
+import de.steamwar.command.annotationprocessor.AbstractAnnotationProcessor;
+import de.steamwar.command.annotations.Supplier;
+
+import java.lang.annotation.Annotation;
+
+public class SupplierAnnotationProcessor extends AbstractAnnotationProcessor {
+
+ @Override
+ public Class extends Annotation> getAnnotationClass() {
+ return Supplier.class;
+ }
+}
diff --git a/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/annotationprocessor/impl/ValidatorAnnotationProcessor.java b/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/annotationprocessor/impl/ValidatorAnnotationProcessor.java
new file mode 100644
index 00000000..1526c49c
--- /dev/null
+++ b/CommandFramework/CommandFrameworkAnnotationProcessor/src/de/steamwar/command/annotationprocessor/impl/ValidatorAnnotationProcessor.java
@@ -0,0 +1,33 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2025 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.annotationprocessor.impl;
+
+import de.steamwar.command.annotationprocessor.AbstractAnnotationProcessor;
+import de.steamwar.command.annotations.Validator;
+
+import java.lang.annotation.Annotation;
+
+public class ValidatorAnnotationProcessor extends AbstractAnnotationProcessor {
+
+ @Override
+ public Class extends Annotation> getAnnotationClass() {
+ return Validator.class;
+ }
+}
diff --git a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/CommandUtils.java b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/CommandUtils.java
index be9dc2e0..b72bd936 100644
--- a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/CommandUtils.java
+++ b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/CommandUtils.java
@@ -132,14 +132,14 @@ public class CommandUtils {
return annotations;
}
- public static ToIntFunction createComparator(String type, Class> clazz, int iValue, long lValue, float fValue, double dValue) {
- if (clazz == int.class || clazz == Integer.class) {
+ public static ToIntFunction createComparator(String type, Handler.TypeWrapper clazz, int iValue, long lValue, float fValue, double dValue) {
+ if (clazz.is(int.class) || clazz.is(Integer.class)) {
return number -> Integer.compare(number.intValue(), iValue);
- } else if (clazz == long.class || clazz == Long.class) {
+ } else if (clazz.is(long.class) || clazz.is(Long.class)) {
return number -> Long.compare(number.longValue(), lValue);
- } else if (clazz == float.class || clazz == Float.class) {
+ } else if (clazz.is(float.class) || clazz.is(Float.class)) {
return number -> Float.compare(number.floatValue(), fValue);
- } else if (clazz == double.class || clazz == Double.class) {
+ } else if (clazz.is(double.class) || clazz.is(Double.class)) {
return number -> Double.compare(number.doubleValue(), dValue);
} else {
throw new IllegalArgumentException(type + " annotation is not supported for " + clazz);
diff --git a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/Handler.java b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/Handler.java
index 667c0375..5529af6e 100644
--- a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/Handler.java
+++ b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/Handler.java
@@ -19,11 +19,15 @@
package de.steamwar.command;
+import lombok.Getter;
+
import java.lang.annotation.*;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.List;
import java.util.Optional;
import java.util.function.Function;
@@ -58,17 +62,29 @@ public interface Handler {
Class extends Handler> value();
}
+ class HandlerException extends Exception {
+ public HandlerException(String message) {
+ super(message);
+ }
+ }
+
interface DataCheckable {
boolean hasExecutorMapper(Class> clazz);
+
boolean hasMapper(String key);
+
boolean hasValidator(String key);
+
boolean hasSupplier(String key);
}
interface DataReadable {
Function, ?> getExecutorMapper(Class> clazz);
+
AbstractTypeMapper getMapper(String key);
+
AbstractTypeValidator getValidator(String key);
+
AbstractTypeSupplier getSupplier(String key);
}
@@ -76,17 +92,26 @@ public interface Handler {
Function, ?> getExecutorMapper(Class> clazz);
void addMapper(String key, boolean local, AbstractTypeMapper mapper);
+
void addValidator(String key, boolean local, AbstractTypeValidator validator);
+
void addSupplier(String key, boolean local, AbstractTypeSupplier supplier);
+
/**
* Invoking the same method twice will result in the exact same result.
*/
T invoke(Method method);
+
void addCommand(Method method, String[] subCommand, String[] description, boolean noTabComplete);
}
interface HandlerMethod extends Handler {
- void check(T annotation, Method method, DataCheckable dataCheckable) throws Exception;
+ default void check(T annotation, Method method, DataCheckable dataCheckable) throws Exception {
+ check(annotation, new MethodWrapper.ForMethod(method), dataCheckable);
+ }
+
+ default void check(T annotation, MethodWrapper method, DataCheckable dataCheckable) throws HandlerException {
+ }
int getRunPriority();
@@ -94,7 +119,12 @@ public interface Handler {
}
interface HandlerParameter extends Handler {
- void check(T annotation, Parameter parameter, int index, DataCheckable dataCheckable) throws Exception;
+ default void check(T annotation, Parameter parameter, int index, DataCheckable dataCheckable) throws Exception {
+ check(annotation, new MethodWrapper.ForMethod((Method) parameter.getDeclaringExecutable()), new ParameterWrapper.ForParameter(parameter), index, dataCheckable);
+ }
+
+ default void check(T annotation, MethodWrapper methodWrapper, ParameterWrapper parameter, int index, DataCheckable dataCheckable) throws HandlerException {
+ }
default boolean needsParentTypeMapper() {
return false;
@@ -118,4 +148,179 @@ public interface Handler {
return null;
}
}
+
+ interface MethodWrapper {
+ String getName();
+
+ int getParameterCount();
+
+ TypeWrapper getReturnType();
+
+ ParameterWrapper[] getParameters();
+
+ class ForMethod implements MethodWrapper {
+
+ @Getter
+ private final Method method;
+
+ public ForMethod(Method method) {
+ this.method = method;
+ }
+
+ @Override
+ public String getName() {
+ return method.getName();
+ }
+
+ @Override
+ public int getParameterCount() {
+ return method.getParameterCount();
+ }
+
+ @Override
+ public TypeWrapper getReturnType() {
+ return new TypeWrapper.ForClass(method.getReturnType());
+ }
+
+ @Override
+ public ParameterWrapper[] getParameters() {
+ return Arrays.stream(method.getParameters()).map(ParameterWrapper.ForParameter::new).toArray(ParameterWrapper[]::new);
+ }
+ }
+ }
+
+ interface ParameterWrapper {
+ TypeWrapper getType();
+
+ boolean isVarArgs();
+
+ boolean isAnnotationPresent(Class extends Annotation> annotation);
+
+ A getAnnotation(Class annotation);
+
+ String getName();
+
+ List getAnnotations();
+
+ class ForParameter implements ParameterWrapper {
+
+ @Getter
+ private final Parameter parameter;
+
+ public ForParameter(Parameter parameter) {
+ this.parameter = parameter;
+ }
+
+ @Override
+ public TypeWrapper getType() {
+ return new TypeWrapper.ForClass(this.parameter.getType());
+ }
+
+ @Override
+ public boolean isVarArgs() {
+ return parameter.isVarArgs();
+ }
+
+ @Override
+ public boolean isAnnotationPresent(Class extends Annotation> annotation) {
+ return parameter.isAnnotationPresent(annotation);
+ }
+
+ @Override
+ public A getAnnotation(Class annotation) {
+ return parameter.getAnnotation(annotation);
+ }
+
+ @Override
+ public String getName() {
+ return parameter.getName();
+ }
+
+ @Override
+ public List getAnnotations() {
+ return CommandUtils.getAnnotations(parameter);
+ }
+ }
+ }
+
+ interface TypeWrapper {
+
+ boolean isAssignableTo(Class> clazz);
+
+ boolean isAssignableTo(TypeWrapper type);
+
+ boolean isPrimitive();
+
+ boolean isArray();
+
+ boolean isEnum();
+
+ boolean is(Class> clazz);
+
+ boolean is(TypeWrapper type);
+
+ TypeWrapper getComponentType();
+
+ String getName();
+
+ class ForClass implements TypeWrapper {
+ @Getter
+ private final Class> clazz;
+
+ public ForClass(Class> clazz) {
+ this.clazz = clazz;
+ }
+
+ @Override
+ public boolean isAssignableTo(Class> clazz) {
+ return clazz.isAssignableFrom(this.clazz);
+ }
+
+ @Override
+ public boolean isAssignableTo(TypeWrapper type) {
+ if (type instanceof ForClass) {
+ return ((ForClass) type).getClazz().isAssignableFrom(clazz);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isPrimitive() {
+ return clazz.isPrimitive();
+ }
+
+ @Override
+ public boolean isArray() {
+ return clazz.isArray();
+ }
+
+ @Override
+ public boolean isEnum() {
+ return clazz.isEnum();
+ }
+
+ @Override
+ public boolean is(Class> clazz) {
+ return this.clazz == clazz;
+ }
+
+ @Override
+ public boolean is(TypeWrapper type) {
+ if (type instanceof ForClass) {
+ return ((ForClass) type).getClazz() == this.clazz;
+ }
+ return false;
+ }
+
+ @Override
+ public TypeWrapper getComponentType() {
+ return new TypeWrapper.ForClass(this.clazz.getComponentType());
+ }
+
+ @Override
+ public String getName() {
+ return this.clazz.getName();
+ }
+ }
+ }
}
diff --git a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/AllowNullHandler.java b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/AllowNullHandler.java
index dd170378..340cc833 100644
--- a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/AllowNullHandler.java
+++ b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/AllowNullHandler.java
@@ -36,12 +36,12 @@ public final class AllowNullHandler {
public static final class Impl implements Handler.HandlerParameter {
@Override
- public void check(AllowNull annotation, Parameter parameter, int index, DataCheckable dataCheckable) throws Exception {
+ public void check(AllowNull annotation, MethodWrapper method, ParameterWrapper parameter, int index, DataCheckable dataCheckable) throws HandlerException {
if (index == 0) {
- throw new UnsupportedOperationException("AllowNull annotation cannot be used on the first parameter");
+ throw new HandlerException("AllowNull annotation cannot be used on the first parameter");
}
if (parameter.getType().isPrimitive()) {
- throw new UnsupportedOperationException("AllowNull annotation cannot be used on primitive types");
+ throw new HandlerException("AllowNull annotation cannot be used on primitive types");
}
}
}
diff --git a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/ArrayLengthHandler.java b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/ArrayLengthHandler.java
index 487d13b9..65ff83a4 100644
--- a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/ArrayLengthHandler.java
+++ b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/ArrayLengthHandler.java
@@ -47,15 +47,15 @@ public final class ArrayLengthHandler {
public static final class Impl implements Handler.HandlerParameter {
@Override
- public void check(ArrayLength arrayLength, Parameter parameter, int index, DataCheckable dataCheckable) throws Exception {
+ public void check(ArrayLength arrayLength, MethodWrapper methodWrapper, ParameterWrapper parameter, int index, DataCheckable dataCheckable) throws HandlerException {
if (index == 0) {
- throw new UnsupportedOperationException("ArrayLength annotation cannot be used on first parameter");
+ throw new HandlerException("ArrayLength annotation cannot be used on first parameter");
}
if (!parameter.getType().isArray()) {
- throw new UnsupportedOperationException("Parameter " + index + " of " + parameter.getDeclaringExecutable().getName() + " is not an array");
+ throw new HandlerException("Parameter " + index + " of " + methodWrapper.getName() + " is not an array");
}
if (arrayLength.min() > arrayLength.max()) {
- throw new UnsupportedOperationException("Min ArrayLength cannot be smaller than Max ArrayLength");
+ throw new HandlerException("Min ArrayLength cannot be smaller than Max ArrayLength");
}
}
}
diff --git a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/CachedHandler.java b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/CachedHandler.java
index 59ac3522..a72023d8 100644
--- a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/CachedHandler.java
+++ b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/CachedHandler.java
@@ -31,12 +31,12 @@ public final class CachedHandler {
public static final class Impl implements Handler.HandlerMethod {
@Override
- public void check(Cached annotation, Method method, DataCheckable dataCheckable) throws Exception {
+ public void check(Cached annotation, MethodWrapper method, DataCheckable dataCheckable) throws HandlerException {
if (method.getParameterCount() != 0) {
- throw new UnsupportedOperationException("Cached method must have no parameters");
+ throw new HandlerException("Cached method must have no parameters");
}
- if (!AbstractTypeMapper.class.isAssignableFrom(method.getReturnType())) {
- throw new UnsupportedOperationException("Cached method must return AbstractTypeMapper");
+ if (!method.getReturnType().isAssignableTo(AbstractTypeMapper.class)) {
+ throw new HandlerException("Cached method must return AbstractTypeMapper");
}
}
diff --git a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/ClassMapperHandler.java b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/ClassMapperHandler.java
index ab31acb1..15d7a97d 100644
--- a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/ClassMapperHandler.java
+++ b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/ClassMapperHandler.java
@@ -31,12 +31,12 @@ public final class ClassMapperHandler {
public static final class Impl implements Handler.HandlerMethod {
@Override
- public void check(ClassMapper annotation, Method method, DataCheckable dataCheckable) throws Exception {
+ public void check(ClassMapper annotation, MethodWrapper method, DataCheckable dataCheckable) throws HandlerException {
if (method.getParameterCount() != 0) {
- throw new UnsupportedOperationException("ClassMapper method must have no parameters");
+ throw new HandlerException("ClassMapper method must have no parameters");
}
- if (!AbstractTypeMapper.class.isAssignableFrom(method.getReturnType())) {
- throw new UnsupportedOperationException("ClassMapper method must return AbstractTypeMapper");
+ if (!method.getReturnType().isAssignableTo(AbstractTypeMapper.class)) {
+ throw new HandlerException("ClassMapper method must return AbstractTypeMapper");
}
}
diff --git a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/ClassValidatorHandler.java b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/ClassValidatorHandler.java
index a8d64e82..2a282cf0 100644
--- a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/ClassValidatorHandler.java
+++ b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/ClassValidatorHandler.java
@@ -31,12 +31,12 @@ public final class ClassValidatorHandler {
public static final class Impl implements Handler.HandlerMethod {
@Override
- public void check(ClassValidator annotation, Method method, DataCheckable dataCheckable) throws Exception {
+ public void check(ClassValidator annotation, MethodWrapper method, DataCheckable dataCheckable) throws HandlerException {
if (method.getParameterCount() != 0) {
- throw new UnsupportedOperationException("ClassValidator method must have no parameters");
+ throw new HandlerException("ClassValidator method must have no parameters");
}
- if (!AbstractTypeValidator.class.isAssignableFrom(method.getReturnType())) {
- throw new UnsupportedOperationException("ClassValidator method must return AbstractValidator");
+ if (!method.getReturnType().isAssignableTo(AbstractTypeValidator.class)) {
+ throw new HandlerException("ClassValidator method must return AbstractValidator");
}
}
diff --git a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/EndsWithHandler.java b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/EndsWithHandler.java
index 37ea29ee..5ea8500f 100644
--- a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/EndsWithHandler.java
+++ b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/EndsWithHandler.java
@@ -35,12 +35,12 @@ public final class EndsWithHandler {
public static final class Impl implements Handler.HandlerParameter {
@Override
- public void check(EndsWith annotation, Parameter parameter, int index, DataCheckable dataCheckable) throws Exception {
+ public void check(EndsWith annotation, MethodWrapper methodWrapper, ParameterWrapper parameter, int index, DataCheckable dataCheckable) throws HandlerException {
if (index == 0) {
- throw new UnsupportedOperationException("EndsWith annotation cannot be used on first parameter");
+ throw new HandlerException("EndsWith annotation cannot be used on first parameter");
}
- if (parameter.getType() != String.class) {
- throw new UnsupportedOperationException("EndsWith annotation cannot be used on String parameter");
+ if (!parameter.getType().is(String.class)) {
+ throw new HandlerException("EndsWith annotation cannot be used on String parameter");
}
}
diff --git a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/ErrorMessageHandler.java b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/ErrorMessageHandler.java
index df5a278e..56dd5e0a 100644
--- a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/ErrorMessageHandler.java
+++ b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/ErrorMessageHandler.java
@@ -31,12 +31,12 @@ public final class ErrorMessageHandler {
public static final class Impl implements Handler.HandlerParameter {
@Override
- public void check(ErrorMessage errorMessage, Parameter parameter, int index, DataCheckable dataCheckable) throws Exception {
+ public void check(ErrorMessage errorMessage, MethodWrapper methodWrapper, ParameterWrapper parameter, int index, DataCheckable dataCheckable) throws HandlerException {
if (index == 0) {
- throw new UnsupportedOperationException("ErrorMessage annotation cannot be used on first parameter");
+ throw new HandlerException("ErrorMessage annotation cannot be used on first parameter");
}
if (!errorMessage.allowEAs() && !(parameter.isVarArgs() || parameter.getType().isArray())) {
- throw new UnsupportedOperationException("ErrorMessage allowESs cannot be used on non array or varargs parameter");
+ throw new HandlerException("ErrorMessage allowESs cannot be used on non array or varargs parameter");
}
}
diff --git a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/GreedyHandler.java b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/GreedyHandler.java
index 1eaa20a0..4d595a8e 100644
--- a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/GreedyHandler.java
+++ b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/GreedyHandler.java
@@ -44,9 +44,9 @@ public final class GreedyHandler {
public static final class Impl implements Handler.HandlerParameter {
@Override
- public void check(Greedy annotation, Parameter parameter, int index, DataCheckable dataCheckable) throws Exception {
+ public void check(Greedy annotation, MethodWrapper methodWrapper, ParameterWrapper parameter, int index, DataCheckable dataCheckable) throws HandlerException {
if (!parameter.getType().isArray() || parameter.isVarArgs()) {
- throw new UnsupportedOperationException("Greedy annotation cannot be used on non array parameters");
+ throw new HandlerException("Greedy annotation cannot be used on non array parameters");
}
}
}
diff --git a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/LengthHandler.java b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/LengthHandler.java
index 9d6ba906..aedb45c9 100644
--- a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/LengthHandler.java
+++ b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/LengthHandler.java
@@ -35,9 +35,9 @@ public final class LengthHandler {
public static final class Impl implements Handler.HandlerParameter {
@Override
- public void check(Length annotation, Parameter parameter, int index, DataCheckable dataCheckable) throws Exception {
+ public void check(Length annotation, MethodWrapper methodWrapper, ParameterWrapper parameter, int index, DataCheckable dataCheckable) throws HandlerException {
if (index == 0) {
- throw new UnsupportedOperationException("Length annotation cannot be used on first parameter");
+ throw new HandlerException("Length annotation cannot be used on first parameter");
}
}
diff --git a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/MapperHandler.java b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/MapperHandler.java
index a01392c1..57122912 100644
--- a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/MapperHandler.java
+++ b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/MapperHandler.java
@@ -32,26 +32,29 @@ public final class MapperHandler {
public static final class Impl implements Handler.HandlerMethod, Handler.HandlerParameter {
@Override
- public void check(Mapper annotation, Method method, DataCheckable dataCheckable) throws Exception {
+ public void check(Mapper annotation, MethodWrapper method, DataCheckable dataCheckable) throws HandlerException {
if (method.getParameterCount() != 0) {
- throw new UnsupportedOperationException("Mapper method must have no parameters");
+ throw new HandlerException("Mapper method must have no parameters");
}
- if (!AbstractTypeMapper.class.isAssignableFrom(method.getReturnType())) {
- throw new UnsupportedOperationException("Mapper method must return AbstractTypeMapper");
+ if (!method.getReturnType().isAssignableTo(AbstractTypeMapper.class)) {
+ throw new HandlerException("Mapper method must return AbstractTypeMapper");
}
if (annotation.value() != null && !annotation.value().isEmpty()) {
return;
}
- Optional> genericType = getGenericTypeOfReturn(method);
- if (annotation.type() == void.class) {
- if (genericType.isEmpty()) {
- throw new UnsupportedOperationException("Please supply a class type to the Mapper");
- }
- } else {
- if (genericType.isPresent() && !annotation.type().isAssignableFrom(genericType.get())) {
- throw new UnsupportedOperationException("Supplied type does not conform to actual type");
+ // TODO: Implement! for AnnotationProcessor as well!
+ if (method instanceof MethodWrapper.ForMethod) {
+ Optional> genericType = getGenericTypeOfReturn(((MethodWrapper.ForMethod) method).getMethod());
+ if (annotation.type() == void.class) {
+ if (genericType.isEmpty()) {
+ throw new HandlerException("Please supply a class type to the Mapper");
+ }
+ } else {
+ if (genericType.isPresent() && !annotation.type().isAssignableFrom(genericType.get())) {
+ throw new HandlerException("Supplied type does not conform to actual type");
+ }
}
}
}
@@ -74,9 +77,9 @@ public final class MapperHandler {
}
@Override
- public void check(Mapper annotation, Parameter parameter, int index, DataCheckable dataCheckable) throws Exception {
+ public void check(Mapper annotation, MethodWrapper methodWrapper, ParameterWrapper parameter, int index, DataCheckable dataCheckable) throws HandlerException {
if (index == 0) {
- throw new UnsupportedOperationException("Mapper annotation cannot be used on first parameter");
+ throw new HandlerException("Mapper annotation cannot be used on first parameter");
}
if (!dataCheckable.hasMapper(annotation.value())) {
throw new UnsupportedOperationException("Mapper '" + annotation.value() + "' not found");
diff --git a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/MaxHandler.java b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/MaxHandler.java
index a44d985c..65d98be1 100644
--- a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/MaxHandler.java
+++ b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/MaxHandler.java
@@ -34,15 +34,15 @@ public final class MaxHandler {
public static final class Impl implements Handler.HandlerParameter {
@Override
- public void check(Max max, Parameter parameter, int index, DataCheckable dataCheckable) throws Exception {
+ public void check(Max max, MethodWrapper methodWrapper, ParameterWrapper parameter, int index, DataCheckable dataCheckable) throws HandlerException {
if (index == 0) {
- throw new UnsupportedOperationException("Max annotation cannot be used on first parameter");
+ throw new HandlerException("Max annotation cannot be used on first parameter");
}
- Class> type = parameter.getType();
+ TypeWrapper type = parameter.getType();
if (parameter.isVarArgs()) type = type.getComponentType();
- if (type != int.class && type != Integer.class && type != long.class && type != Long.class && type != float.class && type != Float.class && type != double.class && type != Double.class) {
- throw new UnsupportedOperationException("Parameter " + index + " of " + parameter.getDeclaringExecutable() + " is not a number.");
+ if (!type.is(int.class) && !type.is(Integer.class) && !type.is(long.class) && !type.is(Long.class) && !type.is(float.class) && !type.is(Float.class) && !type.is(double.class) && !type.is(Double.class)) {
+ throw new HandlerException("Parameter " + index + " of " + methodWrapper.getName() + " is not a number.");
}
if (!parameter.isAnnotationPresent(Min.class)) {
@@ -52,13 +52,13 @@ public final class MaxHandler {
Min min = parameter.getAnnotation(Min.class);
Number minValue;
- if (type.equals(int.class) || type.equals(Integer.class)) {
+ if (type.is(int.class) || type.is(Integer.class)) {
minValue = min.intValue();
- } else if (type.equals(long.class) || type.equals(Long.class)) {
+ } else if (type.is(long.class) || type.is(Long.class)) {
minValue = min.longValue();
- } else if (type.equals(float.class) || type.equals(Float.class)) {
+ } else if (type.is(float.class) || type.is(Float.class)) {
minValue = min.floatValue();
- } else if (type.equals(double.class) || type.equals(Double.class)) {
+ } else if (type.is(double.class) || type.is(Double.class)) {
minValue = min.doubleValue();
} else {
throw new SecurityException();
@@ -66,9 +66,9 @@ public final class MaxHandler {
ToIntFunction maxComparator = CommandUtils.createComparator("Max", type, max.intValue(), max.longValue(), max.floatValue(), max.doubleValue());
if (!(min.inclusive() && max.inclusive()) && maxComparator.applyAsInt(minValue) == 0) {
- throw new UnsupportedOperationException("Min and Max cannot be equal if not both are inclusive");
+ throw new HandlerException("Min and Max cannot be equal if not both are inclusive");
} else if (maxComparator.applyAsInt(minValue) > 0) {
- throw new UnsupportedOperationException("Max must be bigger then Min");
+ throw new HandlerException("Max must be bigger then Min");
}
}
@@ -83,7 +83,7 @@ public final class MaxHandler {
if (parameter.isVarArgs()) type = type.getComponentType();
int compareValue = max.inclusive() ? 0 : -1;
- ToIntFunction comparator = CommandUtils.createComparator("Max", type, max.intValue(), max.longValue(), max.floatValue(), max.doubleValue());
+ ToIntFunction comparator = CommandUtils.createComparator("Max", new TypeWrapper.ForClass(type), max.intValue(), max.longValue(), max.floatValue(), max.doubleValue());
boolean onlyNegative = comparator.applyAsInt(0) >= 0;
Min min = parameter.getAnnotation(Min.class);
@@ -155,7 +155,7 @@ public final class MaxHandler {
}
int compareValue = max.inclusive() ? 0 : -1;
- ToIntFunction comparator = CommandUtils.createComparator("Max", type, max.intValue(), max.longValue(), max.floatValue(), max.doubleValue());
+ ToIntFunction comparator = CommandUtils.createComparator("Max", new TypeWrapper.ForClass(type), max.intValue(), max.longValue(), max.floatValue(), max.doubleValue());
return (sender, value, messageSender) -> {
if (value == null) return true;
diff --git a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/MaxReferenceHandler.java b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/MaxReferenceHandler.java
index 05ae49c2..ec2031f8 100644
--- a/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/MaxReferenceHandler.java
+++ b/CommandFramework/CommandFrameworkBase/src/de/steamwar/command/handler/MaxReferenceHandler.java
@@ -36,20 +36,20 @@ public final class MaxReferenceHandler {
public static final class Impl implements Handler.HandlerParameter {
@Override
- public void check(Max.Reference annotation, Parameter parameter, int index, DataCheckable dataCheckable) throws Exception {
+ public void check(Max.Reference annotation, MethodWrapper methodWrapper, ParameterWrapper parameter, int index, DataCheckable dataCheckable) throws HandlerException {
if (index == 0) {
- throw new UnsupportedOperationException("Max.Reference annotation cannot be used on first parameter");
+ throw new HandlerException("Max.Reference annotation cannot be used on first parameter");
}
- Class> type = parameter.getType();
+ TypeWrapper type = parameter.getType();
if (type.isArray()) type = type.getComponentType();
- if (type != int.class && type != Integer.class && type != long.class && type != Long.class && type != float.class && type != Float.class && type != double.class && type != Double.class) {
- throw new UnsupportedOperationException("Parameter " + index + " of " + parameter.getDeclaringExecutable() + " is not a number.");
+ if (!type.is(int.class) && !type.is(Integer.class) && !type.is(long.class) && !type.is(Long.class) && !type.is(float.class) && !type.is(Float.class) && !type.is(double.class) && !type.is(Double.class)) {
+ throw new HandlerException("Parameter " + index + " of " + methodWrapper.getName() + " is not a number.");
}
- Parameter[] parameters = parameter.getDeclaringExecutable().getParameters();
+ ParameterWrapper[] parameters = methodWrapper.getParameters();
for (int i = index - 1; i >= 1; i--) {
- Parameter toCheck = parameters[i];
+ ParameterWrapper toCheck = parameters[i];
Name name = toCheck.getAnnotation(Name.class);
String parameterName;
if (name == null) {
@@ -60,14 +60,14 @@ public final class MaxReferenceHandler {
if (!parameterName.equals(annotation.value())) {
continue;
}
- Class> parameterType = toCheck.getType();
- if (!type.isAssignableFrom(parameterType)) {
- throw new UnsupportedOperationException("Parameter type being referenced cannot be assigned here!");
+ TypeWrapper parameterType = toCheck.getType();
+ if (!parameterType.isAssignableTo(type)) {
+ throw new HandlerException("Parameter type being referenced cannot be assigned here!");
} else {
return;
}
}
- throw new UnsupportedOperationException("Parameter with name '" + annotation.value() + "' does not exist.");
+ throw new HandlerException("Parameter with name '" + annotation.value() + "' does not exist.");
}
@Override
@@ -79,7 +79,7 @@ public final class MaxReferenceHandler {
public AbstractTypeMapper