package com.supaham.commons.bukkit.commands.utils;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.Chars;
import com.sk89q.intake.Command;
import com.sk89q.intake.CommandCallable;
import com.sk89q.intake.Description;
import com.sk89q.intake.ImmutableDescription;
import com.sk89q.intake.parametric.AbstractParametricCallable;
import com.sk89q.intake.parametric.ArgumentParser;
import com.sk89q.intake.parametric.IllegalParameterException;
import com.sk89q.intake.parametric.ParametricBuilder;
import com.sk89q.intake.parametric.ParametricException;
import com.sk89q.intake.parametric.handler.InvokeListener;
import com.supaham.commons.utils.ReflectionUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
/**
* Created by Ali on 25/01/2016.
*/
public class CommandUtils {
private static Constructor ctor;
private static Method setCommandAnnotations;
private static Method setIgnoreUnusedFlags;
private static Method setUnusedFlags;
private static Method getInvokeListeners;
static {
try {
ctor = Class.forName("com.sk89q.intake.parametric.MethodCallable")
.getDeclaredConstructor(ParametricBuilder.class, ArgumentParser.class, Object.class, Method.class,
Description.class, List.class);
ctor.setAccessible(true);
setCommandAnnotations = ReflectionUtils.getMethod(AbstractParametricCallable.class, "setCommandAnnotations",
List.class);
setIgnoreUnusedFlags = ReflectionUtils.getMethod(AbstractParametricCallable.class, "setIgnoreUnusedFlags",
boolean.class);
setUnusedFlags = ReflectionUtils.getMethod(AbstractParametricCallable.class, "setUnusedFlags", Set.class);
getInvokeListeners = ReflectionUtils.getMethod(ParametricBuilder.class, "getInvokeListeners");
} catch (ClassNotFoundException | NoSuchMethodException e) {
e.printStackTrace();
}
}
/*
* Intake, a command processing library
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) Intake team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
public static void registerMethod(CommonCommandData commonCommandData) throws ParametricException {
Preconditions.checkNotNull(commonCommandData, "commonCommandData cannot be null.");
CommandCallable callable = create(commonCommandData);
commonCommandData.getManager().dispatcher().registerCommand(callable, commonCommandData.getAliasesArray());
}
public static AbstractParametricCallable create(CommonCommandData data) throws IllegalParameterException {
checkNotNull(data, "data");
ParametricBuilder builder = data.getManager().config();
Object object = data.getClassInstance();
Method method = data.getMethod();
Set<Annotation> commandAnnotations = ImmutableSet.copyOf(method.getAnnotations());
Command definition = method.getAnnotation(Command.class);
checkNotNull(definition, "Method lacks a @Command annotation");
boolean ignoreUnusedFlags = definition.anyFlags();
Set<Character> unusedFlags = ImmutableSet.copyOf(Chars.asList(definition.flags().toCharArray()));
Annotation[][] annotations = method.getParameterAnnotations();
Type[] types = method.getGenericParameterTypes();
ArgumentParser.Builder parserBuilder = new ArgumentParser.Builder(builder.getInjector());
for (int i = 0; i < types.length; i++) {
parserBuilder.addParameter(types[i], Arrays.asList(annotations[i]));
}
ArgumentParser parser = parserBuilder.build();
ImmutableDescription.Builder descBuilder = new ImmutableDescription.Builder()
.setParameters(parser.getUserParameters())
.setShortDescription(!definition.desc().isEmpty() ? definition.desc() : null)
.setHelp(!definition.help().isEmpty() ? definition.help() : null)
.setUsageOverride(!definition.usage().isEmpty() ? definition.usage() : null);
List<String> permissions = data.getPermissions();
try {
for (InvokeListener listener : (List<InvokeListener>) getInvokeListeners.invoke(builder)) {
listener.updateDescription(commandAnnotations, parser, descBuilder);
}
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
Description description = descBuilder.build();
try {
AbstractParametricCallable o =
(AbstractParametricCallable) ctor.newInstance(builder, parser, object, method, description, permissions);
setCommandAnnotations.invoke(o, ImmutableList.copyOf(method.getAnnotations()));
setIgnoreUnusedFlags.invoke(o, ignoreUnusedFlags);
setUnusedFlags.invoke(o, unusedFlags);
return o;
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}