Skip to content

Commit b494ea3

Browse files
committed
Optimize the ParameterHandler base
1 parent 9240a7d commit b494ea3

File tree

1 file changed

+94
-78
lines changed

1 file changed

+94
-78
lines changed

src/main/java/me/despical/commandframework/ParameterHandler.java

Lines changed: 94 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@
2222
import me.despical.commandframework.annotations.Default;
2323
import me.despical.commandframework.annotations.Param;
2424
import me.despical.commandframework.exceptions.CommandException;
25+
import me.despical.commandframework.utils.CompleterHelper;
2526
import org.jetbrains.annotations.ApiStatus;
2627
import org.jetbrains.annotations.NotNull;
2728

28-
import java.lang.annotation.Annotation;
2929
import java.lang.reflect.Method;
3030
import java.lang.reflect.Parameter;
3131
import java.util.HashMap;
@@ -40,81 +40,97 @@
4040
@ApiStatus.Internal
4141
public final class ParameterHandler {
4242

43-
@NotNull
44-
private final Map<String, Function<CommandArguments, ?>> customParametersMap;
45-
46-
public ParameterHandler() {
47-
this.customParametersMap = new HashMap<>();
48-
}
49-
50-
public <A, B extends A> void addCustomParameter(@NotNull String value, @NotNull Function<CommandArguments, B> function) {
51-
if (this.customParametersMap.containsKey(value))
52-
throw new CommandException("Custom parameter function called ''{0}'' is already registered!", value);
53-
this.customParametersMap.put(value, function);
54-
}
55-
56-
@NotNull
57-
public Object[] getParameterArray(Method method, CommandArguments commandArguments) throws Exception {
58-
final Parameter[] parameters = method.getParameters();
59-
final Object[] methodParameters = new Object[parameters.length];
60-
61-
outer_loop:
62-
for (int i = 0; i < parameters.length; i++) {
63-
final String simpleName = parameters[i].getType().getSimpleName();
64-
65-
if ("CommandArguments".equals(simpleName)) {
66-
methodParameters[i] = commandArguments;
67-
continue;
68-
}
69-
70-
for (Annotation annotation : parameters[i].getAnnotations()) {
71-
if (annotation instanceof Param) {
72-
String value = ((Param) annotation).value();
73-
74-
if (!customParametersMap.containsKey(value)) {
75-
throw new CommandException("Custom parameter (type: {0}, value: {1}) is requested but return function is not found!", simpleName, value);
76-
}
77-
78-
methodParameters[i] = customParametersMap.get(value).apply(commandArguments);
79-
80-
if (methodParameters[i] == null) {
81-
if (!parameters[i].isAnnotationPresent(Default.class)) {
82-
continue outer_loop;
83-
}
84-
85-
String defaultValue = parameters[i].getAnnotation(Default.class).value();
86-
87-
if (!parameters[i].getType().isInstance(String.class)) {
88-
Class<?> clazz = parameters[i].getType();
89-
90-
if (!Primitives.isWrapperType(clazz)) {
91-
try {
92-
methodParameters[i] = clazz.getMethod("valueOf", String.class).invoke(null, defaultValue);
93-
} catch (Exception exception) {
94-
throw new CommandException("Static method {0}#valueOf(String) does not exist!", clazz.getSimpleName());
95-
}
96-
97-
continue outer_loop;
98-
}
99-
100-
methodParameters[i] = Primitives.wrap(clazz).getMethod("valueOf", String.class).invoke(null, defaultValue);
101-
continue outer_loop;
102-
}
103-
104-
methodParameters[i] = defaultValue;
105-
}
106-
107-
continue outer_loop;
108-
}
109-
}
110-
111-
if (!customParametersMap.containsKey(simpleName)) {
112-
throw new CommandException("Custom parameter (type: {0}) is requested but return function is not found!", simpleName);
113-
}
114-
115-
methodParameters[i] = customParametersMap.get(simpleName).apply(commandArguments);
116-
}
117-
118-
return methodParameters;
119-
}
43+
@NotNull
44+
private final Map<String, Function<CommandArguments, ?>> customParametersMap;
45+
46+
public ParameterHandler() {
47+
this.customParametersMap = new HashMap<>();
48+
this.customParametersMap.put(CompleterHelper.class.getSimpleName(), CompleterHelper::new);
49+
}
50+
51+
public <A, B extends A> void addCustomParameter(@NotNull String key, @NotNull Function<CommandArguments, B> function) {
52+
if (this.customParametersMap.containsKey(key)) {
53+
throw new CommandException("Cannot register custom parameter provider for ''{0}'' because it is already registered!", key);
54+
}
55+
56+
this.customParametersMap.put(key, function);
57+
}
58+
59+
public <T> void addCustomParameter(@NotNull Class<T> clazz, @NotNull Function<CommandArguments, T> function) {
60+
this.addCustomParameter(clazz.getSimpleName(), function);
61+
}
62+
63+
@NotNull
64+
public Object[] getParameterArray(Method method, CommandArguments commandArguments) throws Exception {
65+
final Parameter[] parameters = method.getParameters();
66+
final Object[] methodParameters = new Object[parameters.length];
67+
68+
for (int i = 0; i < parameters.length; i++) {
69+
Parameter param = parameters[i];
70+
Class<?> paramType = param.getType();
71+
72+
if (CommandArguments.class.isAssignableFrom(paramType)) {
73+
methodParameters[i] = commandArguments;
74+
continue;
75+
}
76+
77+
Param paramAnnotation = param.getAnnotation(Param.class);
78+
79+
String simpleName = paramType.getSimpleName();
80+
String key = getKey(method, paramAnnotation, simpleName);
81+
82+
Object value = customParametersMap.get(key).apply(commandArguments);
83+
84+
if (value == null && param.isAnnotationPresent(Default.class)) {
85+
String defaultValue = param.getAnnotation(Default.class).value();
86+
value = parseDefaultValue(paramType, defaultValue);
87+
}
88+
89+
if (value == null && paramType.isPrimitive()) {
90+
throw new CommandException(
91+
"Primitive parameter ''{0}'' (type: {1}) in method ''{2}'' cannot be null! usage: Use a wrapper class (e.g. Integer) or ensure the provider returns a value.",
92+
key, simpleName, method.getName()
93+
);
94+
}
95+
96+
methodParameters[i] = value;
97+
}
98+
99+
return methodParameters;
100+
}
101+
102+
private String getKey(Method method, Param paramAnnotation, String simpleName) {
103+
String key = (paramAnnotation != null) ? paramAnnotation.value() : simpleName;
104+
105+
if (!customParametersMap.containsKey(key)) {
106+
String methodName = "%s#%s".formatted(method.getDeclaringClass().getSimpleName(), method.getName());
107+
108+
if (paramAnnotation != null) {
109+
throw new CommandException(
110+
"No parameter provider found for @Param(''{0}'') in method ''{1}''. Requested Type: {2}. Did you forget to register it?",
111+
key, methodName, simpleName
112+
);
113+
}
114+
115+
throw new CommandException(
116+
"No parameter provider found for type ''{0}'' in method ''{1}''. Did you forget to register it using CommandFramework#addCustomParameter?",
117+
simpleName, methodName
118+
);
119+
}
120+
return key;
121+
}
122+
123+
private Object parseDefaultValue(Class<?> type, String value) throws Exception {
124+
if (type == String.class) {
125+
return value;
126+
}
127+
128+
Class<?> actualType = Primitives.isWrapperType(type) ? type : Primitives.wrap(type);
129+
130+
try {
131+
return actualType.getMethod("valueOf", String.class).invoke(null, value);
132+
} catch (NoSuchMethodException exception) {
133+
throw new CommandException("Type ''{0}'' does not support default values (missing static valueOf(String) method).", type.getSimpleName());
134+
}
135+
}
120136
}

0 commit comments

Comments
 (0)