diff --git a/docs/acf-core/co/aikar/commands/BaseCommand.html b/docs/acf-core/co/aikar/commands/BaseCommand.html index 99d5990e..82bd9d73 100644 --- a/docs/acf-core/co/aikar/commands/BaseCommand.html +++ b/docs/acf-core/co/aikar/commands/BaseCommand.html @@ -360,7 +360,7 @@ extends
  • BaseCommand

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

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

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

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

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

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

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

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

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

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

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

    getCommandHelp

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

    showCommandHelp

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

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

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

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

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

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

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

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

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

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

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

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

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

    -
    public RegisteredCommand getDefaultRegisteredCommand()
    +
    public RegisteredCommand getDefaultRegisteredCommand()
  • 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 b7b9f96a..d6d14d32 100644 --- a/docs/acf-core/src-html/co/aikar/commands/BaseCommand.html +++ b/docs/acf-core/src-html/co/aikar/commands/BaseCommand.html @@ -89,581 +89,590 @@ 081 082 private ExceptionHandler exceptionHandler = null; 083 CommandOperationContext lastCommandOperationContext; -084 -085 public BaseCommand() {} -086 public BaseCommand(String cmd) { -087 this.commandName = cmd; -088 } -089 -090 /** -091 * Gets the root command name that the user actually typed -092 * @return Name -093 */ -094 public String getExecCommandLabel() { -095 return execLabel; -096 } -097 -098 /** -099 * Gets the actual sub command name the user typed -100 * @return Name -101 */ -102 public String getExecSubcommand() { -103 return execSubcommand; -104 } -105 -106 /** -107 * Gets the actual args in string form the user typed -108 * @return Args -109 */ -110 public String[] getOrigArgs() { -111 return origArgs; -112 } -113 -114 void setParentCommand(BaseCommand command) { -115 this.parentCommand = command; -116 } -117 void onRegister(CommandManager manager) { -118 onRegister(manager, this.commandName); -119 } -120 void onRegister(CommandManager manager, String cmd) { -121 this.manager = manager; -122 final Class<? extends BaseCommand> self = this.getClass(); -123 CommandAlias rootCmdAliasAnno = self.getAnnotation(CommandAlias.class); -124 String rootCmdAlias = rootCmdAliasAnno != null ? manager.getCommandReplacements().replace(rootCmdAliasAnno.value()).toLowerCase() : null; -125 if (cmd == null && rootCmdAlias != null) { -126 cmd = ACFPatterns.PIPE.split(rootCmdAlias)[0]; -127 } -128 this.commandName = cmd != null ? cmd : self.getSimpleName().toLowerCase(); -129 -130 this.description = this.commandName + " commands"; -131 this.usageMessage = "/" + this.commandName; -132 -133 final CommandPermission perm = self.getAnnotation(CommandPermission.class); -134 if (perm != null) { -135 this.permission = manager.getCommandReplacements().replace(perm.value()); -136 } -137 -138 boolean foundDefault = false; -139 boolean foundUnknown = false; -140 for (Method method : self.getMethods()) { -141 method.setAccessible(true); -142 String sublist = null; -143 String sub = getSubcommandValue(method); -144 final Default def = method.getAnnotation(Default.class); -145 final HelpCommand helpCommand = method.getAnnotation(HelpCommand.class); -146 -147 final CommandAlias commandAliases = method.getAnnotation(CommandAlias.class); -148 -149 if (def != null || (!foundDefault && helpCommand != null)) { -150 if (!foundDefault) { -151 registerSubcommand(method, DEFAULT); -152 if (def != null) { -153 foundDefault = true; -154 } -155 } else { -156 ACFUtil.sneaky(new IllegalStateException("Multiple @Default/@HelpCommand commands, duplicate on " + method.getDeclaringClass().getName() + "#" + method.getName())); -157 } -158 } -159 -160 if (sub != null) { -161 sublist = sub; -162 } else if (commandAliases != null) { -163 sublist = commandAliases.value(); -164 } else if (helpCommand != null) { -165 sublist = helpCommand.value(); -166 } -167 -168 UnknownHandler unknown = method.getAnnotation(UnknownHandler.class); -169 PreCommand preCommand = method.getAnnotation(PreCommand.class); -170 if (unknown != null || (!foundUnknown && helpCommand != null)) { -171 if (!foundUnknown) { -172 registerSubcommand(method, UNKNOWN); -173 if (unknown != null) { -174 foundUnknown = true; -175 } -176 } else { -177 ACFUtil.sneaky(new IllegalStateException("Multiple @UnknownHandler/@HelpCommand commands, duplicate on " + method.getDeclaringClass().getName() + "#" + method.getName())); -178 } -179 } else if (preCommand != null) { -180 if (this.preCommandHandler == null) { -181 this.preCommandHandler = method; -182 } else { -183 ACFUtil.sneaky(new IllegalStateException("Multiple @PreCommand commands, duplicate on " + method.getDeclaringClass().getName() + "#" + method.getName())); -184 } -185 } -186 if (Objects.equals(method.getDeclaringClass(), this.getClass()) && sublist != null) { -187 registerSubcommand(method, sublist); -188 } -189 } -190 -191 if (rootCmdAlias != null) { -192 Set<String> cmdList = new HashSet<>(); -193 Collections.addAll(cmdList, ACFPatterns.PIPE.split(rootCmdAlias)); -194 cmdList.remove(cmd); -195 for (String cmdAlias : cmdList) { -196 register(cmdAlias, this); -197 } -198 } -199 -200 if (cmd != null) { -201 register(cmd, this); -202 } -203 for (Class<?> clazz : this.getClass().getDeclaredClasses()) { -204 if (BaseCommand.class.isAssignableFrom(clazz)) { -205 try { -206 BaseCommand subCommand = null; -207 Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors(); -208 for (Constructor<?> declaredConstructor : declaredConstructors) { -209 -210 declaredConstructor.setAccessible(true); -211 Parameter[] parameters = declaredConstructor.getParameters(); -212 if (parameters.length == 1) { -213 subCommand = (BaseCommand) declaredConstructor.newInstance(this); -214 } else { -215 manager.log(LogLevel.INFO, "Found unusable constructor: " + declaredConstructor.getName() + "(" + Stream.of(parameters).map(p -> p.getType().getSimpleName() + " " + p.getName()).collect(Collectors.joining("<c2>,</c2> ")) + ")"); -216 } -217 } -218 if (subCommand != null) { -219 subCommand.setParentCommand(this); -220 subCommand.onRegister(manager, cmd); -221 this.subCommands.putAll(subCommand.subCommands); -222 this.registeredCommands.putAll(subCommand.registeredCommands); -223 } else { -224 this.manager.log(LogLevel.ERROR, "Could not find a subcommand ctor for " + clazz.getName()); -225 } -226 } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { -227 e.printStackTrace(); -228 } -229 } -230 } -231 -232 } -233 -234 private String getSubcommandValue(Method method) { -235 final Subcommand sub = method.getAnnotation(Subcommand.class); -236 if (sub == null) { -237 return null; -238 } -239 List<String> subList = new ArrayList<>(); -240 subList.add(sub.value()); -241 Class<?> clazz = method.getDeclaringClass(); -242 while (clazz != null) { -243 Subcommand classSub = clazz.getAnnotation(Subcommand.class); -244 if (classSub != null) { -245 subList.add(classSub.value()); -246 } -247 clazz = clazz.getEnclosingClass(); -248 } -249 Collections.reverse(subList); -250 return ACFUtil.join(subList, " "); -251 } -252 -253 private void register(String name, BaseCommand cmd) { -254 String nameLower = name.toLowerCase(); -255 RootCommand rootCommand = manager.obtainRootCommand(nameLower); -256 rootCommand.addChild(cmd); -257 -258 this.registeredCommands.put(nameLower, rootCommand); -259 } -260 -261 private void registerSubcommand(Method method, String subCommand) { -262 subCommand = manager.getCommandReplacements().replace(subCommand.toLowerCase()); -263 final String[] subCommandParts = ACFPatterns.SPACE.split(subCommand); -264 // Must run getSubcommandPossibility BEFORE we rewrite it just after this. -265 Set<String> cmdList = getSubCommandPossibilityList(subCommandParts); +084 private String parentSubcommand; +085 +086 public BaseCommand() {} +087 public BaseCommand(String cmd) { +088 this.commandName = cmd; +089 } +090 +091 /** +092 * Gets the root command name that the user actually typed +093 * @return Name +094 */ +095 public String getExecCommandLabel() { +096 return execLabel; +097 } +098 +099 /** +100 * Gets the actual sub command name the user typed +101 * @return Name +102 */ +103 public String getExecSubcommand() { +104 return execSubcommand; +105 } +106 +107 /** +108 * Gets the actual args in string form the user typed +109 * @return Args +110 */ +111 public String[] getOrigArgs() { +112 return origArgs; +113 } +114 +115 void setParentCommand(BaseCommand command) { +116 this.parentCommand = command; +117 } +118 void onRegister(CommandManager manager) { +119 onRegister(manager, this.commandName); +120 } +121 void onRegister(CommandManager manager, String cmd) { +122 this.manager = manager; +123 final Class<? extends BaseCommand> self = this.getClass(); +124 CommandAlias rootCmdAliasAnno = self.getAnnotation(CommandAlias.class); +125 String rootCmdAlias = rootCmdAliasAnno != null ? manager.getCommandReplacements().replace(rootCmdAliasAnno.value()).toLowerCase() : null; +126 if (cmd == null && rootCmdAlias != null) { +127 cmd = ACFPatterns.PIPE.split(rootCmdAlias)[0]; +128 } +129 this.commandName = cmd != null ? cmd : self.getSimpleName().toLowerCase(); +130 +131 this.description = this.commandName + " commands"; +132 this.usageMessage = "/" + this.commandName; +133 this.parentSubcommand = getParentSubcommand(this.getClass()); +134 +135 final CommandPermission perm = self.getAnnotation(CommandPermission.class); +136 if (perm != null) { +137 this.permission = manager.getCommandReplacements().replace(perm.value()); +138 } +139 +140 boolean foundDefault = false; +141 boolean foundUnknown = false; +142 boolean isParentEmpty = parentSubcommand.isEmpty(); +143 for (Method method : self.getMethods()) { +144 method.setAccessible(true); +145 String sublist = null; +146 String sub = getSubcommandValue(method); +147 final Default def = method.getAnnotation(Default.class); +148 final HelpCommand helpCommand = method.getAnnotation(HelpCommand.class); +149 final CommandAlias commandAliases = method.getAnnotation(CommandAlias.class); +150 +151 if (!isParentEmpty && def != null) { +152 sub = parentSubcommand; +153 } +154 if (isParentEmpty && (def != null || (!foundDefault && helpCommand != null))) { +155 if (!foundDefault) { +156 registerSubcommand(method, DEFAULT); +157 if (def != null) { +158 foundDefault = true; +159 } +160 } else { +161 ACFUtil.sneaky(new IllegalStateException("Multiple @Default/@HelpCommand commands, duplicate on " + method.getDeclaringClass().getName() + "#" + method.getName())); +162 } +163 } +164 +165 if (sub != null) { +166 sublist = sub; +167 } else if (commandAliases != null) { +168 sublist = commandAliases.value(); +169 } else if (helpCommand != null) { +170 sublist = helpCommand.value(); +171 } +172 +173 UnknownHandler unknown = method.getAnnotation(UnknownHandler.class); +174 PreCommand preCommand = method.getAnnotation(PreCommand.class); +175 if (unknown != null || (!foundUnknown && helpCommand != null)) { +176 if (!foundUnknown) { +177 registerSubcommand(method, UNKNOWN); +178 if (unknown != null) { +179 foundUnknown = true; +180 } +181 } else { +182 ACFUtil.sneaky(new IllegalStateException("Multiple @UnknownHandler/@HelpCommand commands, duplicate on " + method.getDeclaringClass().getName() + "#" + method.getName())); +183 } +184 } else if (preCommand != null) { +185 if (this.preCommandHandler == null) { +186 this.preCommandHandler = method; +187 } else { +188 ACFUtil.sneaky(new IllegalStateException("Multiple @PreCommand commands, duplicate on " + method.getDeclaringClass().getName() + "#" + method.getName())); +189 } +190 } +191 if (Objects.equals(method.getDeclaringClass(), this.getClass()) && sublist != null) { +192 registerSubcommand(method, sublist); +193 } +194 } +195 +196 if (rootCmdAlias != null) { +197 Set<String> cmdList = new HashSet<>(); +198 Collections.addAll(cmdList, ACFPatterns.PIPE.split(rootCmdAlias)); +199 cmdList.remove(cmd); +200 for (String cmdAlias : cmdList) { +201 register(cmdAlias, this); +202 } +203 } +204 +205 if (cmd != null) { +206 register(cmd, this); +207 } +208 for (Class<?> clazz : this.getClass().getDeclaredClasses()) { +209 if (BaseCommand.class.isAssignableFrom(clazz)) { +210 try { +211 BaseCommand subCommand = null; +212 Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors(); +213 for (Constructor<?> declaredConstructor : declaredConstructors) { +214 +215 declaredConstructor.setAccessible(true); +216 Parameter[] parameters = declaredConstructor.getParameters(); +217 if (parameters.length == 1) { +218 subCommand = (BaseCommand) declaredConstructor.newInstance(this); +219 } else { +220 manager.log(LogLevel.INFO, "Found unusable constructor: " + declaredConstructor.getName() + "(" + Stream.of(parameters).map(p -> p.getType().getSimpleName() + " " + p.getName()).collect(Collectors.joining("<c2>,</c2> ")) + ")"); +221 } +222 } +223 if (subCommand != null) { +224 subCommand.setParentCommand(this); +225 subCommand.onRegister(manager, cmd); +226 this.subCommands.putAll(subCommand.subCommands); +227 this.registeredCommands.putAll(subCommand.registeredCommands); +228 } else { +229 this.manager.log(LogLevel.ERROR, "Could not find a subcommand ctor for " + clazz.getName()); +230 } +231 } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { +232 e.printStackTrace(); +233 } +234 } +235 } +236 +237 } +238 +239 private String getSubcommandValue(Method method) { +240 final Subcommand sub = method.getAnnotation(Subcommand.class); +241 if (sub == null) { +242 return null; +243 } +244 Class<?> clazz = method.getDeclaringClass(); +245 String parent = getParentSubcommand(clazz); +246 return parent == null || parent.isEmpty() ? sub.value() : parent + " " + sub.value(); +247 } +248 +249 private String getParentSubcommand(Class<?> clazz) { +250 List<String> subList = new ArrayList<>(); +251 while (clazz != null) { +252 Subcommand classSub = clazz.getAnnotation(Subcommand.class); +253 if (classSub != null) { +254 subList.add(classSub.value()); +255 } +256 clazz = clazz.getEnclosingClass(); +257 } +258 Collections.reverse(subList); +259 return ACFUtil.join(subList, " "); +260 } +261 +262 private void register(String name, BaseCommand cmd) { +263 String nameLower = name.toLowerCase(); +264 RootCommand rootCommand = manager.obtainRootCommand(nameLower); +265 rootCommand.addChild(cmd); 266 -267 // Strip pipes off for auto complete addition -268 for (int i = 0; i < subCommandParts.length; i++) { -269 subCommandParts[i] = ACFPatterns.PIPE.split(subCommandParts[i])[0]; -270 } -271 String prefSubCommand = ApacheCommonsLangUtil.join(subCommandParts, " "); -272 final CommandAlias cmdAlias = method.getAnnotation(CommandAlias.class); -273 -274 final String[] aliasNames = cmdAlias != null ? ACFPatterns.PIPE.split(manager.getCommandReplacements().replace(cmdAlias.value().toLowerCase())) : null; -275 String cmdName = aliasNames != null ? aliasNames[0] : this.commandName + " "; -276 RegisteredCommand cmd = manager.createRegisteredCommand(this, cmdName, method, prefSubCommand); -277 -278 for (String subcmd : cmdList) { -279 subCommands.put(subcmd, cmd); -280 } -281 cmd.addSubcommands(cmdList); +267 this.registeredCommands.put(nameLower, rootCommand); +268 } +269 +270 private void registerSubcommand(Method method, String subCommand) { +271 subCommand = manager.getCommandReplacements().replace(subCommand.toLowerCase()); +272 final String[] subCommandParts = ACFPatterns.SPACE.split(subCommand); +273 // Must run getSubcommandPossibility BEFORE we rewrite it just after this. +274 Set<String> cmdList = getSubCommandPossibilityList(subCommandParts); +275 +276 // Strip pipes off for auto complete addition +277 for (int i = 0; i < subCommandParts.length; i++) { +278 subCommandParts[i] = ACFPatterns.PIPE.split(subCommandParts[i])[0]; +279 } +280 String prefSubCommand = ApacheCommonsLangUtil.join(subCommandParts, " "); +281 final CommandAlias cmdAlias = method.getAnnotation(CommandAlias.class); 282 -283 if (aliasNames != null) { -284 for (String name : aliasNames) { -285 register(name, new ForwardingCommand(this, subCommandParts)); -286 } -287 } -288 } -289 -290 /** -291 * Takes a string like "foo|bar baz|qux" and generates a list of -292 * - foo baz -293 * - foo qux -294 * - bar baz -295 * - bar qux -296 * -297 * For every possible sub command combination -298 * -299 * @param subCommandParts -300 * @return List of all sub command possibilities -301 */ -302 private static Set<String> getSubCommandPossibilityList(String[] subCommandParts) { -303 int i = 0; -304 Set<String> current = null; -305 while (true) { -306 Set<String> newList = new HashSet<>(); -307 -308 if (i < subCommandParts.length) { -309 for (String s1 : ACFPatterns.PIPE.split(subCommandParts[i])) { -310 if (current != null) { -311 newList.addAll(current.stream().map(s -> s + " " + s1).collect(Collectors.toList())); -312 } else { -313 newList.add(s1); -314 } -315 } -316 } -317 -318 if (i + 1 < subCommandParts.length) { -319 current = newList; -320 i = i + 1; -321 continue; -322 } -323 -324 return newList; -325 } -326 } -327 -328 public void execute(CommandIssuer issuer, String commandLabel, String[] args) { -329 commandLabel = commandLabel.toLowerCase(); -330 try { -331 CommandOperationContext commandContext = preCommandOperation(issuer, commandLabel, args, false); +283 final String[] aliasNames = cmdAlias != null ? ACFPatterns.PIPE.split(manager.getCommandReplacements().replace(cmdAlias.value().toLowerCase())) : null; +284 String cmdName = aliasNames != null ? aliasNames[0] : this.commandName + " "; +285 RegisteredCommand cmd = manager.createRegisteredCommand(this, cmdName, method, prefSubCommand); +286 +287 for (String subcmd : cmdList) { +288 subCommands.put(subcmd, cmd); +289 } +290 cmd.addSubcommands(cmdList); +291 +292 if (aliasNames != null) { +293 for (String name : aliasNames) { +294 register(name, new ForwardingCommand(this, subCommandParts)); +295 } +296 } +297 } +298 +299 /** +300 * Takes a string like "foo|bar baz|qux" and generates a list of +301 * - foo baz +302 * - foo qux +303 * - bar baz +304 * - bar qux +305 * +306 * For every possible sub command combination +307 * +308 * @param subCommandParts +309 * @return List of all sub command possibilities +310 */ +311 private static Set<String> getSubCommandPossibilityList(String[] subCommandParts) { +312 int i = 0; +313 Set<String> current = null; +314 while (true) { +315 Set<String> newList = new HashSet<>(); +316 +317 if (i < subCommandParts.length) { +318 for (String s1 : ACFPatterns.PIPE.split(subCommandParts[i])) { +319 if (current != null) { +320 newList.addAll(current.stream().map(s -> s + " " + s1).collect(Collectors.toList())); +321 } else { +322 newList.add(s1); +323 } +324 } +325 } +326 +327 if (i + 1 < subCommandParts.length) { +328 current = newList; +329 i = i + 1; +330 continue; +331 } 332 -333 if (args.length > 0) { -334 CommandSearch cmd = findSubCommand(args); -335 if (cmd != null) { -336 execSubcommand = cmd.getCheckSub(); -337 final String[] execargs = Arrays.copyOfRange(args, cmd.argIndex, args.length); -338 executeCommand(commandContext, issuer, execargs, cmd.cmd); -339 return; -340 } -341 } -342 -343 if (subCommands.get(DEFAULT) != null && args.length == 0) { -344 executeSubcommand(commandContext, DEFAULT, issuer, args); -345 } else if (subCommands.get(UNKNOWN) != null) { -346 if (!executeSubcommand(commandContext, UNKNOWN, issuer, args)) { -347 help(issuer, args); -348 } -349 } else if (subCommands.get(DEFAULT) != null) { -350 executeSubcommand(commandContext, DEFAULT, issuer, args); -351 } -352 -353 } finally { -354 postCommandOperation(); -355 } -356 } -357 -358 RegisteredCommand<?> getRegisteredCommand(String[] args) { -359 final CommandSearch cmd = findSubCommand(args); -360 return cmd != null ? cmd.cmd : null; -361 } -362 -363 private void postCommandOperation() { -364 CommandManager.commandOperationContext.get().pop(); -365 execSubcommand = null; -366 execLabel = null; -367 origArgs = new String[]{}; -368 } -369 -370 private CommandOperationContext preCommandOperation(CommandIssuer issuer, String commandLabel, String[] args, boolean isAsync) { -371 Stack<CommandOperationContext> contexts = CommandManager.commandOperationContext.get(); -372 CommandOperationContext context = this.manager.createCommandOperationContext(this, issuer, commandLabel, args, isAsync); -373 contexts.push(context); -374 lastCommandOperationContext = context; -375 execSubcommand = null; -376 execLabel = commandLabel; -377 origArgs = args; -378 return context; -379 } -380 -381 public CommandIssuer getCurrentCommandIssuer() { -382 return CommandManager.getCurrentCommandIssuer(); -383 } -384 public CommandManager getCurrentCommandManager() { -385 return CommandManager.getCurrentCommandManager(); -386 } -387 -388 private CommandSearch findSubCommand(String[] args) { -389 return findSubCommand(args, false); -390 } -391 private CommandSearch findSubCommand(String[] args, boolean completion) { -392 for (int i = args.length; i >= 0; i--) { -393 String checkSub = ApacheCommonsLangUtil.join(args, " ", 0, i).toLowerCase(); -394 Set<RegisteredCommand> cmds = subCommands.get(checkSub); -395 -396 final int extraArgs = args.length - i; -397 if (!cmds.isEmpty()) { -398 RegisteredCommand cmd = null; -399 if (cmds.size() == 1) { -400 cmd = Iterables.getOnlyElement(cmds); -401 } else { -402 Optional<RegisteredCommand> optCmd = cmds.stream().filter(c -> { -403 int required = c.requiredResolvers; -404 int optional = c.optionalResolvers; -405 return extraArgs <= required + optional && (completion || extraArgs >= required); -406 }).sorted((c1, c2) -> { -407 int a = c1.requiredResolvers + c1.optionalResolvers; -408 int b = c2.requiredResolvers + c2.optionalResolvers; -409 -410 if (a == b) { -411 return 0; -412 } -413 return a < b ? 1 : -1; -414 }).findFirst(); -415 if (optCmd.isPresent()) { -416 cmd = optCmd.get(); -417 } -418 } -419 if (cmd != null) { -420 return new CommandSearch(cmd, i, checkSub); -421 } -422 } -423 } -424 return null; -425 } -426 -427 private void executeCommand(CommandOperationContext commandOperationContext, -428 CommandIssuer issuer, String[] args, RegisteredCommand cmd) { -429 if (cmd.hasPermission(issuer)) { -430 commandOperationContext.setRegisteredCommand(cmd); -431 if (checkPrecommand(commandOperationContext, cmd, issuer, args)) { -432 return; -433 } -434 List<String> sargs = Lists.newArrayList(args); -435 cmd.invoke(issuer, sargs); -436 } else { -437 issuer.sendMessage(MessageType.ERROR, MessageKeys.PERMISSION_DENIED); -438 } -439 } -440 -441 public boolean canExecute(CommandIssuer issuer, RegisteredCommand<?> cmd) { -442 return true; -443 } -444 -445 public List<String> tabComplete(CommandIssuer issuer, String commandLabel, String[] args) { -446 return tabComplete(issuer, commandLabel, args, false); -447 } -448 public List<String> tabComplete(CommandIssuer issuer, String commandLabel, String[] args, boolean isAsync) -449 throws IllegalArgumentException { -450 -451 commandLabel = commandLabel.toLowerCase(); -452 if (args.length == 0) { -453 args = new String[]{""}; -454 } -455 try { -456 CommandOperationContext commandOperationContext = preCommandOperation(issuer, commandLabel, args, isAsync); -457 -458 final CommandSearch search = findSubCommand(args, true); +333 return newList; +334 } +335 } +336 +337 public void execute(CommandIssuer issuer, String commandLabel, String[] args) { +338 commandLabel = commandLabel.toLowerCase(); +339 try { +340 CommandOperationContext commandContext = preCommandOperation(issuer, commandLabel, args, false); +341 +342 if (args.length > 0) { +343 CommandSearch cmd = findSubCommand(args); +344 if (cmd != null) { +345 execSubcommand = cmd.getCheckSub(); +346 final String[] execargs = Arrays.copyOfRange(args, cmd.argIndex, args.length); +347 executeCommand(commandContext, issuer, execargs, cmd.cmd); +348 return; +349 } +350 } +351 +352 if (subCommands.get(DEFAULT) != null && args.length == 0) { +353 executeSubcommand(commandContext, DEFAULT, issuer, args); +354 } else if (subCommands.get(UNKNOWN) != null) { +355 if (!executeSubcommand(commandContext, UNKNOWN, issuer, args)) { +356 help(issuer, args); +357 } +358 } else if (subCommands.get(DEFAULT) != null) { +359 executeSubcommand(commandContext, DEFAULT, issuer, args); +360 } +361 +362 } finally { +363 postCommandOperation(); +364 } +365 } +366 +367 RegisteredCommand<?> getRegisteredCommand(String[] args) { +368 final CommandSearch cmd = findSubCommand(args); +369 return cmd != null ? cmd.cmd : null; +370 } +371 +372 private void postCommandOperation() { +373 CommandManager.commandOperationContext.get().pop(); +374 execSubcommand = null; +375 execLabel = null; +376 origArgs = new String[]{}; +377 } +378 +379 private CommandOperationContext preCommandOperation(CommandIssuer issuer, String commandLabel, String[] args, boolean isAsync) { +380 Stack<CommandOperationContext> contexts = CommandManager.commandOperationContext.get(); +381 CommandOperationContext context = this.manager.createCommandOperationContext(this, issuer, commandLabel, args, isAsync); +382 contexts.push(context); +383 lastCommandOperationContext = context; +384 execSubcommand = null; +385 execLabel = commandLabel; +386 origArgs = args; +387 return context; +388 } +389 +390 public CommandIssuer getCurrentCommandIssuer() { +391 return CommandManager.getCurrentCommandIssuer(); +392 } +393 public CommandManager getCurrentCommandManager() { +394 return CommandManager.getCurrentCommandManager(); +395 } +396 +397 private CommandSearch findSubCommand(String[] args) { +398 return findSubCommand(args, false); +399 } +400 private CommandSearch findSubCommand(String[] args, boolean completion) { +401 for (int i = args.length; i >= 0; i--) { +402 String checkSub = ApacheCommonsLangUtil.join(args, " ", 0, i).toLowerCase(); +403 Set<RegisteredCommand> cmds = subCommands.get(checkSub); +404 +405 final int extraArgs = args.length - i; +406 if (!cmds.isEmpty()) { +407 RegisteredCommand cmd = null; +408 if (cmds.size() == 1) { +409 cmd = Iterables.getOnlyElement(cmds); +410 } else { +411 Optional<RegisteredCommand> optCmd = cmds.stream().filter(c -> { +412 int required = c.requiredResolvers; +413 int optional = c.optionalResolvers; +414 return extraArgs <= required + optional && (completion || extraArgs >= required); +415 }).sorted((c1, c2) -> { +416 int a = c1.requiredResolvers + c1.optionalResolvers; +417 int b = c2.requiredResolvers + c2.optionalResolvers; +418 +419 if (a == b) { +420 return 0; +421 } +422 return a < b ? 1 : -1; +423 }).findFirst(); +424 if (optCmd.isPresent()) { +425 cmd = optCmd.get(); +426 } +427 } +428 if (cmd != null) { +429 return new CommandSearch(cmd, i, checkSub); +430 } +431 } +432 } +433 return null; +434 } +435 +436 private void executeCommand(CommandOperationContext commandOperationContext, +437 CommandIssuer issuer, String[] args, RegisteredCommand cmd) { +438 if (cmd.hasPermission(issuer)) { +439 commandOperationContext.setRegisteredCommand(cmd); +440 if (checkPrecommand(commandOperationContext, cmd, issuer, args)) { +441 return; +442 } +443 List<String> sargs = Lists.newArrayList(args); +444 cmd.invoke(issuer, sargs); +445 } else { +446 issuer.sendMessage(MessageType.ERROR, MessageKeys.PERMISSION_DENIED); +447 } +448 } +449 +450 public boolean canExecute(CommandIssuer issuer, RegisteredCommand<?> cmd) { +451 return true; +452 } +453 +454 public List<String> tabComplete(CommandIssuer issuer, String commandLabel, String[] args) { +455 return tabComplete(issuer, commandLabel, args, false); +456 } +457 public List<String> tabComplete(CommandIssuer issuer, String commandLabel, String[] args, boolean isAsync) +458 throws IllegalArgumentException { 459 -460 -461 final List<String> cmds = new ArrayList<>(); -462 -463 if (search != null) { -464 cmds.addAll(completeCommand(issuer, search.cmd, Arrays.copyOfRange(args, search.argIndex, args.length), commandLabel, isAsync)); -465 } else if (subCommands.get(UNKNOWN).size() == 1) { -466 cmds.addAll(completeCommand(issuer, Iterables.getOnlyElement(subCommands.get(UNKNOWN)), args, commandLabel, isAsync)); -467 } +460 commandLabel = commandLabel.toLowerCase(); +461 if (args.length == 0) { +462 args = new String[]{""}; +463 } +464 try { +465 CommandOperationContext commandOperationContext = preCommandOperation(issuer, commandLabel, args, isAsync); +466 +467 final CommandSearch search = findSubCommand(args, true); 468 -469 return filterTabComplete(args[args.length - 1], cmds); -470 } finally { -471 postCommandOperation(); -472 } -473 } -474 -475 List<String> getCommandsForCompletion(CommandIssuer issuer, String[] args) { -476 final Set<String> cmds = new HashSet<>(); -477 String argString = ApacheCommonsLangUtil.join(args, " ").toLowerCase(); -478 for (Map.Entry<String, RegisteredCommand> entry : subCommands.entries()) { -479 final String key = entry.getKey(); -480 if (key.startsWith(argString) && !UNKNOWN.equals(key) && !DEFAULT.equals(key)) { -481 final RegisteredCommand value = entry.getValue(); -482 if (!value.hasPermission(issuer)) { -483 continue; -484 } -485 -486 String[] split = ACFPatterns.SPACE.split(value.prefSubCommand); -487 cmds.add(split[args.length - 1]); -488 } -489 } -490 return new ArrayList<>(cmds); -491 } -492 -493 private List<String> completeCommand(CommandIssuer issuer, RegisteredCommand cmd, String[] args, String commandLabel, boolean isAsync) { -494 if (!cmd.hasPermission(issuer) || args.length > cmd.requiredResolvers + cmd.optionalResolvers || args.length == 0 -495 || cmd.complete == null) { -496 return ImmutableList.of(); -497 } -498 -499 String[] completions = ACFPatterns.SPACE.split(cmd.complete); -500 -501 List<String> cmds = manager.getCommandCompletions().of(cmd, issuer, completions, args, isAsync); -502 return filterTabComplete(args[args.length-1], cmds); -503 } -504 -505 private static List<String> filterTabComplete(String arg, List<String> cmds) { -506 return cmds.stream() -507 .distinct() -508 .filter(cmd -> cmd != null && (arg.isEmpty() || ApacheCommonsLangUtil.startsWithIgnoreCase(cmd, arg))) -509 .collect(Collectors.toList()); -510 } -511 -512 RegisteredCommand getSubcommand(String subcommand) { -513 return getSubcommand(subcommand, false); -514 } -515 -516 RegisteredCommand getSubcommand(String subcommand, boolean requireOne) { -517 final Set<RegisteredCommand> commands = subCommands.get(subcommand); -518 if (!commands.isEmpty() && (!requireOne || commands.size() == 1)) { -519 return commands.iterator().next(); -520 } -521 return null; -522 } -523 -524 private boolean executeSubcommand(CommandOperationContext commandContext, String subcommand, CommandIssuer issuer, String... args) { -525 final RegisteredCommand cmd = this.getSubcommand(subcommand); -526 if (cmd != null) { -527 executeCommand(commandContext, issuer, args, cmd); -528 return true; +469 +470 final List<String> cmds = new ArrayList<>(); +471 +472 if (search != null) { +473 cmds.addAll(completeCommand(issuer, search.cmd, Arrays.copyOfRange(args, search.argIndex, args.length), commandLabel, isAsync)); +474 } else if (subCommands.get(UNKNOWN).size() == 1) { +475 cmds.addAll(completeCommand(issuer, Iterables.getOnlyElement(subCommands.get(UNKNOWN)), args, commandLabel, isAsync)); +476 } +477 +478 return filterTabComplete(args[args.length - 1], cmds); +479 } finally { +480 postCommandOperation(); +481 } +482 } +483 +484 List<String> getCommandsForCompletion(CommandIssuer issuer, String[] args) { +485 final Set<String> cmds = new HashSet<>(); +486 String argString = ApacheCommonsLangUtil.join(args, " ").toLowerCase(); +487 for (Map.Entry<String, RegisteredCommand> entry : subCommands.entries()) { +488 final String key = entry.getKey(); +489 if (key.startsWith(argString) && !UNKNOWN.equals(key) && !DEFAULT.equals(key)) { +490 final RegisteredCommand value = entry.getValue(); +491 if (!value.hasPermission(issuer)) { +492 continue; +493 } +494 +495 String[] split = ACFPatterns.SPACE.split(value.prefSubCommand); +496 cmds.add(split[args.length - 1]); +497 } +498 } +499 return new ArrayList<>(cmds); +500 } +501 +502 private List<String> completeCommand(CommandIssuer issuer, RegisteredCommand cmd, String[] args, String commandLabel, boolean isAsync) { +503 if (!cmd.hasPermission(issuer) || args.length > cmd.requiredResolvers + cmd.optionalResolvers || args.length == 0 +504 || cmd.complete == null) { +505 return ImmutableList.of(); +506 } +507 +508 String[] completions = ACFPatterns.SPACE.split(cmd.complete); +509 +510 List<String> cmds = manager.getCommandCompletions().of(cmd, issuer, completions, args, isAsync); +511 return filterTabComplete(args[args.length-1], cmds); +512 } +513 +514 private static List<String> filterTabComplete(String arg, List<String> cmds) { +515 return cmds.stream() +516 .distinct() +517 .filter(cmd -> cmd != null && (arg.isEmpty() || ApacheCommonsLangUtil.startsWithIgnoreCase(cmd, arg))) +518 .collect(Collectors.toList()); +519 } +520 +521 RegisteredCommand getSubcommand(String subcommand) { +522 return getSubcommand(subcommand, false); +523 } +524 +525 RegisteredCommand getSubcommand(String subcommand, boolean requireOne) { +526 final Set<RegisteredCommand> commands = subCommands.get(subcommand); +527 if (!commands.isEmpty() && (!requireOne || commands.size() == 1)) { +528 return commands.iterator().next(); 529 } -530 -531 return false; -532 } -533 -534 private boolean checkPrecommand(CommandOperationContext commandOperationContext, RegisteredCommand cmd, CommandIssuer issuer, String[] args) { -535 Method pre = this.preCommandHandler; -536 if (pre != null) { -537 try { -538 Class<?>[] types = pre.getParameterTypes(); -539 Object[] parameters = new Object[pre.getParameterCount()]; -540 for (int i = 0; i < parameters.length; i++) { -541 Class<?> type = types[i]; -542 Object issuerObject = issuer.getIssuer(); -543 if (manager.isCommandIssuer(type) && type.isAssignableFrom(issuerObject.getClass())) { -544 parameters[i] = issuerObject; -545 } else if (CommandIssuer.class.isAssignableFrom(type)) { -546 parameters[i] = issuer; -547 } else if (RegisteredCommand.class.isAssignableFrom(type)) { -548 parameters[i] = cmd; -549 } else if (String[].class.isAssignableFrom((type))) { -550 parameters[i] = args; -551 } else { -552 parameters[i] = null; -553 } -554 } -555 -556 return (boolean) pre.invoke(this, parameters); -557 } catch (IllegalAccessException | InvocationTargetException e) { -558 this.manager.log(LogLevel.ERROR, "Exception encountered while command pre-processing", e); -559 } -560 } -561 return false; -562 } -563 -564 /** @deprecated Unstable API */ @Deprecated @UnstableAPI -565 public CommandHelp getCommandHelp() { -566 return manager.generateCommandHelp(); -567 } -568 -569 /** @deprecated Unstable API */ @Deprecated @UnstableAPI -570 public void showCommandHelp() { -571 getCommandHelp().showHelp(); -572 } -573 -574 public void help(Object issuer, String[] args) { -575 help(manager.getCommandIssuer(issuer), args); +530 return null; +531 } +532 +533 private boolean executeSubcommand(CommandOperationContext commandContext, String subcommand, CommandIssuer issuer, String... args) { +534 final RegisteredCommand cmd = this.getSubcommand(subcommand); +535 if (cmd != null) { +536 executeCommand(commandContext, issuer, args, cmd); +537 return true; +538 } +539 +540 return false; +541 } +542 +543 private boolean checkPrecommand(CommandOperationContext commandOperationContext, RegisteredCommand cmd, CommandIssuer issuer, String[] args) { +544 Method pre = this.preCommandHandler; +545 if (pre != null) { +546 try { +547 Class<?>[] types = pre.getParameterTypes(); +548 Object[] parameters = new Object[pre.getParameterCount()]; +549 for (int i = 0; i < parameters.length; i++) { +550 Class<?> type = types[i]; +551 Object issuerObject = issuer.getIssuer(); +552 if (manager.isCommandIssuer(type) && type.isAssignableFrom(issuerObject.getClass())) { +553 parameters[i] = issuerObject; +554 } else if (CommandIssuer.class.isAssignableFrom(type)) { +555 parameters[i] = issuer; +556 } else if (RegisteredCommand.class.isAssignableFrom(type)) { +557 parameters[i] = cmd; +558 } else if (String[].class.isAssignableFrom((type))) { +559 parameters[i] = args; +560 } else { +561 parameters[i] = null; +562 } +563 } +564 +565 return (boolean) pre.invoke(this, parameters); +566 } catch (IllegalAccessException | InvocationTargetException e) { +567 this.manager.log(LogLevel.ERROR, "Exception encountered while command pre-processing", e); +568 } +569 } +570 return false; +571 } +572 +573 /** @deprecated Unstable API */ @Deprecated @UnstableAPI +574 public CommandHelp getCommandHelp() { +575 return manager.generateCommandHelp(); 576 } -577 public void help(CommandIssuer issuer, String[] args) { -578 issuer.sendMessage(MessageType.ERROR, MessageKeys.UNKNOWN_COMMAND); -579 } -580 public void doHelp(Object issuer, String... args) { -581 doHelp(manager.getCommandIssuer(issuer), args); -582 } -583 public void doHelp(CommandIssuer issuer, String... args) { -584 help(issuer, args); +577 +578 /** @deprecated Unstable API */ @Deprecated @UnstableAPI +579 public void showCommandHelp() { +580 getCommandHelp().showHelp(); +581 } +582 +583 public void help(Object issuer, String[] args) { +584 help(manager.getCommandIssuer(issuer), args); 585 } -586 -587 public void showSyntax(CommandIssuer issuer, RegisteredCommand<?> cmd) { -588 issuer.sendMessage(MessageType.SYNTAX, MessageKeys.INVALID_SYNTAX, -589 "{command}", "/" + cmd.command, -590 "{syntax}", cmd.syntaxText -591 ); -592 } -593 -594 public boolean hasPermission(Object issuer) { -595 return hasPermission(manager.getCommandIssuer(issuer)); -596 } -597 -598 public boolean hasPermission(CommandIssuer issuer) { -599 return permission == null || permission.isEmpty() || (manager.hasPermission(issuer, permission) && (parentCommand == null || parentCommand.hasPermission(issuer))); -600 } -601 +586 public void help(CommandIssuer issuer, String[] args) { +587 issuer.sendMessage(MessageType.ERROR, MessageKeys.UNKNOWN_COMMAND); +588 } +589 public void doHelp(Object issuer, String... args) { +590 doHelp(manager.getCommandIssuer(issuer), args); +591 } +592 public void doHelp(CommandIssuer issuer, String... args) { +593 help(issuer, args); +594 } +595 +596 public void showSyntax(CommandIssuer issuer, RegisteredCommand<?> cmd) { +597 issuer.sendMessage(MessageType.SYNTAX, MessageKeys.INVALID_SYNTAX, +598 "{command}", "/" + cmd.command, +599 "{syntax}", cmd.syntaxText +600 ); +601 } 602 -603 public Set<String> getRequiredPermissions() { -604 if (this.permission == null || this.permission.isEmpty()) { -605 return ImmutableSet.of(); -606 } -607 return Sets.newHashSet(ACFPatterns.COMMA.split(this.permission)); -608 } -609 -610 public boolean requiresPermission(String permission) { -611 return getRequiredPermissions().contains(permission) || this.parentCommand != null && parentCommand.requiresPermission(permission); -612 } -613 -614 public String getName() { -615 return commandName; -616 } -617 -618 public ExceptionHandler getExceptionHandler() { -619 return exceptionHandler; -620 } -621 -622 public BaseCommand setExceptionHandler(ExceptionHandler exceptionHandler) { -623 this.exceptionHandler = exceptionHandler; -624 return this; +603 public boolean hasPermission(Object issuer) { +604 return hasPermission(manager.getCommandIssuer(issuer)); +605 } +606 +607 public boolean hasPermission(CommandIssuer issuer) { +608 return permission == null || permission.isEmpty() || (manager.hasPermission(issuer, permission) && (parentCommand == null || parentCommand.hasPermission(issuer))); +609 } +610 +611 +612 public Set<String> getRequiredPermissions() { +613 if (this.permission == null || this.permission.isEmpty()) { +614 return ImmutableSet.of(); +615 } +616 return Sets.newHashSet(ACFPatterns.COMMA.split(this.permission)); +617 } +618 +619 public boolean requiresPermission(String permission) { +620 return getRequiredPermissions().contains(permission) || this.parentCommand != null && parentCommand.requiresPermission(permission); +621 } +622 +623 public String getName() { +624 return commandName; 625 } 626 -627 public RegisteredCommand getDefaultRegisteredCommand() { -628 return this.getSubcommand(DEFAULT); +627 public ExceptionHandler getExceptionHandler() { +628 return exceptionHandler; 629 } 630 -631 private static class CommandSearch { RegisteredCommand cmd; int argIndex; String checkSub; -632 -633 CommandSearch(RegisteredCommand cmd, int argIndex, String checkSub) { -634 this.cmd = cmd; -635 this.argIndex = argIndex; -636 this.checkSub = checkSub; -637 } -638 -639 String getCheckSub() { -640 return this.checkSub; -641 } -642 -643 @Override -644 public boolean equals(Object o) { -645 if (this == o) return true; -646 if (o == null || getClass() != o.getClass()) return false; -647 CommandSearch that = (CommandSearch) o; -648 return argIndex == that.argIndex && -649 Objects.equals(cmd, that.cmd) && -650 Objects.equals(checkSub, that.checkSub); -651 } -652 -653 @Override -654 public int hashCode() { -655 return Objects.hash(cmd, argIndex, checkSub); -656 } -657 } -658} +631 public BaseCommand setExceptionHandler(ExceptionHandler exceptionHandler) { +632 this.exceptionHandler = exceptionHandler; +633 return this; +634 } +635 +636 public RegisteredCommand getDefaultRegisteredCommand() { +637 return this.getSubcommand(DEFAULT); +638 } +639 +640 private static class CommandSearch { RegisteredCommand cmd; int argIndex; String checkSub; +641 +642 CommandSearch(RegisteredCommand cmd, int argIndex, String checkSub) { +643 this.cmd = cmd; +644 this.argIndex = argIndex; +645 this.checkSub = checkSub; +646 } +647 +648 String getCheckSub() { +649 return this.checkSub; +650 } +651 +652 @Override +653 public boolean equals(Object o) { +654 if (this == o) return true; +655 if (o == null || getClass() != o.getClass()) return false; +656 CommandSearch that = (CommandSearch) o; +657 return argIndex == that.argIndex && +658 Objects.equals(cmd, that.cmd) && +659 Objects.equals(checkSub, that.checkSub); +660 } +661 +662 @Override +663 public int hashCode() { +664 return Objects.hash(cmd, argIndex, checkSub); +665 } +666 } +667}