From 7b1e4f085d7cb4629ed2faad7a96d960ee3e4766 Mon Sep 17 00:00:00 2001 From: Aikar Date: Mon, 26 Mar 2018 01:50:43 -0400 Subject: [PATCH] (DEPLOYED ACF) Updated JavaDocs --- .../co/aikar/commands/BaseCommand.html | 62 +- .../co/aikar/commands/RegisteredCommand.html | 24 +- .../co/aikar/commands/BaseCommand.html | 1272 ++++++++--------- .../co/aikar/commands/RegisteredCommand.html | 534 ++++--- 4 files changed, 932 insertions(+), 960 deletions(-) diff --git a/docs/acf-core/co/aikar/commands/BaseCommand.html b/docs/acf-core/co/aikar/commands/BaseCommand.html index f0f0b409..6e48b63d 100644 --- a/docs/acf-core/co/aikar/commands/BaseCommand.html +++ b/docs/acf-core/co/aikar/commands/BaseCommand.html @@ -112,7 +112,7 @@ var activeTableTab = "activeTableTab";

-
public abstract class BaseCommand
+
public abstract class BaseCommand
 extends Object
@@ -335,7 +335,7 @@ extends
  • CATCHUNKNOWN

    -
    public static final String CATCHUNKNOWN
    +
    public static final String CATCHUNKNOWN
    See Also:
    Constant Field Values
    @@ -348,7 +348,7 @@ extends
  • DEFAULT

    -
    public static final String DEFAULT
    +
    public static final String DEFAULT
    See Also:
    Constant Field Values
    @@ -369,7 +369,7 @@ extends
  • BaseCommand

    -
    public BaseCommand()
    +
    public BaseCommand()
  • @@ -378,7 +378,7 @@ extends
  • BaseCommand

    -
    public BaseCommand(String cmd)
    +
    public BaseCommand(String cmd)
  • @@ -395,7 +395,7 @@ extends
  • getExecCommandLabel

    -
    public String getExecCommandLabel()
    +
    public String getExecCommandLabel()
    Gets the root command name that the user actually typed
    Returns:
    @@ -409,7 +409,7 @@ extends
  • getExecSubcommand

    -
    public String getExecSubcommand()
    +
    public String getExecSubcommand()
    Gets the actual sub command name the user typed
    Returns:
    @@ -423,7 +423,7 @@ extends
  • getOrigArgs

    -
    public String[] getOrigArgs()
    +
    public String[] getOrigArgs()
    Gets the actual args in string form the user typed
    Returns:
    @@ -437,7 +437,7 @@ extends
  • execute

    -
    public void execute(CommandIssuer issuer,
    +
    public void execute(CommandIssuer issuer,
                         String commandLabel,
                         String[] args)
  • @@ -448,7 +448,7 @@ extends
  • getCurrentCommandIssuer

    -
    public CommandIssuer getCurrentCommandIssuer()
    +
    public CommandIssuer getCurrentCommandIssuer()
  • @@ -457,7 +457,7 @@ extends
  • getCurrentCommandManager

    -
    public CommandManager getCurrentCommandManager()
    +
    public CommandManager getCurrentCommandManager()
  • @@ -466,7 +466,7 @@ extends
  • canExecute

    -
    public boolean canExecute(CommandIssuer issuer,
    +
    public boolean canExecute(CommandIssuer issuer,
                               RegisteredCommand<?> cmd)
  • @@ -476,7 +476,7 @@ extends
  • tabComplete

    -
    public List<StringtabComplete(CommandIssuer issuer,
    +
    public List<StringtabComplete(CommandIssuer issuer,
                                     String commandLabel,
                                     String[] args)
  • @@ -487,7 +487,7 @@ extends
  • tabComplete

    -
    public List<StringtabComplete(CommandIssuer issuer,
    +
    public List<StringtabComplete(CommandIssuer issuer,
                                     String commandLabel,
                                     String[] args,
                                     boolean isAsync)
    @@ -505,7 +505,7 @@ extends 
     

    getCommandHelp

    @Deprecated
    -public CommandHelp getCommandHelp()
    +public CommandHelp getCommandHelp()
    Deprecated. Unstable API
  • @@ -516,7 +516,7 @@ public 

    showCommandHelp

    @Deprecated
    -public void showCommandHelp()
    +public void showCommandHelp()
  • Deprecated. Unstable API
    @@ -526,7 +526,7 @@ public void 
  • help

    -
    public void help(Object issuer,
    +
    public void help(Object issuer,
                      String[] args)
  • @@ -536,7 +536,7 @@ public void 
  • help

    -
    public void help(CommandIssuer issuer,
    +
    public void help(CommandIssuer issuer,
                      String[] args)
  • @@ -546,7 +546,7 @@ public void 
  • doHelp

    -
    public void doHelp(Object issuer,
    +
    public void doHelp(Object issuer,
                        String... args)
  • @@ -556,7 +556,7 @@ public void 
  • doHelp

    -
    public void doHelp(CommandIssuer issuer,
    +
    public void doHelp(CommandIssuer issuer,
                        String... args)
  • @@ -566,7 +566,7 @@ public void 
  • showSyntax

    -
    public void showSyntax(CommandIssuer issuer,
    +
    public void showSyntax(CommandIssuer issuer,
                            RegisteredCommand<?> cmd)
  • @@ -576,7 +576,7 @@ public void 
  • hasPermission

    -
    public boolean hasPermission(Object issuer)
    +
    public boolean hasPermission(Object issuer)
  • @@ -585,7 +585,7 @@ public void 
  • hasPermission

    -
    public boolean hasPermission(CommandIssuer issuer)
    +
    public boolean hasPermission(CommandIssuer issuer)
  • @@ -594,7 +594,7 @@ public void 
  • getRequiredPermissions

    -
    public Set<StringgetRequiredPermissions()
    +
    public Set<StringgetRequiredPermissions()
  • @@ -603,7 +603,7 @@ public void 
  • requiresPermission

    -
    public boolean requiresPermission(String permission)
    +
    public boolean requiresPermission(String permission)
  • @@ -612,7 +612,7 @@ public void 
  • getName

    -
    public String getName()
    +
    public String getName()
  • @@ -621,7 +621,7 @@ public void 
  • getExceptionHandler

    -
    public ExceptionHandler getExceptionHandler()
    +
    public ExceptionHandler getExceptionHandler()
  • @@ -630,7 +630,7 @@ public void 
  • setExceptionHandler

    -
    public BaseCommand setExceptionHandler(ExceptionHandler exceptionHandler)
    +
    public BaseCommand setExceptionHandler(ExceptionHandler exceptionHandler)
  • @@ -639,7 +639,7 @@ public void 
  • getDefaultRegisteredCommand

    -
    public RegisteredCommand getDefaultRegisteredCommand()
    +
    public RegisteredCommand getDefaultRegisteredCommand()
  • @@ -648,7 +648,7 @@ public void 
  • setContextFlags

    -
    public String setContextFlags(Class<?> cls,
    +
    public String setContextFlags(Class<?> cls,
                                   String flags)
  • @@ -658,7 +658,7 @@ public void 
  • getContextFlags

    -
    public String getContextFlags(Class<?> cls)
    +
    public String getContextFlags(Class<?> cls)
  • diff --git a/docs/acf-core/co/aikar/commands/RegisteredCommand.html b/docs/acf-core/co/aikar/commands/RegisteredCommand.html index 56efa0fb..9fd85eea 100644 --- a/docs/acf-core/co/aikar/commands/RegisteredCommand.html +++ b/docs/acf-core/co/aikar/commands/RegisteredCommand.html @@ -108,7 +108,7 @@ var activeTableTab = "activeTableTab";


  • -
    public class RegisteredCommand<CEC extends CommandExecutionContext<CEC,? extends CommandIssuer>>
    +
    public class RegisteredCommand<CEC extends CommandExecutionContext<CEC,? extends CommandIssuer>>
     extends Object
  • @@ -217,7 +217,7 @@ extends
  • helpSearchTags

    -
    public String helpSearchTags
    +
    public String helpSearchTags
  • @@ -234,7 +234,7 @@ extends
  • preCommand

    -
    public void preCommand()
    +
    public void preCommand()
  • @@ -243,7 +243,7 @@ extends
  • postCommand

    -
    public void postCommand()
    +
    public void postCommand()
  • @@ -253,7 +253,7 @@ extends

    getPermission

    @Deprecated
    -public String getPermission()
    +public String getPermission()
    Deprecated. 
    See Also:
    @@ -267,7 +267,7 @@ public 
  • getRequiredPermissions

    -
    public Set<StringgetRequiredPermissions()
    +
    public Set<StringgetRequiredPermissions()
  • @@ -276,7 +276,7 @@ public 
  • requiresPermission

    -
    public boolean requiresPermission(String permission)
    +
    public boolean requiresPermission(String permission)
  • @@ -285,7 +285,7 @@ public 
  • getPrefSubCommand

    -
    public String getPrefSubCommand()
    +
    public String getPrefSubCommand()
  • @@ -294,7 +294,7 @@ public 
  • getSyntaxText

    -
    public String getSyntaxText()
    +
    public String getSyntaxText()
  • @@ -303,7 +303,7 @@ public 
  • getCommand

    -
    public String getCommand()
    +
    public String getCommand()
  • @@ -312,7 +312,7 @@ public 
  • addSubcommand

    -
    public void addSubcommand(String cmd)
    +
    public void addSubcommand(String cmd)
  • @@ -321,7 +321,7 @@ public 
  • addSubcommands

    -
    public void addSubcommands(Collection<String> cmd)
    +
    public void addSubcommands(Collection<String> cmd)
  • diff --git a/docs/acf-core/src-html/co/aikar/commands/BaseCommand.html b/docs/acf-core/src-html/co/aikar/commands/BaseCommand.html index af31eaac..6a243136 100644 --- a/docs/acf-core/src-html/co/aikar/commands/BaseCommand.html +++ b/docs/acf-core/src-html/co/aikar/commands/BaseCommand.html @@ -50,672 +50,660 @@ 042import com.google.common.collect.Maps; 043import com.google.common.collect.SetMultimap; 044import com.google.common.collect.Sets; -045import org.jetbrains.annotations.Nullable; -046 -047import java.lang.invoke.MethodHandle; -048import java.lang.invoke.MethodHandles; -049import java.lang.reflect.Constructor; -050import java.lang.reflect.InvocationTargetException; -051import java.lang.reflect.Method; -052import java.lang.reflect.Parameter; -053import java.util.ArrayList; -054import java.util.Arrays; -055import java.util.Collections; -056import java.util.HashMap; -057import java.util.HashSet; -058import java.util.List; -059import java.util.Map; -060import java.util.Objects; -061import java.util.Optional; -062import java.util.Set; -063import java.util.Stack; -064import java.util.stream.Collectors; -065import java.util.stream.Stream; +045 +046import java.lang.reflect.Constructor; +047import java.lang.reflect.InvocationTargetException; +048import java.lang.reflect.Method; +049import java.lang.reflect.Parameter; +050import java.util.ArrayList; +051import java.util.Arrays; +052import java.util.Collections; +053import java.util.HashMap; +054import java.util.HashSet; +055import java.util.List; +056import java.util.Map; +057import java.util.Objects; +058import java.util.Optional; +059import java.util.Set; +060import java.util.Stack; +061import java.util.stream.Collectors; +062import java.util.stream.Stream; +063 +064@SuppressWarnings("unused") +065public abstract class BaseCommand { 066 -067@SuppressWarnings("unused") -068public abstract class BaseCommand { -069 -070 public static final String CATCHUNKNOWN = "__catchunknown"; -071 public static final String DEFAULT = "__default"; -072 final SetMultimap<String, RegisteredCommand> subCommands = HashMultimap.create(); -073 final Map<Class<?>, String> contextFlags = Maps.newHashMap(); -074 @Nullable private MethodHandle preCommandHandler = null; -075 private Method preCommandReflectiveHandler = null; -076 +067 public static final String CATCHUNKNOWN = "__catchunknown"; +068 public static final String DEFAULT = "__default"; +069 final SetMultimap<String, RegisteredCommand> subCommands = HashMultimap.create(); +070 final Map<Class<?>, String> contextFlags = Maps.newHashMap(); +071 private Method preCommandHandler; +072 +073 @SuppressWarnings("WeakerAccess") +074 private String execLabel; +075 @SuppressWarnings("WeakerAccess") +076 private String execSubcommand; 077 @SuppressWarnings("WeakerAccess") -078 private String execLabel; -079 @SuppressWarnings("WeakerAccess") -080 private String execSubcommand; -081 @SuppressWarnings("WeakerAccess") -082 private String[] origArgs; -083 CommandManager<?, ?, ?, ?, ?, ?> manager = null; -084 BaseCommand parentCommand; -085 Map<String, RootCommand> registeredCommands = new HashMap<>(); -086 String description; -087 String commandName; -088 String permission; -089 String conditions; +078 private String[] origArgs; +079 CommandManager<?, ?, ?, ?, ?, ?> manager = null; +080 BaseCommand parentCommand; +081 Map<String, RootCommand> registeredCommands = new HashMap<>(); +082 String description; +083 String commandName; +084 String permission; +085 String conditions; +086 +087 private ExceptionHandler exceptionHandler = null; +088 CommandOperationContext lastCommandOperationContext; +089 private String parentSubcommand; 090 -091 private ExceptionHandler exceptionHandler = null; -092 CommandOperationContext lastCommandOperationContext; -093 private String parentSubcommand; -094 -095 public BaseCommand() {} -096 public BaseCommand(String cmd) { -097 this.commandName = cmd; -098 } -099 -100 /** -101 * Gets the root command name that the user actually typed -102 * @return Name -103 */ -104 public String getExecCommandLabel() { -105 return execLabel; -106 } -107 -108 /** -109 * Gets the actual sub command name the user typed -110 * @return Name -111 */ -112 public String getExecSubcommand() { -113 return execSubcommand; -114 } -115 -116 /** -117 * Gets the actual args in string form the user typed -118 * @return Args -119 */ -120 public String[] getOrigArgs() { -121 return origArgs; +091 public BaseCommand() {} +092 public BaseCommand(String cmd) { +093 this.commandName = cmd; +094 } +095 +096 /** +097 * Gets the root command name that the user actually typed +098 * @return Name +099 */ +100 public String getExecCommandLabel() { +101 return execLabel; +102 } +103 +104 /** +105 * Gets the actual sub command name the user typed +106 * @return Name +107 */ +108 public String getExecSubcommand() { +109 return execSubcommand; +110 } +111 +112 /** +113 * Gets the actual args in string form the user typed +114 * @return Args +115 */ +116 public String[] getOrigArgs() { +117 return origArgs; +118 } +119 +120 void setParentCommand(BaseCommand command) { +121 this.parentCommand = command; 122 } -123 -124 void setParentCommand(BaseCommand command) { -125 this.parentCommand = command; -126 } -127 void onRegister(CommandManager manager) { -128 onRegister(manager, this.commandName); -129 } -130 void onRegister(CommandManager manager, String cmd) { -131 manager.injectDependencies(this); -132 this.manager = manager; -133 -134 final Annotations annotations = manager.getAnnotations(); -135 final Class<? extends BaseCommand> self = this.getClass(); -136 -137 String[] cmdAliases = annotations.getAnnotationValues(self, CommandAlias.class, Annotations.REPLACEMENTS | Annotations.LOWERCASE | Annotations.NO_EMPTY); +123 void onRegister(CommandManager manager) { +124 onRegister(manager, this.commandName); +125 } +126 void onRegister(CommandManager manager, String cmd) { +127 manager.injectDependencies(this); +128 this.manager = manager; +129 +130 final Annotations annotations = manager.getAnnotations(); +131 final Class<? extends BaseCommand> self = this.getClass(); +132 +133 String[] cmdAliases = annotations.getAnnotationValues(self, CommandAlias.class, Annotations.REPLACEMENTS | Annotations.LOWERCASE | Annotations.NO_EMPTY); +134 +135 if (cmd == null && cmdAliases != null) { +136 cmd = cmdAliases[0]; +137 } 138 -139 if (cmd == null && cmdAliases != null) { -140 cmd = cmdAliases[0]; -141 } -142 -143 this.commandName = cmd != null ? cmd : self.getSimpleName().toLowerCase(); -144 this.permission = annotations.getAnnotationValue(self, CommandPermission.class, Annotations.REPLACEMENTS); -145 this.description = this.commandName + " commands"; -146 this.parentSubcommand = getParentSubcommand(self); -147 this.conditions = annotations.getAnnotationValue(self, Conditions.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY); -148 -149 registerSubcommands(); -150 -151 if (cmdAliases != null) { -152 Set<String> cmdList = new HashSet<>(); -153 Collections.addAll(cmdList, cmdAliases); -154 cmdList.remove(cmd); -155 for (String cmdAlias : cmdList) { -156 register(cmdAlias, this); -157 } +139 this.commandName = cmd != null ? cmd : self.getSimpleName().toLowerCase(); +140 this.permission = annotations.getAnnotationValue(self, CommandPermission.class, Annotations.REPLACEMENTS); +141 this.description = this.commandName + " commands"; +142 this.parentSubcommand = getParentSubcommand(self); +143 this.conditions = annotations.getAnnotationValue(self, Conditions.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY); +144 +145 registerSubcommands(); +146 +147 if (cmdAliases != null) { +148 Set<String> cmdList = new HashSet<>(); +149 Collections.addAll(cmdList, cmdAliases); +150 cmdList.remove(cmd); +151 for (String cmdAlias : cmdList) { +152 register(cmdAlias, this); +153 } +154 } +155 +156 if (cmd != null) { +157 register(cmd, this); 158 } -159 -160 if (cmd != null) { -161 register(cmd, this); -162 } -163 registerSubclasses(cmd); -164 -165 } -166 -167 private void registerSubclasses(String cmd) { -168 for (Class<?> clazz : this.getClass().getDeclaredClasses()) { -169 if (BaseCommand.class.isAssignableFrom(clazz)) { -170 try { -171 BaseCommand subCommand = null; -172 Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors(); -173 for (Constructor<?> declaredConstructor : declaredConstructors) { -174 -175 declaredConstructor.setAccessible(true); -176 Parameter[] parameters = declaredConstructor.getParameters(); -177 if (parameters.length == 1) { -178 subCommand = (BaseCommand) declaredConstructor.newInstance(this); -179 } else { -180 manager.log(LogLevel.INFO, "Found unusable constructor: " + declaredConstructor.getName() + "(" + Stream.of(parameters).map(p -> p.getType().getSimpleName() + " " + p.getName()).collect(Collectors.joining("<c2>,</c2> ")) + ")"); -181 } -182 } -183 if (subCommand != null) { -184 subCommand.setParentCommand(this); -185 subCommand.onRegister(manager, cmd); -186 this.subCommands.putAll(subCommand.subCommands); -187 this.registeredCommands.putAll(subCommand.registeredCommands); -188 } else { -189 this.manager.log(LogLevel.ERROR, "Could not find a subcommand ctor for " + clazz.getName()); -190 } -191 } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { -192 this.manager.log(LogLevel.ERROR, "Error registering subclass", e); -193 } -194 } -195 } -196 } -197 -198 private void registerSubcommands() { -199 final Annotations annotations = manager.getAnnotations(); -200 boolean foundDefault = false; -201 boolean foundCatchUnknown = false; -202 boolean isParentEmpty = parentSubcommand.isEmpty(); -203 -204 for (Method method : this.getClass().getMethods()) { -205 method.setAccessible(true); -206 String sublist = null; -207 String sub = getSubcommandValue(method); -208 final boolean def = annotations.hasAnnotation(method, Default.class); -209 final String helpCommand = annotations.getAnnotationValue(method, HelpCommand.class, Annotations.NOTHING); -210 final String commandAliases = annotations.getAnnotationValue(method, CommandAlias.class, Annotations.NOTHING); -211 -212 if (!isParentEmpty && def) { -213 sub = parentSubcommand; -214 } -215 if (isParentEmpty && (def || (!foundDefault && helpCommand != null))) { -216 if (!foundDefault) { -217 if (def) { -218 this.subCommands.get(DEFAULT).clear(); -219 foundDefault = true; -220 } -221 registerSubcommand(method, DEFAULT); -222 } else { -223 ACFUtil.sneaky(new IllegalStateException("Multiple @Default/@HelpCommand commands, duplicate on " + method.getDeclaringClass().getName() + "#" + method.getName())); -224 } -225 } -226 -227 if (sub != null) { -228 sublist = sub; -229 } else if (commandAliases != null) { -230 sublist = commandAliases; -231 } else if (helpCommand != null) { -232 sublist = helpCommand; -233 } -234 -235 boolean preCommand = annotations.hasAnnotation(method, PreCommand.class); -236 boolean hasCatchUnknown = annotations.hasAnnotation(method, CatchUnknown.class) || -237 annotations.hasAnnotation(method, CatchAll.class) || -238 annotations.hasAnnotation(method, UnknownHandler.class); -239 -240 if (hasCatchUnknown || (!foundCatchUnknown && helpCommand != null)) { -241 if (!foundCatchUnknown) { -242 if (hasCatchUnknown) { -243 this.subCommands.get(CATCHUNKNOWN).clear(); -244 foundCatchUnknown = true; -245 } -246 registerSubcommand(method, CATCHUNKNOWN); -247 } else { -248 ACFUtil.sneaky(new IllegalStateException("Multiple @UnknownHandler/@HelpCommand commands, duplicate on " + method.getDeclaringClass().getName() + "#" + method.getName())); -249 } -250 } else if (preCommand) { -251 if (this.preCommandHandler == null) { -252 this.preCommandReflectiveHandler = method; -253 try { -254 this.preCommandHandler = MethodHandles.lookup().unreflect(method); -255 } catch (IllegalAccessException ignored) { -256 // We use preCommandReflectiveHandler whenever the methodhandle is used instead -257 } -258 } else { -259 ACFUtil.sneaky(new IllegalStateException("Multiple @PreCommand commands, duplicate on " + method.getDeclaringClass().getName() + "#" + method.getName())); -260 } -261 } -262 if (Objects.equals(method.getDeclaringClass(), this.getClass()) && sublist != null) { -263 registerSubcommand(method, sublist); -264 } -265 } -266 } -267 -268 private String getSubcommandValue(Method method) { -269 final String sub = manager.getAnnotations().getAnnotationValue(method, Subcommand.class, Annotations.NOTHING); -270 if (sub == null) { -271 return null; -272 } -273 Class<?> clazz = method.getDeclaringClass(); -274 String parent = getParentSubcommand(clazz); -275 return parent == null || parent.isEmpty() ? sub : parent + " " + sub; -276 } -277 -278 private String getParentSubcommand(Class<?> clazz) { -279 List<String> subList = new ArrayList<>(); -280 while (clazz != null) { -281 String sub = manager.getAnnotations().getAnnotationValue(clazz, Subcommand.class, Annotations.NOTHING); -282 if (sub != null) { -283 subList.add(sub); -284 } -285 clazz = clazz.getEnclosingClass(); -286 } -287 Collections.reverse(subList); -288 return ACFUtil.join(subList, " "); -289 } -290 -291 private void register(String name, BaseCommand cmd) { -292 String nameLower = name.toLowerCase(); -293 RootCommand rootCommand = manager.obtainRootCommand(nameLower); -294 rootCommand.addChild(cmd); +159 registerSubclasses(cmd); +160 +161 } +162 +163 private void registerSubclasses(String cmd) { +164 for (Class<?> clazz : this.getClass().getDeclaredClasses()) { +165 if (BaseCommand.class.isAssignableFrom(clazz)) { +166 try { +167 BaseCommand subCommand = null; +168 Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors(); +169 for (Constructor<?> declaredConstructor : declaredConstructors) { +170 +171 declaredConstructor.setAccessible(true); +172 Parameter[] parameters = declaredConstructor.getParameters(); +173 if (parameters.length == 1) { +174 subCommand = (BaseCommand) declaredConstructor.newInstance(this); +175 } else { +176 manager.log(LogLevel.INFO, "Found unusable constructor: " + declaredConstructor.getName() + "(" + Stream.of(parameters).map(p -> p.getType().getSimpleName() + " " + p.getName()).collect(Collectors.joining("<c2>,</c2> ")) + ")"); +177 } +178 } +179 if (subCommand != null) { +180 subCommand.setParentCommand(this); +181 subCommand.onRegister(manager, cmd); +182 this.subCommands.putAll(subCommand.subCommands); +183 this.registeredCommands.putAll(subCommand.registeredCommands); +184 } else { +185 this.manager.log(LogLevel.ERROR, "Could not find a subcommand ctor for " + clazz.getName()); +186 } +187 } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { +188 this.manager.log(LogLevel.ERROR, "Error registering subclass", e); +189 } +190 } +191 } +192 } +193 +194 private void registerSubcommands() { +195 final Annotations annotations = manager.getAnnotations(); +196 boolean foundDefault = false; +197 boolean foundCatchUnknown = false; +198 boolean isParentEmpty = parentSubcommand.isEmpty(); +199 +200 for (Method method : this.getClass().getMethods()) { +201 method.setAccessible(true); +202 String sublist = null; +203 String sub = getSubcommandValue(method); +204 final boolean def = annotations.hasAnnotation(method, Default.class); +205 final String helpCommand = annotations.getAnnotationValue(method, HelpCommand.class, Annotations.NOTHING); +206 final String commandAliases = annotations.getAnnotationValue(method, CommandAlias.class, Annotations.NOTHING); +207 +208 if (!isParentEmpty && def) { +209 sub = parentSubcommand; +210 } +211 if (isParentEmpty && (def || (!foundDefault && helpCommand != null))) { +212 if (!foundDefault) { +213 if (def) { +214 this.subCommands.get(DEFAULT).clear(); +215 foundDefault = true; +216 } +217 registerSubcommand(method, DEFAULT); +218 } else { +219 ACFUtil.sneaky(new IllegalStateException("Multiple @Default/@HelpCommand commands, duplicate on " + method.getDeclaringClass().getName() + "#" + method.getName())); +220 } +221 } +222 +223 if (sub != null) { +224 sublist = sub; +225 } else if (commandAliases != null) { +226 sublist = commandAliases; +227 } else if (helpCommand != null) { +228 sublist = helpCommand; +229 } +230 +231 boolean preCommand = annotations.hasAnnotation(method, PreCommand.class); +232 boolean hasCatchUnknown = annotations.hasAnnotation(method, CatchUnknown.class) || +233 annotations.hasAnnotation(method, CatchAll.class) || +234 annotations.hasAnnotation(method, UnknownHandler.class); +235 +236 if (hasCatchUnknown || (!foundCatchUnknown && helpCommand != null)) { +237 if (!foundCatchUnknown) { +238 if (hasCatchUnknown) { +239 this.subCommands.get(CATCHUNKNOWN).clear(); +240 foundCatchUnknown = true; +241 } +242 registerSubcommand(method, CATCHUNKNOWN); +243 } else { +244 ACFUtil.sneaky(new IllegalStateException("Multiple @UnknownHandler/@HelpCommand commands, duplicate on " + method.getDeclaringClass().getName() + "#" + method.getName())); +245 } +246 } else if (preCommand) { +247 if (this.preCommandHandler == null) { +248 this.preCommandHandler = method; +249 } else { +250 ACFUtil.sneaky(new IllegalStateException("Multiple @PreCommand commands, duplicate on " + method.getDeclaringClass().getName() + "#" + method.getName())); +251 } +252 } +253 if (Objects.equals(method.getDeclaringClass(), this.getClass()) && sublist != null) { +254 registerSubcommand(method, sublist); +255 } +256 } +257 } +258 +259 private String getSubcommandValue(Method method) { +260 final String sub = manager.getAnnotations().getAnnotationValue(method, Subcommand.class, Annotations.NOTHING); +261 if (sub == null) { +262 return null; +263 } +264 Class<?> clazz = method.getDeclaringClass(); +265 String parent = getParentSubcommand(clazz); +266 return parent == null || parent.isEmpty() ? sub : parent + " " + sub; +267 } +268 +269 private String getParentSubcommand(Class<?> clazz) { +270 List<String> subList = new ArrayList<>(); +271 while (clazz != null) { +272 String sub = manager.getAnnotations().getAnnotationValue(clazz, Subcommand.class, Annotations.NOTHING); +273 if (sub != null) { +274 subList.add(sub); +275 } +276 clazz = clazz.getEnclosingClass(); +277 } +278 Collections.reverse(subList); +279 return ACFUtil.join(subList, " "); +280 } +281 +282 private void register(String name, BaseCommand cmd) { +283 String nameLower = name.toLowerCase(); +284 RootCommand rootCommand = manager.obtainRootCommand(nameLower); +285 rootCommand.addChild(cmd); +286 +287 this.registeredCommands.put(nameLower, rootCommand); +288 } +289 +290 private void registerSubcommand(Method method, String subCommand) { +291 subCommand = manager.getCommandReplacements().replace(subCommand.toLowerCase()); +292 final String[] subCommandParts = ACFPatterns.SPACE.split(subCommand); +293 // Must run getSubcommandPossibility BEFORE we rewrite it just after this. +294 Set<String> cmdList = getSubCommandPossibilityList(subCommandParts); 295 -296 this.registeredCommands.put(nameLower, rootCommand); -297 } -298 -299 private void registerSubcommand(Method method, String subCommand) { -300 subCommand = manager.getCommandReplacements().replace(subCommand.toLowerCase()); -301 final String[] subCommandParts = ACFPatterns.SPACE.split(subCommand); -302 // Must run getSubcommandPossibility BEFORE we rewrite it just after this. -303 Set<String> cmdList = getSubCommandPossibilityList(subCommandParts); -304 -305 // Strip pipes off for auto complete addition -306 for (int i = 0; i < subCommandParts.length; i++) { -307 String[] split = ACFPatterns.PIPE.split(subCommandParts[i]); -308 if (split.length == 0 || split[0].isEmpty()) { -309 throw new IllegalArgumentException("Invalid @Subcommand configuration for " + method.getName() + " - parts can not start with | or be empty"); -310 } -311 subCommandParts[i] = split[0]; +296 // Strip pipes off for auto complete addition +297 for (int i = 0; i < subCommandParts.length; i++) { +298 String[] split = ACFPatterns.PIPE.split(subCommandParts[i]); +299 if (split.length == 0 || split[0].isEmpty()) { +300 throw new IllegalArgumentException("Invalid @Subcommand configuration for " + method.getName() + " - parts can not start with | or be empty"); +301 } +302 subCommandParts[i] = split[0]; +303 } +304 String prefSubCommand = ApacheCommonsLangUtil.join(subCommandParts, " "); +305 final String[] aliasNames = manager.getAnnotations().getAnnotationValues(method, CommandAlias.class, Annotations.REPLACEMENTS | Annotations.LOWERCASE); +306 +307 String cmdName = aliasNames != null ? aliasNames[0] : this.commandName + " "; +308 RegisteredCommand cmd = manager.createRegisteredCommand(this, cmdName, method, prefSubCommand); +309 +310 for (String subcmd : cmdList) { +311 subCommands.put(subcmd, cmd); 312 } -313 String prefSubCommand = ApacheCommonsLangUtil.join(subCommandParts, " "); -314 final String[] aliasNames = manager.getAnnotations().getAnnotationValues(method, CommandAlias.class, Annotations.REPLACEMENTS | Annotations.LOWERCASE); -315 -316 String cmdName = aliasNames != null ? aliasNames[0] : this.commandName + " "; -317 RegisteredCommand cmd = manager.createRegisteredCommand(this, cmdName, method, prefSubCommand); -318 -319 for (String subcmd : cmdList) { -320 subCommands.put(subcmd, cmd); -321 } -322 cmd.addSubcommands(cmdList); -323 -324 if (aliasNames != null) { -325 for (String name : aliasNames) { -326 register(name, new ForwardingCommand(this, subCommandParts)); -327 } -328 } -329 } -330 -331 /** -332 * Takes a string like "foo|bar baz|qux" and generates a list of -333 * - foo baz -334 * - foo qux -335 * - bar baz -336 * - bar qux -337 * -338 * For every possible sub command combination -339 * -340 * @param subCommandParts -341 * @return List of all sub command possibilities -342 */ -343 private static Set<String> getSubCommandPossibilityList(String[] subCommandParts) { -344 int i = 0; -345 Set<String> current = null; -346 while (true) { -347 Set<String> newList = new HashSet<>(); -348 -349 if (i < subCommandParts.length) { -350 for (String s1 : ACFPatterns.PIPE.split(subCommandParts[i])) { -351 if (current != null) { -352 newList.addAll(current.stream().map(s -> s + " " + s1).collect(Collectors.toList())); -353 } else { -354 newList.add(s1); -355 } -356 } -357 } -358 -359 if (i + 1 < subCommandParts.length) { -360 current = newList; -361 i = i + 1; -362 continue; -363 } +313 cmd.addSubcommands(cmdList); +314 +315 if (aliasNames != null) { +316 for (String name : aliasNames) { +317 register(name, new ForwardingCommand(this, subCommandParts)); +318 } +319 } +320 } +321 +322 /** +323 * Takes a string like "foo|bar baz|qux" and generates a list of +324 * - foo baz +325 * - foo qux +326 * - bar baz +327 * - bar qux +328 * +329 * For every possible sub command combination +330 * +331 * @param subCommandParts +332 * @return List of all sub command possibilities +333 */ +334 private static Set<String> getSubCommandPossibilityList(String[] subCommandParts) { +335 int i = 0; +336 Set<String> current = null; +337 while (true) { +338 Set<String> newList = new HashSet<>(); +339 +340 if (i < subCommandParts.length) { +341 for (String s1 : ACFPatterns.PIPE.split(subCommandParts[i])) { +342 if (current != null) { +343 newList.addAll(current.stream().map(s -> s + " " + s1).collect(Collectors.toList())); +344 } else { +345 newList.add(s1); +346 } +347 } +348 } +349 +350 if (i + 1 < subCommandParts.length) { +351 current = newList; +352 i = i + 1; +353 continue; +354 } +355 +356 return newList; +357 } +358 } +359 +360 public void execute(CommandIssuer issuer, String commandLabel, String[] args) { +361 commandLabel = commandLabel.toLowerCase(); +362 try { +363 CommandOperationContext commandContext = preCommandOperation(issuer, commandLabel, args, false); 364 -365 return newList; -366 } -367 } -368 -369 public void execute(CommandIssuer issuer, String commandLabel, String[] args) { -370 commandLabel = commandLabel.toLowerCase(); -371 try { -372 CommandOperationContext commandContext = preCommandOperation(issuer, commandLabel, args, false); -373 -374 if (args.length > 0) { -375 CommandSearch cmd = findSubCommand(args); -376 if (cmd != null) { -377 execSubcommand = cmd.getCheckSub(); -378 final String[] execargs = Arrays.copyOfRange(args, cmd.argIndex, args.length); -379 executeCommand(commandContext, issuer, execargs, cmd.cmd); -380 return; -381 } -382 } -383 -384 if (subCommands.get(DEFAULT) != null && args.length == 0) { -385 executeSubcommand(commandContext, DEFAULT, issuer, args); -386 } else if (subCommands.get(CATCHUNKNOWN) != null) { -387 if (!executeSubcommand(commandContext, CATCHUNKNOWN, issuer, args)) { -388 help(issuer, args); -389 } -390 } else if (subCommands.get(DEFAULT) != null) { -391 executeSubcommand(commandContext, DEFAULT, issuer, args); -392 } -393 -394 } finally { -395 postCommandOperation(); -396 } -397 } -398 -399 RegisteredCommand<?> getRegisteredCommand(String[] args) { -400 final CommandSearch cmd = findSubCommand(args); -401 return cmd != null ? cmd.cmd : null; -402 } -403 -404 private void postCommandOperation() { -405 CommandManager.commandOperationContext.get().pop(); -406 execSubcommand = null; -407 execLabel = null; -408 origArgs = new String[]{}; -409 } -410 -411 private CommandOperationContext preCommandOperation(CommandIssuer issuer, String commandLabel, String[] args, boolean isAsync) { -412 Stack<CommandOperationContext> contexts = CommandManager.commandOperationContext.get(); -413 CommandOperationContext context = this.manager.createCommandOperationContext(this, issuer, commandLabel, args, isAsync); -414 contexts.push(context); -415 lastCommandOperationContext = context; -416 execSubcommand = null; -417 execLabel = commandLabel; -418 origArgs = args; -419 return context; -420 } -421 -422 public CommandIssuer getCurrentCommandIssuer() { -423 return CommandManager.getCurrentCommandIssuer(); -424 } -425 public CommandManager getCurrentCommandManager() { -426 return CommandManager.getCurrentCommandManager(); -427 } -428 -429 private CommandSearch findSubCommand(String[] args) { -430 return findSubCommand(args, false); -431 } -432 private CommandSearch findSubCommand(String[] args, boolean completion) { -433 for (int i = args.length; i >= 0; i--) { -434 String checkSub = ApacheCommonsLangUtil.join(args, " ", 0, i).toLowerCase(); -435 Set<RegisteredCommand> cmds = subCommands.get(checkSub); -436 -437 final int extraArgs = args.length - i; -438 if (!cmds.isEmpty()) { -439 RegisteredCommand cmd = null; -440 if (cmds.size() == 1) { -441 cmd = Iterables.getOnlyElement(cmds); -442 } else { -443 Optional<RegisteredCommand> optCmd = cmds.stream().filter(c -> { -444 int required = c.requiredResolvers; -445 int optional = c.optionalResolvers; -446 return extraArgs <= required + optional && (completion || extraArgs >= required); -447 }).sorted((c1, c2) -> { -448 int a = c1.consumeInputResolvers; -449 int b = c2.consumeInputResolvers; -450 -451 if (a == b) { -452 return 0; -453 } -454 return a < b ? 1 : -1; -455 }).findFirst(); -456 if (optCmd.isPresent()) { -457 cmd = optCmd.get(); -458 } -459 } -460 if (cmd != null) { -461 return new CommandSearch(cmd, i, checkSub); -462 } -463 } -464 } -465 return null; -466 } -467 -468 private void executeCommand(CommandOperationContext commandOperationContext, -469 CommandIssuer issuer, String[] args, RegisteredCommand cmd) { -470 if (cmd.hasPermission(issuer)) { -471 commandOperationContext.setRegisteredCommand(cmd); -472 if (checkPrecommand(commandOperationContext, cmd, issuer, args)) { -473 return; -474 } -475 List<String> sargs = Lists.newArrayList(args); -476 cmd.invoke(issuer, sargs, commandOperationContext); -477 } else { -478 issuer.sendMessage(MessageType.ERROR, MessageKeys.PERMISSION_DENIED); -479 } -480 } -481 -482 public boolean canExecute(CommandIssuer issuer, RegisteredCommand<?> cmd) { -483 return true; -484 } -485 -486 public List<String> tabComplete(CommandIssuer issuer, String commandLabel, String[] args) { -487 return tabComplete(issuer, commandLabel, args, false); -488 } -489 public List<String> tabComplete(CommandIssuer issuer, String commandLabel, String[] args, boolean isAsync) -490 throws IllegalArgumentException { +365 if (args.length > 0) { +366 CommandSearch cmd = findSubCommand(args); +367 if (cmd != null) { +368 execSubcommand = cmd.getCheckSub(); +369 final String[] execargs = Arrays.copyOfRange(args, cmd.argIndex, args.length); +370 executeCommand(commandContext, issuer, execargs, cmd.cmd); +371 return; +372 } +373 } +374 +375 if (subCommands.get(DEFAULT) != null && args.length == 0) { +376 executeSubcommand(commandContext, DEFAULT, issuer, args); +377 } else if (subCommands.get(CATCHUNKNOWN) != null) { +378 if (!executeSubcommand(commandContext, CATCHUNKNOWN, issuer, args)) { +379 help(issuer, args); +380 } +381 } else if (subCommands.get(DEFAULT) != null) { +382 executeSubcommand(commandContext, DEFAULT, issuer, args); +383 } +384 +385 } finally { +386 postCommandOperation(); +387 } +388 } +389 +390 RegisteredCommand<?> getRegisteredCommand(String[] args) { +391 final CommandSearch cmd = findSubCommand(args); +392 return cmd != null ? cmd.cmd : null; +393 } +394 +395 private void postCommandOperation() { +396 CommandManager.commandOperationContext.get().pop(); +397 execSubcommand = null; +398 execLabel = null; +399 origArgs = new String[]{}; +400 } +401 +402 private CommandOperationContext preCommandOperation(CommandIssuer issuer, String commandLabel, String[] args, boolean isAsync) { +403 Stack<CommandOperationContext> contexts = CommandManager.commandOperationContext.get(); +404 CommandOperationContext context = this.manager.createCommandOperationContext(this, issuer, commandLabel, args, isAsync); +405 contexts.push(context); +406 lastCommandOperationContext = context; +407 execSubcommand = null; +408 execLabel = commandLabel; +409 origArgs = args; +410 return context; +411 } +412 +413 public CommandIssuer getCurrentCommandIssuer() { +414 return CommandManager.getCurrentCommandIssuer(); +415 } +416 public CommandManager getCurrentCommandManager() { +417 return CommandManager.getCurrentCommandManager(); +418 } +419 +420 private CommandSearch findSubCommand(String[] args) { +421 return findSubCommand(args, false); +422 } +423 private CommandSearch findSubCommand(String[] args, boolean completion) { +424 for (int i = args.length; i >= 0; i--) { +425 String checkSub = ApacheCommonsLangUtil.join(args, " ", 0, i).toLowerCase(); +426 Set<RegisteredCommand> cmds = subCommands.get(checkSub); +427 +428 final int extraArgs = args.length - i; +429 if (!cmds.isEmpty()) { +430 RegisteredCommand cmd = null; +431 if (cmds.size() == 1) { +432 cmd = Iterables.getOnlyElement(cmds); +433 } else { +434 Optional<RegisteredCommand> optCmd = cmds.stream().filter(c -> { +435 int required = c.requiredResolvers; +436 int optional = c.optionalResolvers; +437 return extraArgs <= required + optional && (completion || extraArgs >= required); +438 }).sorted((c1, c2) -> { +439 int a = c1.consumeInputResolvers; +440 int b = c2.consumeInputResolvers; +441 +442 if (a == b) { +443 return 0; +444 } +445 return a < b ? 1 : -1; +446 }).findFirst(); +447 if (optCmd.isPresent()) { +448 cmd = optCmd.get(); +449 } +450 } +451 if (cmd != null) { +452 return new CommandSearch(cmd, i, checkSub); +453 } +454 } +455 } +456 return null; +457 } +458 +459 private void executeCommand(CommandOperationContext commandOperationContext, +460 CommandIssuer issuer, String[] args, RegisteredCommand cmd) { +461 if (cmd.hasPermission(issuer)) { +462 commandOperationContext.setRegisteredCommand(cmd); +463 if (checkPrecommand(commandOperationContext, cmd, issuer, args)) { +464 return; +465 } +466 List<String> sargs = Lists.newArrayList(args); +467 cmd.invoke(issuer, sargs, commandOperationContext); +468 } else { +469 issuer.sendMessage(MessageType.ERROR, MessageKeys.PERMISSION_DENIED); +470 } +471 } +472 +473 public boolean canExecute(CommandIssuer issuer, RegisteredCommand<?> cmd) { +474 return true; +475 } +476 +477 public List<String> tabComplete(CommandIssuer issuer, String commandLabel, String[] args) { +478 return tabComplete(issuer, commandLabel, args, false); +479 } +480 public List<String> tabComplete(CommandIssuer issuer, String commandLabel, String[] args, boolean isAsync) +481 throws IllegalArgumentException { +482 +483 commandLabel = commandLabel.toLowerCase(); +484 if (args.length == 0) { +485 args = new String[]{""}; +486 } +487 try { +488 CommandOperationContext commandOperationContext = preCommandOperation(issuer, commandLabel, args, isAsync); +489 +490 final CommandSearch search = findSubCommand(args, true); 491 -492 commandLabel = commandLabel.toLowerCase(); -493 if (args.length == 0) { -494 args = new String[]{""}; -495 } -496 try { -497 CommandOperationContext commandOperationContext = preCommandOperation(issuer, commandLabel, args, isAsync); -498 -499 final CommandSearch search = findSubCommand(args, true); -500 -501 -502 final List<String> cmds = new ArrayList<>(); -503 -504 if (search != null) { -505 cmds.addAll(completeCommand(issuer, search.cmd, Arrays.copyOfRange(args, search.argIndex, args.length), commandLabel, isAsync)); -506 } else if (subCommands.get(CATCHUNKNOWN).size() == 1) { -507 cmds.addAll(completeCommand(issuer, Iterables.getOnlyElement(subCommands.get(CATCHUNKNOWN)), args, commandLabel, isAsync)); -508 } else if (subCommands.get(DEFAULT).size() == 1) { -509 cmds.addAll(completeCommand(issuer, Iterables.getOnlyElement(subCommands.get(DEFAULT)), args, commandLabel, isAsync)); -510 } -511 -512 return filterTabComplete(args[args.length - 1], cmds); -513 } finally { -514 postCommandOperation(); -515 } -516 } -517 -518 List<String> getCommandsForCompletion(CommandIssuer issuer, String[] args) { -519 final Set<String> cmds = new HashSet<>(); -520 final int cmdIndex = Math.max(0, args.length - 1); -521 String argString = ApacheCommonsLangUtil.join(args, " ").toLowerCase(); -522 for (Map.Entry<String, RegisteredCommand> entry : subCommands.entries()) { -523 final String key = entry.getKey(); -524 if (key.startsWith(argString) && !CATCHUNKNOWN.equals(key) && !DEFAULT.equals(key)) { -525 final RegisteredCommand value = entry.getValue(); -526 if (!value.hasPermission(issuer)) { -527 continue; -528 } -529 -530 String[] split = ACFPatterns.SPACE.split(value.prefSubCommand); -531 cmds.add(split[cmdIndex]); -532 } -533 } -534 return new ArrayList<>(cmds); +492 +493 final List<String> cmds = new ArrayList<>(); +494 +495 if (search != null) { +496 cmds.addAll(completeCommand(issuer, search.cmd, Arrays.copyOfRange(args, search.argIndex, args.length), commandLabel, isAsync)); +497 } else if (subCommands.get(CATCHUNKNOWN).size() == 1) { +498 cmds.addAll(completeCommand(issuer, Iterables.getOnlyElement(subCommands.get(CATCHUNKNOWN)), args, commandLabel, isAsync)); +499 } else if (subCommands.get(DEFAULT).size() == 1) { +500 cmds.addAll(completeCommand(issuer, Iterables.getOnlyElement(subCommands.get(DEFAULT)), args, commandLabel, isAsync)); +501 } +502 +503 return filterTabComplete(args[args.length - 1], cmds); +504 } finally { +505 postCommandOperation(); +506 } +507 } +508 +509 List<String> getCommandsForCompletion(CommandIssuer issuer, String[] args) { +510 final Set<String> cmds = new HashSet<>(); +511 final int cmdIndex = Math.max(0, args.length - 1); +512 String argString = ApacheCommonsLangUtil.join(args, " ").toLowerCase(); +513 for (Map.Entry<String, RegisteredCommand> entry : subCommands.entries()) { +514 final String key = entry.getKey(); +515 if (key.startsWith(argString) && !CATCHUNKNOWN.equals(key) && !DEFAULT.equals(key)) { +516 final RegisteredCommand value = entry.getValue(); +517 if (!value.hasPermission(issuer)) { +518 continue; +519 } +520 +521 String[] split = ACFPatterns.SPACE.split(value.prefSubCommand); +522 cmds.add(split[cmdIndex]); +523 } +524 } +525 return new ArrayList<>(cmds); +526 } +527 +528 private List<String> completeCommand(CommandIssuer issuer, RegisteredCommand cmd, String[] args, String commandLabel, boolean isAsync) { +529 if (!cmd.hasPermission(issuer) || args.length > cmd.consumeInputResolvers || args.length == 0 || cmd.complete == null) { +530 return ImmutableList.of(); +531 } +532 +533 List<String> cmds = manager.getCommandCompletions().of(cmd, issuer, args, isAsync); +534 return filterTabComplete(args[args.length-1], cmds); 535 } 536 -537 private List<String> completeCommand(CommandIssuer issuer, RegisteredCommand cmd, String[] args, String commandLabel, boolean isAsync) { -538 if (!cmd.hasPermission(issuer) || args.length > cmd.consumeInputResolvers || args.length == 0 || cmd.complete == null) { -539 return ImmutableList.of(); -540 } -541 -542 List<String> cmds = manager.getCommandCompletions().of(cmd, issuer, args, isAsync); -543 return filterTabComplete(args[args.length-1], cmds); -544 } -545 -546 private static List<String> filterTabComplete(String arg, List<String> cmds) { -547 return cmds.stream() -548 .distinct() -549 .filter(cmd -> cmd != null && (arg.isEmpty() || ApacheCommonsLangUtil.startsWithIgnoreCase(cmd, arg))) -550 .collect(Collectors.toList()); -551 } -552 -553 RegisteredCommand getSubcommand(String subcommand) { -554 return getSubcommand(subcommand, false); -555 } -556 -557 RegisteredCommand getSubcommand(String subcommand, boolean requireOne) { -558 final Set<RegisteredCommand> commands = subCommands.get(subcommand); -559 if (!commands.isEmpty() && (!requireOne || commands.size() == 1)) { -560 return commands.iterator().next(); +537 private static List<String> filterTabComplete(String arg, List<String> cmds) { +538 return cmds.stream() +539 .distinct() +540 .filter(cmd -> cmd != null && (arg.isEmpty() || ApacheCommonsLangUtil.startsWithIgnoreCase(cmd, arg))) +541 .collect(Collectors.toList()); +542 } +543 +544 RegisteredCommand getSubcommand(String subcommand) { +545 return getSubcommand(subcommand, false); +546 } +547 +548 RegisteredCommand getSubcommand(String subcommand, boolean requireOne) { +549 final Set<RegisteredCommand> commands = subCommands.get(subcommand); +550 if (!commands.isEmpty() && (!requireOne || commands.size() == 1)) { +551 return commands.iterator().next(); +552 } +553 return null; +554 } +555 +556 private boolean executeSubcommand(CommandOperationContext commandContext, String subcommand, CommandIssuer issuer, String... args) { +557 final RegisteredCommand cmd = this.getSubcommand(subcommand); +558 if (cmd != null) { +559 executeCommand(commandContext, issuer, args, cmd); +560 return true; 561 } -562 return null; -563 } -564 -565 private boolean executeSubcommand(CommandOperationContext commandContext, String subcommand, CommandIssuer issuer, String... args) { -566 final RegisteredCommand cmd = this.getSubcommand(subcommand); -567 if (cmd != null) { -568 executeCommand(commandContext, issuer, args, cmd); -569 return true; -570 } -571 -572 return false; -573 } -574 -575 private boolean checkPrecommand(CommandOperationContext commandOperationContext, RegisteredCommand cmd, CommandIssuer issuer, String[] args) { -576 Method pre = this.preCommandReflectiveHandler; -577 if (pre != null) { -578 try { -579 Class<?>[] types = pre.getParameterTypes(); -580 Object[] parameters = new Object[pre.getParameterCount()]; -581 for (int i = 0; i < parameters.length; i++) { -582 Class<?> type = types[i]; -583 Object issuerObject = issuer.getIssuer(); -584 if (manager.isCommandIssuer(type) && type.isAssignableFrom(issuerObject.getClass())) { -585 parameters[i] = issuerObject; -586 } else if (CommandIssuer.class.isAssignableFrom(type)) { -587 parameters[i] = issuer; -588 } else if (RegisteredCommand.class.isAssignableFrom(type)) { -589 parameters[i] = cmd; -590 } else if (String[].class.isAssignableFrom((type))) { -591 parameters[i] = args; -592 } else { -593 parameters[i] = null; -594 } -595 } -596 -597 if (false) { // preCommandHandler != null) { //TODO: MethodHandle disabled due to WrongMethodTypeException -598 return (boolean) preCommandHandler.invoke(parameters); -599 } -600 return (boolean) pre.invoke(this, parameters); -601 } catch (Throwable e) { -602 this.manager.log(LogLevel.ERROR, "Exception encountered while command pre-processing", e); -603 } -604 } -605 return false; -606 } -607 -608 /** @deprecated Unstable API */ @Deprecated @UnstableAPI -609 public CommandHelp getCommandHelp() { -610 return manager.generateCommandHelp(); +562 +563 return false; +564 } +565 +566 private boolean checkPrecommand(CommandOperationContext commandOperationContext, RegisteredCommand cmd, CommandIssuer issuer, String[] args) { +567 Method pre = this.preCommandHandler; +568 if (pre != null) { +569 try { +570 Class<?>[] types = pre.getParameterTypes(); +571 Object[] parameters = new Object[pre.getParameterCount()]; +572 for (int i = 0; i < parameters.length; i++) { +573 Class<?> type = types[i]; +574 Object issuerObject = issuer.getIssuer(); +575 if (manager.isCommandIssuer(type) && type.isAssignableFrom(issuerObject.getClass())) { +576 parameters[i] = issuerObject; +577 } else if (CommandIssuer.class.isAssignableFrom(type)) { +578 parameters[i] = issuer; +579 } else if (RegisteredCommand.class.isAssignableFrom(type)) { +580 parameters[i] = cmd; +581 } else if (String[].class.isAssignableFrom((type))) { +582 parameters[i] = args; +583 } else { +584 parameters[i] = null; +585 } +586 } +587 +588 return (boolean) pre.invoke(this, parameters); +589 } catch (IllegalAccessException | InvocationTargetException e) { +590 this.manager.log(LogLevel.ERROR, "Exception encountered while command pre-processing", e); +591 } +592 } +593 return false; +594 } +595 +596 /** @deprecated Unstable API */ @Deprecated @UnstableAPI +597 public CommandHelp getCommandHelp() { +598 return manager.generateCommandHelp(); +599 } +600 +601 /** @deprecated Unstable API */ @Deprecated @UnstableAPI +602 public void showCommandHelp() { +603 getCommandHelp().showHelp(); +604 } +605 +606 public void help(Object issuer, String[] args) { +607 help(manager.getCommandIssuer(issuer), args); +608 } +609 public void help(CommandIssuer issuer, String[] args) { +610 issuer.sendMessage(MessageType.ERROR, MessageKeys.UNKNOWN_COMMAND); 611 } -612 -613 /** @deprecated Unstable API */ @Deprecated @UnstableAPI -614 public void showCommandHelp() { -615 getCommandHelp().showHelp(); -616 } -617 -618 public void help(Object issuer, String[] args) { -619 help(manager.getCommandIssuer(issuer), args); -620 } -621 public void help(CommandIssuer issuer, String[] args) { -622 issuer.sendMessage(MessageType.ERROR, MessageKeys.UNKNOWN_COMMAND); -623 } -624 public void doHelp(Object issuer, String... args) { -625 doHelp(manager.getCommandIssuer(issuer), args); -626 } -627 public void doHelp(CommandIssuer issuer, String... args) { -628 help(issuer, args); -629 } -630 -631 public void showSyntax(CommandIssuer issuer, RegisteredCommand<?> cmd) { -632 issuer.sendMessage(MessageType.SYNTAX, MessageKeys.INVALID_SYNTAX, -633 "{command}", manager.getCommandPrefix(issuer) + cmd.command, -634 "{syntax}", cmd.syntaxText -635 ); -636 } -637 -638 public boolean hasPermission(Object issuer) { -639 return hasPermission(manager.getCommandIssuer(issuer)); +612 public void doHelp(Object issuer, String... args) { +613 doHelp(manager.getCommandIssuer(issuer), args); +614 } +615 public void doHelp(CommandIssuer issuer, String... args) { +616 help(issuer, args); +617 } +618 +619 public void showSyntax(CommandIssuer issuer, RegisteredCommand<?> cmd) { +620 issuer.sendMessage(MessageType.SYNTAX, MessageKeys.INVALID_SYNTAX, +621 "{command}", manager.getCommandPrefix(issuer) + cmd.command, +622 "{syntax}", cmd.syntaxText +623 ); +624 } +625 +626 public boolean hasPermission(Object issuer) { +627 return hasPermission(manager.getCommandIssuer(issuer)); +628 } +629 +630 public boolean hasPermission(CommandIssuer issuer) { +631 return permission == null || permission.isEmpty() || (manager.hasPermission(issuer, permission) && (parentCommand == null || parentCommand.hasPermission(issuer))); +632 } +633 +634 +635 public Set<String> getRequiredPermissions() { +636 if (this.permission == null || this.permission.isEmpty()) { +637 return ImmutableSet.of(); +638 } +639 return Sets.newHashSet(ACFPatterns.COMMA.split(this.permission)); 640 } 641 -642 public boolean hasPermission(CommandIssuer issuer) { -643 return permission == null || permission.isEmpty() || (manager.hasPermission(issuer, permission) && (parentCommand == null || parentCommand.hasPermission(issuer))); +642 public boolean requiresPermission(String permission) { +643 return getRequiredPermissions().contains(permission) || this.parentCommand != null && parentCommand.requiresPermission(permission); 644 } 645 -646 -647 public Set<String> getRequiredPermissions() { -648 if (this.permission == null || this.permission.isEmpty()) { -649 return ImmutableSet.of(); -650 } -651 return Sets.newHashSet(ACFPatterns.COMMA.split(this.permission)); +646 public String getName() { +647 return commandName; +648 } +649 +650 public ExceptionHandler getExceptionHandler() { +651 return exceptionHandler; 652 } 653 -654 public boolean requiresPermission(String permission) { -655 return getRequiredPermissions().contains(permission) || this.parentCommand != null && parentCommand.requiresPermission(permission); -656 } -657 -658 public String getName() { -659 return commandName; -660 } -661 -662 public ExceptionHandler getExceptionHandler() { -663 return exceptionHandler; -664 } -665 -666 public BaseCommand setExceptionHandler(ExceptionHandler exceptionHandler) { -667 this.exceptionHandler = exceptionHandler; -668 return this; +654 public BaseCommand setExceptionHandler(ExceptionHandler exceptionHandler) { +655 this.exceptionHandler = exceptionHandler; +656 return this; +657 } +658 +659 public RegisteredCommand getDefaultRegisteredCommand() { +660 return this.getSubcommand(DEFAULT); +661 } +662 +663 public String setContextFlags(Class<?> cls, String flags) { +664 return this.contextFlags.put(cls, flags); +665 } +666 +667 public String getContextFlags(Class<?> cls) { +668 return this.contextFlags.get(cls); 669 } 670 -671 public RegisteredCommand getDefaultRegisteredCommand() { -672 return this.getSubcommand(DEFAULT); -673 } -674 -675 public String setContextFlags(Class<?> cls, String flags) { -676 return this.contextFlags.put(cls, flags); -677 } +671 private static class CommandSearch { RegisteredCommand cmd; int argIndex; String checkSub; +672 +673 CommandSearch(RegisteredCommand cmd, int argIndex, String checkSub) { +674 this.cmd = cmd; +675 this.argIndex = argIndex; +676 this.checkSub = checkSub; +677 } 678 -679 public String getContextFlags(Class<?> cls) { -680 return this.contextFlags.get(cls); -681 } +679 String getCheckSub() { +680 return this.checkSub; +681 } 682 -683 private static class CommandSearch { RegisteredCommand cmd; int argIndex; String checkSub; -684 -685 CommandSearch(RegisteredCommand cmd, int argIndex, String checkSub) { -686 this.cmd = cmd; -687 this.argIndex = argIndex; -688 this.checkSub = checkSub; -689 } -690 -691 String getCheckSub() { -692 return this.checkSub; -693 } -694 -695 @Override -696 public boolean equals(Object o) { -697 if (this == o) return true; -698 if (o == null || getClass() != o.getClass()) return false; -699 CommandSearch that = (CommandSearch) o; -700 return argIndex == that.argIndex && -701 Objects.equals(cmd, that.cmd) && -702 Objects.equals(checkSub, that.checkSub); -703 } -704 -705 @Override -706 public int hashCode() { -707 return Objects.hash(cmd, argIndex, checkSub); -708 } -709 } -710} +683 @Override +684 public boolean equals(Object o) { +685 if (this == o) return true; +686 if (o == null || getClass() != o.getClass()) return false; +687 CommandSearch that = (CommandSearch) o; +688 return argIndex == that.argIndex && +689 Objects.equals(cmd, that.cmd) && +690 Objects.equals(checkSub, that.checkSub); +691 } +692 +693 @Override +694 public int hashCode() { +695 return Objects.hash(cmd, argIndex, checkSub); +696 } +697 } +698} diff --git a/docs/acf-core/src-html/co/aikar/commands/RegisteredCommand.html b/docs/acf-core/src-html/co/aikar/commands/RegisteredCommand.html index 1f4356f4..99c9e7d0 100644 --- a/docs/acf-core/src-html/co/aikar/commands/RegisteredCommand.html +++ b/docs/acf-core/src-html/co/aikar/commands/RegisteredCommand.html @@ -45,288 +45,272 @@ 037import com.google.common.collect.Sets; 038import org.jetbrains.annotations.Nullable; 039 -040import java.lang.invoke.MethodHandle; -041import java.lang.invoke.MethodHandles; -042import java.lang.reflect.InvocationTargetException; -043import java.lang.reflect.Method; -044import java.lang.reflect.Parameter; -045import java.util.ArrayList; -046import java.util.Collection; -047import java.util.List; -048import java.util.Map; -049import java.util.Set; -050import java.util.stream.Collectors; -051 -052@SuppressWarnings("WeakerAccess") -053public class RegisteredCommand <CEC extends CommandExecutionContext<CEC, ? extends CommandIssuer>> { -054 final BaseCommand scope; -055 final Method method; -056 @Nullable final MethodHandle methodHandle; -057 final CommandParameter<CEC>[] parameters; -058 final CommandManager manager; -059 final List<String> registeredSubcommands = new ArrayList<>(); -060 -061 String command; -062 String prefSubCommand; -063 String syntaxText; -064 String helpText; -065 String permission; -066 String complete; -067 String conditions; -068 public String helpSearchTags; -069 -070 final int requiredResolvers; -071 final int consumeInputResolvers; -072 final int doesNotConsumeInputResolvers; -073 final int optionalResolvers; -074 -075 RegisteredCommand(BaseCommand scope, String command, Method method, String prefSubCommand) { -076 this.scope = scope; -077 this.manager = this.scope.manager; -078 final Annotations annotations = this.manager.getAnnotations(); -079 -080 if (BaseCommand.CATCHUNKNOWN.equals(prefSubCommand) || BaseCommand.DEFAULT.equals(prefSubCommand)) { -081 prefSubCommand = ""; -082 } -083 this.command = command + (!annotations.hasAnnotation(method, CommandAlias.class, false) && !prefSubCommand.isEmpty() ? prefSubCommand : ""); -084 this.method = method; -085 MethodHandle methodHandle = null; -086 try { -087 methodHandle = MethodHandles.lookup().unreflect(method); -088 } catch (IllegalAccessException ignored) { -089 // As the method has been found, it cannot not have permission for it. -090 // In the case that it does however manage to fail this, keep it null and handle it later on. -091 } -092 this.methodHandle = methodHandle; -093 this.prefSubCommand = prefSubCommand; +040import java.lang.reflect.InvocationTargetException; +041import java.lang.reflect.Method; +042import java.lang.reflect.Parameter; +043import java.util.ArrayList; +044import java.util.Collection; +045import java.util.List; +046import java.util.Map; +047import java.util.Set; +048import java.util.stream.Collectors; +049 +050@SuppressWarnings("WeakerAccess") +051public class RegisteredCommand <CEC extends CommandExecutionContext<CEC, ? extends CommandIssuer>> { +052 final BaseCommand scope; +053 final Method method; +054 final CommandParameter<CEC>[] parameters; +055 final CommandManager manager; +056 final List<String> registeredSubcommands = new ArrayList<>(); +057 +058 String command; +059 String prefSubCommand; +060 String syntaxText; +061 String helpText; +062 String permission; +063 String complete; +064 String conditions; +065 public String helpSearchTags; +066 +067 final int requiredResolvers; +068 final int consumeInputResolvers; +069 final int doesNotConsumeInputResolvers; +070 final int optionalResolvers; +071 +072 RegisteredCommand(BaseCommand scope, String command, Method method, String prefSubCommand) { +073 this.scope = scope; +074 this.manager = this.scope.manager; +075 final Annotations annotations = this.manager.getAnnotations(); +076 +077 if (BaseCommand.CATCHUNKNOWN.equals(prefSubCommand) || BaseCommand.DEFAULT.equals(prefSubCommand)) { +078 prefSubCommand = ""; +079 } +080 this.command = command + (!annotations.hasAnnotation(method, CommandAlias.class, false) && !prefSubCommand.isEmpty() ? prefSubCommand : ""); +081 this.method = method; +082 this.prefSubCommand = prefSubCommand; +083 +084 this.permission = annotations.getAnnotationValue(method, CommandPermission.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY); +085 this.complete = annotations.getAnnotationValue(method, CommandCompletion.class); +086 this.helpText = annotations.getAnnotationValue(method, Description.class, Annotations.REPLACEMENTS | Annotations.DEFAULT_EMPTY); +087 this.conditions = annotations.getAnnotationValue(method, Conditions.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY); +088 this.helpSearchTags = annotations.getAnnotationValue(method, HelpSearchTags.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY); +089 +090 Parameter[] parameters = method.getParameters(); +091 //noinspection unchecked +092 this.parameters = new CommandParameter[parameters.length]; +093 094 -095 this.permission = annotations.getAnnotationValue(method, CommandPermission.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY); -096 this.complete = annotations.getAnnotationValue(method, CommandCompletion.class); -097 this.helpText = annotations.getAnnotationValue(method, Description.class, Annotations.REPLACEMENTS | Annotations.DEFAULT_EMPTY); -098 this.conditions = annotations.getAnnotationValue(method, Conditions.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY); -099 this.helpSearchTags = annotations.getAnnotationValue(method, HelpSearchTags.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY); +095 int requiredResolvers = 0; +096 int consumeInputResolvers = 0; +097 int doesNotConsumeInputResolvers = 0; +098 int optionalResolvers = 0; +099 StringBuilder syntaxBuilder = new StringBuilder(64); 100 -101 Parameter[] parameters = method.getParameters(); -102 //noinspection unchecked -103 this.parameters = new CommandParameter[parameters.length]; -104 -105 -106 int requiredResolvers = 0; -107 int consumeInputResolvers = 0; -108 int doesNotConsumeInputResolvers = 0; -109 int optionalResolvers = 0; -110 StringBuilder syntaxBuilder = new StringBuilder(64); -111 -112 for (int i = 0; i < parameters.length; i++) { -113 CommandParameter<CEC> parameter = this.parameters[i] = new CommandParameter<>(this, parameters[i], i); -114 if (!parameter.isCommandIssuer()) { -115 if (!parameter.requiresInput()) { -116 optionalResolvers++; -117 } else { -118 requiredResolvers++; -119 } -120 if (parameter.canConsumeInput()) { -121 consumeInputResolvers++; -122 } else { -123 doesNotConsumeInputResolvers++; -124 } -125 } -126 if (parameter.getSyntax() != null) { -127 if (syntaxBuilder.length() > 0) { -128 syntaxBuilder.append(' '); -129 } -130 syntaxBuilder.append(parameter.getSyntax()); -131 } -132 } -133 String syntaxText = syntaxBuilder.toString().trim(); -134 final String syntaxStr = annotations.getAnnotationValue(method, Syntax.class); -135 this.syntaxText = syntaxStr != null ? ACFUtil.replace(syntaxStr, "@syntax", syntaxText) : syntaxText; -136 this.requiredResolvers = requiredResolvers; -137 this.consumeInputResolvers = consumeInputResolvers; -138 this.doesNotConsumeInputResolvers = doesNotConsumeInputResolvers; -139 this.optionalResolvers = optionalResolvers; -140 } +101 for (int i = 0; i < parameters.length; i++) { +102 CommandParameter<CEC> parameter = this.parameters[i] = new CommandParameter<>(this, parameters[i], i); +103 if (!parameter.isCommandIssuer()) { +104 if (!parameter.requiresInput()) { +105 optionalResolvers++; +106 } else { +107 requiredResolvers++; +108 } +109 if (parameter.canConsumeInput()) { +110 consumeInputResolvers++; +111 } else { +112 doesNotConsumeInputResolvers++; +113 } +114 } +115 if (parameter.getSyntax() != null) { +116 if (syntaxBuilder.length() > 0) { +117 syntaxBuilder.append(' '); +118 } +119 syntaxBuilder.append(parameter.getSyntax()); +120 } +121 } +122 String syntaxText = syntaxBuilder.toString().trim(); +123 final String syntaxStr = annotations.getAnnotationValue(method, Syntax.class); +124 this.syntaxText = syntaxStr != null ? ACFUtil.replace(syntaxStr, "@syntax", syntaxText) : syntaxText; +125 this.requiredResolvers = requiredResolvers; +126 this.consumeInputResolvers = consumeInputResolvers; +127 this.doesNotConsumeInputResolvers = doesNotConsumeInputResolvers; +128 this.optionalResolvers = optionalResolvers; +129 } +130 +131 +132 void invoke(CommandIssuer sender, List<String> args, CommandOperationContext context) { +133 if (!scope.canExecute(sender, this)) { +134 return; +135 } +136 preCommand(); +137 try { +138 this.manager.conditions.validateConditions(context); +139 Map<String, Object> passedArgs = resolveContexts(sender, args); +140 if (passedArgs == null) return; 141 -142 -143 void invoke(CommandIssuer sender, List<String> args, CommandOperationContext context) { -144 if (!scope.canExecute(sender, this)) { -145 return; -146 } -147 preCommand(); -148 try { -149 this.manager.conditions.validateConditions(context); -150 Map<String, Object> passedArgs = resolveContexts(sender, args); -151 if (passedArgs == null) return; -152 -153 if (false) {// methodHandle != null) { //TODO: MethodHandle disabled due to WrongMethodTypeException -154 methodHandle.invokeWithArguments(passedArgs.values().toArray()); -155 } else { -156 // The offchance the method handle wasn't unreflected, we're going to use the slower, working reflection. -157 method.invoke(scope, passedArgs.values().toArray()); -158 } -159 } catch (Throwable throwable) { -160 handleException(sender, args, throwable instanceof Exception ? (Exception) throwable : new Exception(throwable)); -161 } -162 postCommand(); -163 } -164 public void preCommand() {} -165 public void postCommand() {} -166 -167 void handleException(CommandIssuer sender, List<String> args, Exception e) { -168 if (e instanceof InvocationTargetException && e.getCause() instanceof InvalidCommandArgument) { -169 e = (Exception) e.getCause(); -170 } -171 if (e instanceof ShowCommandHelp) { -172 ShowCommandHelp showHelp = (ShowCommandHelp) e; -173 CommandHelp commandHelp = manager.generateCommandHelp(); -174 if (showHelp.search) { -175 commandHelp.setSearch(showHelp.searchArgs == null ? args : showHelp.searchArgs); -176 } -177 commandHelp.showHelp(sender); -178 } else if (e instanceof InvalidCommandArgument) { -179 InvalidCommandArgument invalidCommandArg = (InvalidCommandArgument) e; -180 if (invalidCommandArg.key != null) { -181 sender.sendMessage(MessageType.ERROR, invalidCommandArg.key, invalidCommandArg.replacements); -182 } else if (e.getMessage() != null && !e.getMessage().isEmpty()) { -183 sender.sendMessage(MessageType.ERROR, MessageKeys.ERROR_PREFIX, "{message}", e.getMessage()); -184 } -185 if (invalidCommandArg.showSyntax) { -186 scope.showSyntax(sender, this); -187 } -188 } else { -189 try { -190 if (!this.manager.handleUncaughtException(scope, this, sender, args, e)) { -191 sender.sendMessage(MessageType.ERROR, MessageKeys.ERROR_PERFORMING_COMMAND); -192 } -193 this.manager.log(LogLevel.ERROR, "Exception in command: " + command + " " + ACFUtil.join(args), e); -194 } catch (Exception e2) { -195 this.manager.log(LogLevel.ERROR, "Exception in handleException for command: " + command + " " + ACFUtil.join(args), e); -196 this.manager.log(LogLevel.ERROR, "Exception triggered by exception handler:", e2); -197 } -198 } -199 } -200 -201 @Nullable -202 Map<String, Object> resolveContexts(CommandIssuer sender, List<String> args) throws InvalidCommandArgument { -203 return resolveContexts(sender, args, parameters.length); -204 } -205 @Nullable -206 Map<String, Object> resolveContexts(CommandIssuer sender, List<String> args, int argLimit) throws InvalidCommandArgument { -207 args = Lists.newArrayList(args); -208 String[] origArgs = args.toArray(new String[args.size()]); -209 Map<String, Object> passedArgs = Maps.newLinkedHashMap(); -210 int remainingRequired = requiredResolvers; -211 CommandOperationContext opContext = CommandManager.getCurrentCommandOperationContext(); -212 for (int i = 0; i < parameters.length && i < argLimit; i++) { -213 boolean isLast = i == parameters.length - 1; -214 boolean allowOptional = remainingRequired == 0; -215 final CommandParameter<CEC> parameter = parameters[i]; -216 if (parameter.isCommandIssuer()) { -217 argLimit++; -218 } -219 final String parameterName = parameter.getName(); -220 final Class<?> type = parameter.getType(); -221 //noinspection unchecked -222 final ContextResolver<?, CEC> resolver = parameter.getResolver(); -223 //noinspection unchecked -224 CEC context = (CEC) this.manager.createCommandContext(this, parameter, sender, args, i, passedArgs); -225 boolean requiresInput = parameter.requiresInput(); -226 if (requiresInput && remainingRequired > 0) { -227 remainingRequired--; -228 } -229 if (args.isEmpty() && !(isLast && type == String[].class)) { -230 if (allowOptional && parameter.getDefaultValue() != null) { -231 args.add(parameter.getDefaultValue()); -232 } else if (allowOptional && parameter.isOptional()) { -233 Object value = parameter.isOptionalResolver() ? resolver.getContext(context) : null; -234 if (value == null && parameter.getClass().isPrimitive()) { -235 throw new IllegalStateException("Parameter " + parameter.getName() + " is primitive and does not support Optional."); -236 } +142 method.invoke(scope, passedArgs.values().toArray()); +143 } catch (Exception e) { +144 handleException(sender, args, e); +145 } +146 postCommand(); +147 } +148 public void preCommand() {} +149 public void postCommand() {} +150 +151 void handleException(CommandIssuer sender, List<String> args, Exception e) { +152 if (e instanceof InvocationTargetException && e.getCause() instanceof InvalidCommandArgument) { +153 e = (Exception) e.getCause(); +154 } +155 if (e instanceof ShowCommandHelp) { +156 ShowCommandHelp showHelp = (ShowCommandHelp) e; +157 CommandHelp commandHelp = manager.generateCommandHelp(); +158 if (showHelp.search) { +159 commandHelp.setSearch(showHelp.searchArgs == null ? args : showHelp.searchArgs); +160 } +161 commandHelp.showHelp(sender); +162 } else if (e instanceof InvalidCommandArgument) { +163 InvalidCommandArgument invalidCommandArg = (InvalidCommandArgument) e; +164 if (invalidCommandArg.key != null) { +165 sender.sendMessage(MessageType.ERROR, invalidCommandArg.key, invalidCommandArg.replacements); +166 } else if (e.getMessage() != null && !e.getMessage().isEmpty()) { +167 sender.sendMessage(MessageType.ERROR, MessageKeys.ERROR_PREFIX, "{message}", e.getMessage()); +168 } +169 if (invalidCommandArg.showSyntax) { +170 scope.showSyntax(sender, this); +171 } +172 } else { +173 try { +174 if (!this.manager.handleUncaughtException(scope, this, sender, args, e)) { +175 sender.sendMessage(MessageType.ERROR, MessageKeys.ERROR_PERFORMING_COMMAND); +176 } +177 this.manager.log(LogLevel.ERROR, "Exception in command: " + command + " " + ACFUtil.join(args), e); +178 } catch (Exception e2) { +179 this.manager.log(LogLevel.ERROR, "Exception in handleException for command: " + command + " " + ACFUtil.join(args), e); +180 this.manager.log(LogLevel.ERROR, "Exception triggered by exception handler:", e2); +181 } +182 } +183 } +184 +185 @Nullable +186 Map<String, Object> resolveContexts(CommandIssuer sender, List<String> args) throws InvalidCommandArgument { +187 return resolveContexts(sender, args, parameters.length); +188 } +189 @Nullable +190 Map<String, Object> resolveContexts(CommandIssuer sender, List<String> args, int argLimit) throws InvalidCommandArgument { +191 args = Lists.newArrayList(args); +192 String[] origArgs = args.toArray(new String[args.size()]); +193 Map<String, Object> passedArgs = Maps.newLinkedHashMap(); +194 int remainingRequired = requiredResolvers; +195 CommandOperationContext opContext = CommandManager.getCurrentCommandOperationContext(); +196 for (int i = 0; i < parameters.length && i < argLimit; i++) { +197 boolean isLast = i == parameters.length - 1; +198 boolean allowOptional = remainingRequired == 0; +199 final CommandParameter<CEC> parameter = parameters[i]; +200 if (parameter.isCommandIssuer()) { +201 argLimit++; +202 } +203 final String parameterName = parameter.getName(); +204 final Class<?> type = parameter.getType(); +205 //noinspection unchecked +206 final ContextResolver<?, CEC> resolver = parameter.getResolver(); +207 //noinspection unchecked +208 CEC context = (CEC) this.manager.createCommandContext(this, parameter, sender, args, i, passedArgs); +209 boolean requiresInput = parameter.requiresInput(); +210 if (requiresInput && remainingRequired > 0) { +211 remainingRequired--; +212 } +213 if (args.isEmpty() && !(isLast && type == String[].class)) { +214 if (allowOptional && parameter.getDefaultValue() != null) { +215 args.add(parameter.getDefaultValue()); +216 } else if (allowOptional && parameter.isOptional()) { +217 Object value = parameter.isOptionalResolver() ? resolver.getContext(context) : null; +218 if (value == null && parameter.getClass().isPrimitive()) { +219 throw new IllegalStateException("Parameter " + parameter.getName() + " is primitive and does not support Optional."); +220 } +221 //noinspection unchecked +222 this.manager.conditions.validateConditions(context, value); +223 passedArgs.put(parameterName, value); +224 //noinspection UnnecessaryContinue +225 continue; +226 } else if (requiresInput) { +227 scope.showSyntax(sender, this); +228 return null; +229 } +230 } +231 if (parameter.getValues() != null) { +232 String arg = !args.isEmpty() ? args.get(0) : ""; +233 +234 Set<String> possible = Sets.newHashSet(); +235 CommandCompletions commandCompletions = this.manager.getCommandCompletions(); +236 for (String s : parameter.getValues()) { 237 //noinspection unchecked -238 this.manager.conditions.validateConditions(context, value); -239 passedArgs.put(parameterName, value); -240 //noinspection UnnecessaryContinue -241 continue; -242 } else if (requiresInput) { -243 scope.showSyntax(sender, this); -244 return null; -245 } -246 } -247 if (parameter.getValues() != null) { -248 String arg = !args.isEmpty() ? args.get(0) : ""; -249 -250 Set<String> possible = Sets.newHashSet(); -251 CommandCompletions commandCompletions = this.manager.getCommandCompletions(); -252 for (String s : parameter.getValues()) { -253 //noinspection unchecked -254 List<String> check = commandCompletions.getCompletionValues(this, sender, s, origArgs, opContext.isAsync()); -255 if (!check.isEmpty()) { -256 possible.addAll(check.stream().map(String::toLowerCase).collect(Collectors.toList())); -257 } else { -258 possible.add(s.toLowerCase()); -259 } -260 } -261 -262 if (!possible.contains(arg.toLowerCase())) { -263 throw new InvalidCommandArgument(MessageKeys.PLEASE_SPECIFY_ONE_OF, -264 "{valid}", ACFUtil.join(possible, ", ")); -265 } -266 } -267 Object paramValue = resolver.getContext(context); -268 //noinspection unchecked -269 this.manager.conditions.validateConditions(context, paramValue); -270 passedArgs.put(parameterName, paramValue); -271 } -272 return passedArgs; -273 } -274 -275 boolean hasPermission(CommandIssuer issuer) { -276 return (permission == null || permission.isEmpty() || scope.manager.hasPermission(issuer, permission)) && scope.hasPermission(issuer); -277 } -278 -279 -280 /** -281 * @see #getRequiredPermissions() -282 * @deprecated -283 */ -284 @Deprecated -285 public String getPermission() { -286 if (this.permission == null || this.permission.isEmpty()) { -287 return null; -288 } -289 return ACFPatterns.COMMA.split(this.permission)[0]; -290 } -291 -292 public Set<String> getRequiredPermissions() { -293 if (this.permission == null || this.permission.isEmpty()) { -294 return ImmutableSet.of(); -295 } -296 return Sets.newHashSet(ACFPatterns.COMMA.split(this.permission)); +238 List<String> check = commandCompletions.getCompletionValues(this, sender, s, origArgs, opContext.isAsync()); +239 if (!check.isEmpty()) { +240 possible.addAll(check.stream().map(String::toLowerCase).collect(Collectors.toList())); +241 } else { +242 possible.add(s.toLowerCase()); +243 } +244 } +245 +246 if (!possible.contains(arg.toLowerCase())) { +247 throw new InvalidCommandArgument(MessageKeys.PLEASE_SPECIFY_ONE_OF, +248 "{valid}", ACFUtil.join(possible, ", ")); +249 } +250 } +251 Object paramValue = resolver.getContext(context); +252 //noinspection unchecked +253 this.manager.conditions.validateConditions(context, paramValue); +254 passedArgs.put(parameterName, paramValue); +255 } +256 return passedArgs; +257 } +258 +259 boolean hasPermission(CommandIssuer issuer) { +260 return (permission == null || permission.isEmpty() || scope.manager.hasPermission(issuer, permission)) && scope.hasPermission(issuer); +261 } +262 +263 +264 /** +265 * @see #getRequiredPermissions() +266 * @deprecated +267 */ +268 @Deprecated +269 public String getPermission() { +270 if (this.permission == null || this.permission.isEmpty()) { +271 return null; +272 } +273 return ACFPatterns.COMMA.split(this.permission)[0]; +274 } +275 +276 public Set<String> getRequiredPermissions() { +277 if (this.permission == null || this.permission.isEmpty()) { +278 return ImmutableSet.of(); +279 } +280 return Sets.newHashSet(ACFPatterns.COMMA.split(this.permission)); +281 } +282 +283 public boolean requiresPermission(String permission) { +284 return getRequiredPermissions().contains(permission) || scope.requiresPermission(permission); +285 } +286 +287 public String getPrefSubCommand() { +288 return prefSubCommand; +289 } +290 +291 public String getSyntaxText() { +292 return syntaxText; +293 } +294 +295 public String getCommand() { +296 return command; 297 } 298 -299 public boolean requiresPermission(String permission) { -300 return getRequiredPermissions().contains(permission) || scope.requiresPermission(permission); +299 public void addSubcommand(String cmd) { +300 this.registeredSubcommands.add(cmd); 301 } -302 -303 public String getPrefSubCommand() { -304 return prefSubCommand; -305 } -306 -307 public String getSyntaxText() { -308 return syntaxText; -309 } -310 -311 public String getCommand() { -312 return command; -313 } -314 -315 public void addSubcommand(String cmd) { -316 this.registeredSubcommands.add(cmd); -317 } -318 public void addSubcommands(Collection<String> cmd) { -319 this.registeredSubcommands.addAll(cmd); -320 } -321} +302 public void addSubcommands(Collection<String> cmd) { +303 this.registeredSubcommands.addAll(cmd); +304 } +305}