From 61875f26fac3d5784007779014f6eca5616176f9 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sat, 5 Dec 2015 12:06:44 +0100 Subject: [PATCH 01/18] #305 Prepare to remove CommandParts - replace getCount() to List#size() - Preparations to remove the CommandParts as it's a "decorated list". --- .../authme/command/CommandDescription.java | 11 ++++++---- .../xephi/authme/command/CommandHandler.java | 4 +++- .../fr/xephi/authme/command/CommandParts.java | 12 ++--------- .../command/executable/HelpCommand.java | 6 ++++-- .../executable/authme/AccountsCommand.java | 7 +++---- .../executable/authme/ForceLoginCommand.java | 5 ++++- .../executable/authme/GetEmailCommand.java | 5 ++++- .../executable/authme/GetIpCommand.java | 9 ++++---- .../executable/authme/LastLoginCommand.java | 6 +++--- .../authme/PurgeLastPositionCommand.java | 11 +++++----- .../authme/SwitchAntiBotCommand.java | 6 ++++-- .../executable/register/RegisterCommand.java | 21 ++++++++++--------- .../authme/command/help/HelpSyntaxHelper.java | 8 +++++-- 13 files changed, 60 insertions(+), 51 deletions(-) diff --git a/src/main/java/fr/xephi/authme/command/CommandDescription.java b/src/main/java/fr/xephi/authme/command/CommandDescription.java index 1d26a10a..d9587588 100644 --- a/src/main/java/fr/xephi/authme/command/CommandDescription.java +++ b/src/main/java/fr/xephi/authme/command/CommandDescription.java @@ -459,11 +459,13 @@ public class CommandDescription { */ public FoundCommandResult findCommand(final CommandParts queryReference) { // Make sure the command reference is valid - if (queryReference.getCount() <= 0) + List queryRef = queryReference.getList(); + if (queryRef.isEmpty()) { return null; + } // Check whether this description is for the last element in the command reference, if so return the current command - if (queryReference.getCount() <= getParentCount() + 1) { + if (queryRef.size() <= getParentCount() + 1) { return new FoundCommandResult( this, getCommandReference(queryReference), @@ -523,12 +525,13 @@ public class CommandDescription { */ public int getSuitableArgumentsDifference(CommandParts commandReference) { // Make sure the command reference is valid - if (commandReference.getCount() <= 0) { + List labels = commandReference.getList(); + if (labels.isEmpty()) { return -1; } // Get the remaining command reference element count - int remainingElementCount = commandReference.getCount() - getParentCount() - 1; + int remainingElementCount = labels.size() - getParentCount() - 1; // Check if there are too few arguments int minArguments = CommandUtils.getMinNumberOfArguments(this); diff --git a/src/main/java/fr/xephi/authme/command/CommandHandler.java b/src/main/java/fr/xephi/authme/command/CommandHandler.java index 67a4fbe6..c6cb67b2 100644 --- a/src/main/java/fr/xephi/authme/command/CommandHandler.java +++ b/src/main/java/fr/xephi/authme/command/CommandHandler.java @@ -126,8 +126,10 @@ public class CommandHandler { */ public FoundCommandResult findCommand(CommandParts queryReference) { // Make sure the command reference is valid - if (queryReference.getCount() <= 0) + List labels = queryReference.getList(); + if (labels.isEmpty()) { return null; + } for (CommandDescription commandDescription : commands) { // Check whether there's a command description available for the diff --git a/src/main/java/fr/xephi/authme/command/CommandParts.java b/src/main/java/fr/xephi/authme/command/CommandParts.java index eb6299db..b34df6b1 100644 --- a/src/main/java/fr/xephi/authme/command/CommandParts.java +++ b/src/main/java/fr/xephi/authme/command/CommandParts.java @@ -41,15 +41,6 @@ public class CommandParts { return this.parts; } - /** - * Get the number of parts. - * - * @return Part count. - */ - public int getCount() { - return this.parts.size(); - } - /** * Get a part by its index. * @@ -59,8 +50,9 @@ public class CommandParts { */ public String get(int i) { // Make sure the index is in-bound - if (i < 0 || i >= getCount()) + if (i < 0 || i >= parts.size()) { return null; + } // Get and return the argument return this.parts.get(i); diff --git a/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java b/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java index 49aa82e8..d8982fa9 100644 --- a/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java @@ -5,6 +5,8 @@ import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.command.help.HelpProvider; import org.bukkit.command.CommandSender; +import java.util.List; + /** */ public class HelpCommand extends ExecutableCommand { @@ -12,10 +14,10 @@ public class HelpCommand extends ExecutableCommand { @Override public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { // Check whether quick help should be shown - boolean quickHelp = commandArguments.getCount() == 0; + List arguments = commandArguments.getList(); // Set the proper command arguments for the quick help and show it - if (quickHelp) { + if (arguments.isEmpty()) { commandArguments = new CommandParts(commandReference.get(0)); HelpProvider.showHelp(sender, commandReference, commandArguments, false, false, false, false, false, true); } else { diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java index ba34491a..26e5959d 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java @@ -18,15 +18,14 @@ public class AccountsCommand extends ExecutableCommand { @Override public boolean executeCommand(final CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { - // AuthMe plugin instance final AuthMe plugin = AuthMe.getInstance(); - - // Messages instance final Messages m = plugin.getMessages(); + List arguments = commandArguments.getList(); + // Get the player query String playerQuery = sender.getName(); - if (commandArguments.getCount() >= 1) + if (arguments.size() >= 1) playerQuery = commandArguments.get(0); final String playerQueryFinal = playerQuery; diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/ForceLoginCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/ForceLoginCommand.java index f6f3efef..8ba109f9 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/ForceLoginCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/ForceLoginCommand.java @@ -8,6 +8,8 @@ import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import java.util.List; + /** */ public class ForceLoginCommand extends ExecutableCommand { @@ -19,7 +21,8 @@ public class ForceLoginCommand extends ExecutableCommand { // Get the player query String playerName = sender.getName(); - if (commandArguments.getCount() >= 1) + List arguments = commandArguments.getList(); + if (arguments.size() >= 1) playerName = commandArguments.get(0); // Command logic diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java index cc0ac9b8..2e1389cd 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java @@ -8,6 +8,8 @@ import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; import org.bukkit.command.CommandSender; +import java.util.List; + /** */ public class GetEmailCommand extends ExecutableCommand { @@ -24,8 +26,9 @@ public class GetEmailCommand extends ExecutableCommand { @Override public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { // Get the player name + List arguments = commandArguments.getList(); String playerName = sender.getName(); - if (commandArguments.getCount() >= 1) + if (arguments.size() >= 1) playerName = commandArguments.get(0); // Get the authenticated user diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/GetIpCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/GetIpCommand.java index f311a41d..3e6e5e6e 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/GetIpCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/GetIpCommand.java @@ -7,21 +7,20 @@ import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import java.util.List; + /** */ public class GetIpCommand extends ExecutableCommand { @Override public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { - // AuthMe plugin instance final AuthMe plugin = AuthMe.getInstance(); + List arguments = commandArguments.getList(); // Get the player query - String playerName = sender.getName(); - if (commandArguments.getCount() >= 1) - playerName = commandArguments.get(0); + String playerName = (arguments.size() >= 1) ? arguments.get(0) : sender.getName(); - @SuppressWarnings("deprecation") Player player = Bukkit.getPlayer(playerName); if (player == null) { sender.sendMessage("This player is not actually online"); diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java index ecae052b..36fa096f 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java @@ -9,6 +9,7 @@ import fr.xephi.authme.output.Messages; import org.bukkit.command.CommandSender; import java.util.Date; +import java.util.List; /** */ @@ -17,9 +18,8 @@ public class LastLoginCommand extends ExecutableCommand { @Override public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { // Get the player - String playerName = sender.getName(); - if (commandArguments.getCount() >= 1) - playerName = commandArguments.get(0); + List arguments = commandArguments.getList(); + String playerName = (arguments.size() >= 1) ? arguments.get(0) : sender.getName(); // Validate the player AuthMe plugin = AuthMe.getInstance(); diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommand.java index e9e3c9ad..d49b5a2f 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommand.java @@ -10,6 +10,8 @@ import fr.xephi.authme.output.Messages; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import java.util.List; + /** */ public class PurgeLastPositionCommand extends ExecutableCommand { @@ -25,16 +27,13 @@ public class PurgeLastPositionCommand extends ExecutableCommand { */ @Override public boolean executeCommand(final CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { - // AuthMe plugin instance final AuthMe plugin = AuthMe.getInstance(); - - // Messages instance final Messages m = plugin.getMessages(); + List arguments = commandArguments.getList(); + String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0); + // Get the player - String playerName = sender.getName(); - if (commandArguments.getCount() >= 1) - playerName = commandArguments.get(0); String playerNameLowerCase = playerName.toLowerCase(); // Purge the last position of the player diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommand.java index 3c047867..38123681 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommand.java @@ -28,9 +28,11 @@ public class SwitchAntiBotCommand extends ExecutableCommand { public boolean executeCommand(final CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { // Get the new state String newState = null; - if (commandArguments.getCount() == 1) { + List arguments = commandArguments.getList(); + + if (arguments.size() == 1) { newState = commandArguments.get(0); - } else if(commandArguments.getCount() == 0) { + } else if (arguments.size() == 0) { sender.sendMessage("[AuthMe] AntiBot status: " + AntiBot.getAntiBotStatus().name()); return true; } diff --git a/src/main/java/fr/xephi/authme/command/executable/register/RegisterCommand.java b/src/main/java/fr/xephi/authme/command/executable/register/RegisterCommand.java index 1f366dea..b240bf04 100644 --- a/src/main/java/fr/xephi/authme/command/executable/register/RegisterCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/register/RegisterCommand.java @@ -12,39 +12,40 @@ import fr.xephi.authme.util.Wrapper; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import java.util.List; + /** */ public class RegisterCommand extends ExecutableCommand { @Override public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { - // Make sure the sender is a player if (!(sender instanceof Player)) { sender.sendMessage("Player Only! Use 'authme register ' instead"); return true; } + List arguments = commandArguments.getList(); + final Wrapper wrapper = Wrapper.getInstance(); final AuthMe plugin = wrapper.getAuthMe(); final Messages m = wrapper.getMessages(); // Make sure the command arguments are valid final Player player = (Player) sender; - if (commandArguments.getCount() == 0 || (Settings.getEnablePasswordVerifier && commandArguments.getCount() < 2)) { + if (arguments.isEmpty() || (Settings.getEnablePasswordVerifier && arguments.size() < 2)) { m.send(player, MessageKey.USAGE_REGISTER); return true; } final Management management = plugin.getManagement(); if (Settings.emailRegistration && !Settings.getmailAccount.isEmpty()) { - if (Settings.doubleEmailCheck) { - if (commandArguments.getCount() < 2 || !commandArguments.get(0).equals(commandArguments.get(1))) { - m.send(player, MessageKey.USAGE_REGISTER); - return true; - } + if (Settings.doubleEmailCheck && arguments.size() < 2 || !arguments.get(0).equals(arguments.get(1))) { + m.send(player, MessageKey.USAGE_REGISTER); + return true; } - final String email = commandArguments.get(0); + final String email = arguments.get(0); if (!Settings.isEmailCorrect(email)) { m.send(player, MessageKey.INVALID_EMAIL); return true; @@ -53,8 +54,8 @@ public class RegisterCommand extends ExecutableCommand { management.performRegister(player, thePass, email); return true; } - if (commandArguments.getCount() > 1 && Settings.getEnablePasswordVerifier) { - if (!commandArguments.get(0).equals(commandArguments.get(1))) { + if (arguments.size() > 1 && Settings.getEnablePasswordVerifier) { + if (!arguments.get(0).equals(commandArguments.get(1))) { m.send(player, MessageKey.PASSWORD_MATCH_ERROR); return true; } diff --git a/src/main/java/fr/xephi/authme/command/help/HelpSyntaxHelper.java b/src/main/java/fr/xephi/authme/command/help/HelpSyntaxHelper.java index 5fa3f5e0..d2f5f545 100644 --- a/src/main/java/fr/xephi/authme/command/help/HelpSyntaxHelper.java +++ b/src/main/java/fr/xephi/authme/command/help/HelpSyntaxHelper.java @@ -8,6 +8,8 @@ import fr.xephi.authme.util.CollectionUtils; import fr.xephi.authme.util.StringUtils; import org.bukkit.ChatColor; +import java.util.List; + /** * Helper class for formatting a command's structure (name and arguments) * for a Minecraft user. @@ -37,13 +39,15 @@ public final class HelpSyntaxHelper { // Get the help command reference, and the command label CommandParts helpCommandReference = commandDescription.getCommandReference(commandReference); + List helpLabels = helpCommandReference.getList(); + final String parentCommand = CommandUtils.labelsToString( - CollectionUtils.getRange(helpCommandReference.getList(), 0, helpCommandReference.getCount() - 1)); + CollectionUtils.getRange(helpCommandReference.getList(), 0, helpLabels.size() - 1)); // Check whether the alternative label should be used String commandLabel; if (StringUtils.isEmpty(alternativeLabel)) { - commandLabel = helpCommandReference.get(helpCommandReference.getCount() - 1); + commandLabel = helpLabels.get(helpLabels.size() - 1); } else { commandLabel = alternativeLabel; } From 56c005587c07709ac35fce4a43e1d32c0c6b26ae Mon Sep 17 00:00:00 2001 From: ljacqu Date: Fri, 11 Dec 2015 20:33:09 +0100 Subject: [PATCH 02/18] Create basic outline of command mapper --- .../xephi/authme/command/CommandMapper.java | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 src/main/java/fr/xephi/authme/command/CommandMapper.java diff --git a/src/main/java/fr/xephi/authme/command/CommandMapper.java b/src/main/java/fr/xephi/authme/command/CommandMapper.java new file mode 100644 index 00000000..09336105 --- /dev/null +++ b/src/main/java/fr/xephi/authme/command/CommandMapper.java @@ -0,0 +1,80 @@ +package fr.xephi.authme.command; + +import fr.xephi.authme.util.CollectionUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * Class responsible for mapping incoming arguments to a {@link CommandDescription}. + */ +public class CommandMapper { + + /** + * Map incoming command parts to an actual command. + * + * @param parts The parts to process + * @return The generated result + */ + public FoundCommandResult mapPartsToCommand(final List parts) { + if (CollectionUtils.isEmpty(parts)) { + return null; // TODO pass on the information that the base could not be mapped + } + + CommandDescription base = getBaseCommand(parts.get(0)); + if (base == null) { + return null; // TODO Pass on the information that base could not be mapped + } + + //List labels = CollectionUtils.getRange(parts, 0, 1); + List remaining = parts.subList(1, parts.size()); + + // Prefer labels: /register help goes to "Help command", not "Register command" with 'help' + CommandDescription childCommand = returnSuitableChild(base, remaining); + if (childCommand != null) { + // return childcommand: it's valid... + } + + // No child command found, check if parent is suitable + if (isSuitableArgumentCount(base, remaining.size())) { + // return base... it's valid + } + + // TODO: We don't have a suitable command for the given parts, so find the most similar one + return null; + + } + + private static boolean isSuitableArgumentCount(CommandDescription command, int argumentCount) { + int minArgs = CommandUtils.getMinNumberOfArguments(command); + int maxArgs = CommandUtils.getMaxNumberOfArguments(command); + + return argumentCount >= minArgs && argumentCount <= maxArgs; + } + + // Is the given command a suitable match for the given parts? parts is for example [changepassword, newpw, newpw] + public CommandDescription returnSuitableChild(CommandDescription baseCommand, List parts) { + // TODO: Validate list + make case-insensitive + final String label = parts.get(0).toLowerCase(); + final int argumentCount = parts.size() - 1; + + List args = parts.subList(1, parts.size()); + for (CommandDescription child : baseCommand.getChildren()) { + if (child.getLabels().contains(label) && isSuitableArgumentCount(child, argumentCount)) { + return child; + } + } + return null; + } + + public CommandDescription getBaseCommand(String label) { + String baseLabel = label.toLowerCase(); + for (CommandDescription command : CommandInitializer.getBaseCommands()) { + if (command.getLabels().contains(baseLabel)) { + return command; + } + } + return null; + } + +} From 550eecebdc0b2ed67848f04c4217a98fcf033eee Mon Sep 17 00:00:00 2001 From: ljacqu Date: Fri, 11 Dec 2015 22:08:36 +0100 Subject: [PATCH 03/18] Add command similarity check to mapper (work in progress) --- .../xephi/authme/command/CommandMapper.java | 66 ++++++++++++++++--- 1 file changed, 57 insertions(+), 9 deletions(-) diff --git a/src/main/java/fr/xephi/authme/command/CommandMapper.java b/src/main/java/fr/xephi/authme/command/CommandMapper.java index 09336105..a6a74551 100644 --- a/src/main/java/fr/xephi/authme/command/CommandMapper.java +++ b/src/main/java/fr/xephi/authme/command/CommandMapper.java @@ -1,6 +1,7 @@ package fr.xephi.authme.command; import fr.xephi.authme.util.CollectionUtils; +import fr.xephi.authme.util.StringUtils; import java.util.ArrayList; import java.util.List; @@ -10,6 +11,18 @@ import java.util.List; */ public class CommandMapper { + /** + * The threshold for assuming an existing command. If the difference is below this value, we assume + * that the user meant the similar command and we will run it. + */ + private static final double ASSUME_COMMAND_THRESHOLD = 0.12; + + /** + * The threshold for suggesting a similar command. If the difference is below this value, we will + * ask the player whether he meant the similar command. + */ + private static final double SUGGEST_COMMAND_THRESHOLD = 0.75; + /** * Map incoming command parts to an actual command. * @@ -26,25 +39,41 @@ public class CommandMapper { return null; // TODO Pass on the information that base could not be mapped } - //List labels = CollectionUtils.getRange(parts, 0, 1); List remaining = parts.subList(1, parts.size()); - // Prefer labels: /register help goes to "Help command", not "Register command" with 'help' + // Prefer labels: /register help goes to "Help command", not "Register command" with argument 'help' CommandDescription childCommand = returnSuitableChild(base, remaining); if (childCommand != null) { // return childcommand: it's valid... - } - - // No child command found, check if parent is suitable - if (isSuitableArgumentCount(base, remaining.size())) { + } else if (isSuitableArgumentCount(base, remaining.size())) { // return base... it's valid } - // TODO: We don't have a suitable command for the given parts, so find the most similar one + // TODO: return getCommandWithSmallestDifference() return null; } + // TODO: Return FoundCommandDescription immediately + private CommandDescription getCommandWithSmallestDifference(CommandDescription base, List parts) { + final String label = parts.get(0); + final int argumentCount = parts.size() - 1; + + double minDifference = Double.POSITIVE_INFINITY; + CommandDescription closestCommand = null; + for (CommandDescription child : base.getChildren()) { + double argumentDifference = getArgumentCountDifference(child, argumentCount); + double labelDifference = getLabelDifference(child, label); + // Weigh argument difference less + double difference = labelDifference + argumentCount / 2; + if (difference < minDifference) { + minDifference = difference; + closestCommand = child; + } + } + return closestCommand; + } + private static boolean isSuitableArgumentCount(CommandDescription command, int argumentCount) { int minArgs = CommandUtils.getMinNumberOfArguments(command); int maxArgs = CommandUtils.getMaxNumberOfArguments(command); @@ -52,13 +81,32 @@ public class CommandMapper { return argumentCount >= minArgs && argumentCount <= maxArgs; } + private static double getLabelDifference(CommandDescription command, String givenLabel) { + double minDifference = Double.POSITIVE_INFINITY; + for (String commandLabel : command.getLabels()) { + double difference = StringUtils.getDifference(commandLabel, givenLabel); + if (difference < minDifference) { + minDifference = difference; + } + } + return minDifference; + } + + private static int getArgumentCountDifference(CommandDescription commandDescription, int givenArgumentsCount) { + return Math.min( + Math.abs(givenArgumentsCount - CommandUtils.getMinNumberOfArguments(commandDescription)), + Math.abs(givenArgumentsCount - CommandUtils.getMaxNumberOfArguments(commandDescription))); + } + // Is the given command a suitable match for the given parts? parts is for example [changepassword, newpw, newpw] public CommandDescription returnSuitableChild(CommandDescription baseCommand, List parts) { - // TODO: Validate list + make case-insensitive + if (CollectionUtils.isEmpty(parts)) { + return null; + } + final String label = parts.get(0).toLowerCase(); final int argumentCount = parts.size() - 1; - List args = parts.subList(1, parts.size()); for (CommandDescription child : baseCommand.getChildren()) { if (child.getLabels().contains(label) && isSuitableArgumentCount(child, argumentCount)) { return child; From ec9009d776bda239c405028e58ac42292905d277 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Fri, 11 Dec 2015 23:16:13 +0100 Subject: [PATCH 04/18] =?UTF-8?q?Separate=20command=20handler=20into=20sma?= =?UTF-8?q?ller=20parts=20(wip=20=E2=80=93=20doesn't=20compile)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move logic from CommandMapper to CommandHandler - Create "ResultStatus" on FoundCommandResult to precisely return the error case Naming and structure not final --- .../authme/command/CommandDescription.java | 353 +----------------- .../xephi/authme/command/CommandHandler.java | 273 +++++++------- .../xephi/authme/command/CommandMapper.java | 128 ------- 3 files changed, 139 insertions(+), 615 deletions(-) delete mode 100644 src/main/java/fr/xephi/authme/command/CommandMapper.java diff --git a/src/main/java/fr/xephi/authme/command/CommandDescription.java b/src/main/java/fr/xephi/authme/command/CommandDescription.java index 9114ff1a..a523dfb4 100644 --- a/src/main/java/fr/xephi/authme/command/CommandDescription.java +++ b/src/main/java/fr/xephi/authme/command/CommandDescription.java @@ -13,6 +13,8 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; +import static com.google.common.base.Objects.firstNonNull; + /** * Command description - defines which labels ("names") will lead to a command and points to the * {@link ExecutableCommand} implementation that executes the logic of the command. @@ -99,38 +101,8 @@ public class CommandDescription { return instance; } - /** - * Get the label most similar to the reference. The first label will be returned if no reference was supplied. - * - * @param reference The command reference. - * - * @return The most similar label, or the first label. An empty label will be returned if no label was set. - */ - public String getLabel(CommandParts reference) { - // Ensure there's any item in the command list - if (this.labels.size() == 0) - return ""; - - // Return the first label if we can't use the reference - if (reference == null) - return this.labels.get(0); - - // Get the correct label from the reference - String preferred = reference.get(getParentCount()); - - // Check whether the preferred label is in the label list - double currentDifference = -1; - String currentLabel = this.labels.get(0); - for (String entry : this.labels) { - double entryDifference = StringUtils.getDifference(entry, preferred); - if (entryDifference < currentDifference || currentDifference < 0) { - currentDifference = entryDifference; - currentLabel = entry; - } - } - - // Return the most similar label - return currentLabel; + private void addChild(CommandDescription command) { + children.add(command); } /** @@ -150,7 +122,7 @@ public class CommandDescription { * @return True if this command label equals to the param command. */ public boolean hasLabel(String commandLabel) { - for (String label : this.labels) { + for (String label : labels) { if (label.equalsIgnoreCase(commandLabel)) { return true; } @@ -158,83 +130,6 @@ public class CommandDescription { return false; } - /** - * Check whether this command label is applicable with a command reference. This doesn't check if the parent - * are suitable too. - * - * @param commandReference The command reference. - * - * @return True if the command reference is suitable to this command label, false otherwise. - */ - public boolean isSuitableLabel(CommandParts commandReference) { - // Get the parent count - //getParent() = getParent().getParentCount() + 1 - String element = commandReference.get(getParentCount()); - - // Check whether this command description has this command label - for (String label : labels) { - if (label.equalsIgnoreCase(element)) { - return true; - } - } - return false; - } - - /** - * Get the command reference. - * - * @param reference The reference to use as template, which is used to choose the most similar reference. - * - * @return Command reference. - */ - public CommandParts getCommandReference(CommandParts reference) { - // Build the reference - List referenceList = new ArrayList<>(); - - // Check whether this command has a parent, if so, add the absolute parent command - if (getParent() != null) { - referenceList.addAll(getParent().getCommandReference(reference).getList()); - } - - // Get the current label - referenceList.add(getLabel(reference)); - - // Return the reference - return new CommandParts(referenceList); - } - - /** - * Get the difference between this command and another command reference. - * - * @param other The other command reference. - * - * @return The command difference. Zero if there's no difference. A negative number on error. - */ - public double getCommandDifference(CommandParts other) { - return getCommandDifference(other, false); - } - - /** - * Get the difference between this command and another command reference. - * - * @param other The other command reference. - * @param fullCompare True to fully compare both command references. - * - * @return The command difference. Zero if there's no difference. A negative number on error. - */ - public double getCommandDifference(CommandParts other, boolean fullCompare) { - // Make sure the reference is valid - if (other == null) - return -1; - - // Get the command reference - CommandParts reference = getCommandReference(other); - - // Compare the two references, return the result - return CommandUtils.getDifference(reference.getList(), - CollectionUtils.getRange(other.getList(), 0, reference.getList().size()), fullCompare); - } - /** * Get the executable command. * @@ -244,29 +139,6 @@ public class CommandDescription { return this.executableCommand; } - /** - * Set the executable command. - * - * @param executableCommand The executable command. - */ - public void setExecutableCommand(ExecutableCommand executableCommand) { - this.executableCommand = executableCommand; - } - - /** - * Execute the command, if possible. - * - * @param sender The command sender that triggered the execution of this command. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True on success, false on failure. - */ - public boolean execute(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { - // Execute the command, return the result - return getExecutableCommand().executeCommand(sender, commandReference, commandArguments); - } - /** * Get the parent command if this command description has a parent. * @@ -276,52 +148,6 @@ public class CommandDescription { return this.parent; } - /** - * Get the number of parent this description has. - * - * @return The number of parents. - */ - public int getParentCount() { - // Check whether the this description has a parent - if (!hasParent()) - return 0; - - // Get the parent count of the parent, return the result - return getParent().getParentCount() + 1; - } - - /** - * Set the parent command. - * - * @param parent Parent command. - * - * @return True on success, false on failure. - */ - public boolean setParent(CommandDescription parent) { - // Make sure the parent is different - if (this.parent == parent) - return true; - - // Set the parent - this.parent = parent; - - // Make sure the parent isn't null - if (parent == null) - return true; - - // Add this description as a child to the parent - return parent.addChild(this); - } - - /** - * Check whether the plugin description has a parent command. - * - * @return True if the description has a parent command, false otherwise. - */ - public boolean hasParent() { - return this.parent != null; - } - /** * Get all command children. * @@ -331,70 +157,6 @@ public class CommandDescription { return this.children; } - /** - * Add a child to the command description. - * - * @param commandDescription The child to add. - * - * @return True on success, false on failure. - */ - public boolean addChild(CommandDescription commandDescription) { - // Make sure the description is valid - if (commandDescription == null) - return false; - - // Make sure the child doesn't exist already - if (isChild(commandDescription)) - return true; - - // The command description to add as a child - if (!this.children.add(commandDescription)) - return false; - - // Set this description as parent on the child - return commandDescription.setParent(this); - } - - /** - * Check whether this command has any child labels. - * - * @return True if this command has any child labels. - */ - public boolean hasChildren() { - return (this.children.size() != 0); - } - - /** - * Check if this command description has a specific child. - * - * @param commandDescription The command description to check for. - * - * @return True if this command description has the specific child, false otherwise. - */ - public boolean isChild(CommandDescription commandDescription) { - // Make sure the description is valid - if (commandDescription == null) - return false; - - // Check whether this child exists, return the result - return this.children.contains(commandDescription); - } - - /** - * Add an argument. - * - * @param argument The argument to add. - * - * @return True if succeed, false if failed. - */ - public boolean addArgument(CommandArgumentDescription argument) { - // Make sure the argument is valid - if (argument == null) - return false; - - // Add the argument, return the result - return this.arguments.add(argument); - } /** * Get all command arguments. @@ -432,104 +194,6 @@ public class CommandDescription { return detailedDescription; } - /** - * Find the best suitable command for a query reference. - * - * @param queryReference The query reference to find a command for. - * - * @return The command found, or null. - */ - public FoundCommandResult findCommand(final CommandParts queryReference) { - // Make sure the command reference is valid - List queryRef = queryReference.getList(); - if (queryRef.isEmpty()) { - return null; - } - - // Check whether this description is for the last element in the command reference, if so return the current command - if (queryRef.size() <= getParentCount() + 1) { - return new FoundCommandResult( - this, - getCommandReference(queryReference), - new CommandParts(new ArrayList()), - queryReference); - } - - // Get the new command reference and arguments - CommandParts newReference = new CommandParts(CollectionUtils.getRange(queryReference.getList(), 0, getParentCount() + 1)); - CommandParts newArguments = new CommandParts(CollectionUtils.getRange(queryReference.getList(), getParentCount() + 1)); - - // Handle the child's, if this command has any - if (getChildren().size() > 0) { - // Get a new instance of the child's list, and sort them by their difference in comparison to the query reference - List commandChildren = new ArrayList<>(getChildren()); - Collections.sort(commandChildren, new Comparator() { - @Override - public int compare(CommandDescription o1, CommandDescription o2) { - return Double.compare( - o1.getCommandDifference(queryReference), - o2.getCommandDifference(queryReference)); - } - }); - - // Get the difference of the first child in the list - double firstChildDifference = commandChildren.get(0).getCommandDifference(queryReference, true); - - // Check if the reference perfectly suits the arguments of the current command if it doesn't perfectly suits a child command - if (firstChildDifference > 0.0) - if (getSuitableArgumentsDifference(queryReference) == 0) - return new FoundCommandResult(this, newReference, newArguments, queryReference); - - // Loop through each child - for (CommandDescription child : commandChildren) { - // Get the best suitable command - FoundCommandResult result = child.findCommand(queryReference); - if (result != null) - return result; - } - } - - // Check if the remaining command reference elements fit the arguments for this command - if (getSuitableArgumentsDifference(queryReference) >= 0) - return new FoundCommandResult(this, newReference, newArguments, queryReference); - - // No command found, return null - return null; - } - - /** - * Check if the remaining command reference elements are suitable with arguments of the current command description, - * and get the difference in argument count. - * - * @param commandReference The command reference. - * - * @return The difference in argument count between the reference and the actual command. - */ - public int getSuitableArgumentsDifference(CommandParts commandReference) { - // Make sure the command reference is valid - List labels = commandReference.getList(); - if (labels.isEmpty()) { - return -1; - } - - // Get the remaining command reference element count - int remainingElementCount = labels.size() - getParentCount() - 1; - - // Check if there are too few arguments - int minArguments = CommandUtils.getMinNumberOfArguments(this); - if (minArguments > remainingElementCount) { - return Math.abs(minArguments - remainingElementCount); - } - - // Check if there are too many arguments - int maxArguments = CommandUtils.getMaxNumberOfArguments(this); - if (maxArguments >= 0 && maxArguments < remainingElementCount) { - return Math.abs(remainingElementCount - maxArguments); - } - - // The argument count is the same - return 0; - } /** * Get the command permissions. Return null if the command doesn't require any permission. @@ -562,6 +226,7 @@ public class CommandDescription { * * @return The generated CommandDescription object */ + // TODO ljacqu 20151206 Move validation to the create instance method public CommandDescription build() { return createInstance( getOrThrow(labels, "labels"), @@ -570,7 +235,7 @@ public class CommandDescription { getOrThrow(executableCommand, "executableCommand"), firstNonNull(parent, null), arguments, - firstNonNull(permissions, null) + permissions ); } @@ -629,10 +294,6 @@ public class CommandDescription { return new ArrayList<>(Arrays.asList(items)); } - private static T firstNonNull(T first, T second) { - return first != null ? first : second; - } - private static T getOrThrow(T element, String elementName) { if (!isEmpty(element)) { return element; diff --git a/src/main/java/fr/xephi/authme/command/CommandHandler.java b/src/main/java/fr/xephi/authme/command/CommandHandler.java index c6cb67b2..3b187380 100644 --- a/src/main/java/fr/xephi/authme/command/CommandHandler.java +++ b/src/main/java/fr/xephi/authme/command/CommandHandler.java @@ -2,6 +2,7 @@ package fr.xephi.authme.command; import fr.xephi.authme.AuthMe; import fr.xephi.authme.command.help.HelpProvider; +import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.util.CollectionUtils; import fr.xephi.authme.util.StringUtils; import org.bukkit.ChatColor; @@ -17,27 +18,23 @@ import java.util.Set; */ public class CommandHandler { - /** - * The threshold for assuming an existing command. If the difference is below this value, we assume - * that the user meant the similar command and we will run it. - */ - private static final double ASSUME_COMMAND_THRESHOLD = 0.12; - /** * The threshold for suggesting a similar command. If the difference is below this value, we will * ask the player whether he meant the similar command. */ private static final double SUGGEST_COMMAND_THRESHOLD = 0.75; - private final Set commands; + private final Set baseCommands; + private final PermissionsManager permissionsManager; /** * Create a command handler. * - * @param commands The collection of available AuthMe commands + * @param baseCommands The collection of available AuthMe base commands */ - public CommandHandler(Set commands) { - this.commands = commands; + public CommandHandler(Set baseCommands, PermissionsManager permissionsManager) { + this.baseCommands = baseCommands; + this.permissionsManager = permissionsManager; } /** @@ -51,43 +48,29 @@ public class CommandHandler { * @return True if the command was executed, false otherwise. */ public boolean processCommand(CommandSender sender, String bukkitCommandLabel, String[] bukkitArgs) { - List commandArgs = skipEmptyArguments(bukkitArgs); - // Add the Bukkit command label to the front so we get a list like [authme, register, pass, passConfirm] - commandArgs.add(0, bukkitCommandLabel); + // Add the Bukkit command label to the front so we get a list like [authme, register, bobby, mysecret] + List parts = skipEmptyArguments(bukkitArgs); + parts.add(0, bukkitCommandLabel); - // TODO: remove commandParts - CommandParts commandReference = new CommandParts(commandArgs); - - // Get a suitable command for this reference, and make sure it isn't null - FoundCommandResult result = findCommand(commandReference); - if (result == null) { - // TODO ljacqu 20151204: Log more information to the console (bukkitCommandLabel) - sender.sendMessage(ChatColor.DARK_RED + "Failed to parse " + AuthMe.getPluginName() + " command!"); - return false; + // Get the base command of the result, e.g. authme for [authme, register, bobby, mysecret] + FoundCommandResult result = mapPartsToCommand(parts); + switch (result.getResultStatus()) { + case SUCCESS: + // Check perms + process + break; + case MISSING_BASE_COMMAND: + sender.sendMessage(ChatColor.DARK_RED + "Failed to parse " + AuthMe.getPluginName() + " command!"); + return false; + case INCORRECT_ARGUMENTS: + // sendImproperArgumentsMessage(sender, result); + break; + case UNKNOWN_LABEL: + // sendUnknownCommandMessage(sender); + break; + default: + throw new RuntimeException("Unknown result '" + result.getResultStatus() + "'"); } - - String baseCommand = commandArgs.get(0); - - // Make sure the difference between the command reference and the actual command isn't too big - final double commandDifference = result.getDifference(); - if (commandDifference <= ASSUME_COMMAND_THRESHOLD) { - - // Show a message when the command handler is assuming a command - if (commandDifference > 0) { - sendCommandAssumptionMessage(sender, result, commandReference); - } - - if (!result.hasPermission(sender)) { - sender.sendMessage(ChatColor.DARK_RED + "You don't have permission to use this command!"); - } else if (!result.hasProperArguments()) { - sendImproperArgumentsMessage(sender, result, commandReference, baseCommand); - } else { - return result.executeCommand(sender); - } - } else { - sendUnknownCommandMessage(sender, commandDifference, result, baseCommand); - } return true; } @@ -108,101 +91,22 @@ public class CommandHandler { } - private static CommandDescription mapToBase(String commandLabel) { - for (CommandDescription command : CommandInitializer.getBaseCommands()) { - if (command.getLabels().contains(commandLabel)) { - return command; - } - } - return null; - } - - /** - * Find the best suitable command for the specified reference. - * - * @param queryReference The query reference to find a command for. - * - * @return The command found, or null. - */ - public FoundCommandResult findCommand(CommandParts queryReference) { - // Make sure the command reference is valid - List labels = queryReference.getList(); - if (labels.isEmpty()) { - return null; - } - - for (CommandDescription commandDescription : commands) { - // Check whether there's a command description available for the - // current command - if (!commandDescription.isSuitableLabel(queryReference)) - continue; - - // Find the command reference, return the result - return commandDescription.findCommand(queryReference); - } - - // No applicable command description found, return false - return null; - } - - /** - * Find the best suitable command for the specified reference. - * - * @param commandParts The query reference to find a command for. - * - * @return The command found, or null. - */ - private CommandDescription findCommand(List commandParts) { - // Make sure the command reference is valid - if (commandParts.isEmpty()) { - return null; - } - - // TODO ljacqu 20151129: Since we only use .contains() on the CommandDescription#labels after init, change - // the type to set for faster lookup - Iterable commandsToScan = CommandInitializer.getBaseCommands(); - CommandDescription result = null; - for (String label : commandParts) { - result = findLabel(label, commandsToScan); - if (result == null) { - return null; - } - commandsToScan = result.getChildren(); - } - return result; - } - - private static CommandDescription findLabel(String label, Iterable commands) { - if (commands == null) { - return null; - } - for (CommandDescription command : commands) { - if (command.getLabels().contains(label)) { // TODO ljacqu should be case-insensitive - return command; - } - } - return null; - } - /** * Show an "unknown command" to the user and suggests an existing command if its similarity is within * the defined threshold. * * @param sender The command sender - * @param commandDifference The difference between the invoked command and the existing one * @param result The command that was found during the mapping process - * @param baseCommand The base command (TODO: This is probably already in FoundCommandResult) + * @param baseCommand The base command */ - private static void sendUnknownCommandMessage(CommandSender sender, double commandDifference, - FoundCommandResult result, String baseCommand) { - CommandParts commandReference = result.getCommandReference(); + private static void sendUnknownCommandMessage(CommandSender sender, FoundCommandResult result, String baseCommand) { sender.sendMessage(ChatColor.DARK_RED + "Unknown command!"); - // Show a command suggestion if available and the difference isn't too big - if (commandDifference < SUGGEST_COMMAND_THRESHOLD && result.getCommandDescription() != null) { + if (result.getDifference() < SUGGEST_COMMAND_THRESHOLD && result.getCommandDescription() != null) { sender.sendMessage(ChatColor.YELLOW + "Did you mean " + ChatColor.GOLD + "/" - + result.getCommandDescription().getCommandReference(commandReference) + ChatColor.YELLOW + "?"); + + result.getCommandDescription() + ChatColor.YELLOW + "?"); + // TODO: Define a proper string representation of command description } sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/" + baseCommand + " help" @@ -212,28 +116,115 @@ public class CommandHandler { private static void sendImproperArgumentsMessage(CommandSender sender, FoundCommandResult result, CommandParts commandReference, String baseCommand) { // Get the command and the suggested command reference - List suggestedCommandReference = - result.getCommandDescription().getCommandReference(commandReference).getList(); - List helpCommandReference = CollectionUtils.getRange(suggestedCommandReference, 1); + // FIXME List suggestedCommandReference = + // result.getCommandDescription().getCommandReference(commandReference).getList(); + // List helpCommandReference = CollectionUtils.getRange(suggestedCommandReference, 1); // Show the invalid arguments warning sender.sendMessage(ChatColor.DARK_RED + "Incorrect command arguments!"); // Show the command argument help - HelpProvider.showHelp(sender, commandReference, new CommandParts(suggestedCommandReference), - true, false, true, false, false, false); + // HelpProvider.showHelp(sender, commandReference, new CommandParts(suggestedCommandReference), + // true, false, true, false, false, false); // Show the command to use for detailed help - sender.sendMessage(ChatColor.GOLD + "Detailed help: " + ChatColor.WHITE + "/" + baseCommand - + " help " + CommandUtils.labelsToString(helpCommandReference)); + // sender.sendMessage(ChatColor.GOLD + "Detailed help: " + ChatColor.WHITE + "/" + baseCommand + // + " help " + CommandUtils.labelsToString(helpCommandReference)); } - private static void sendCommandAssumptionMessage(CommandSender sender, FoundCommandResult result, - CommandParts commandReference) { - List assumedCommandParts = - result.getCommandDescription().getCommandReference(commandReference).getList(); + public FoundCommandResult mapPartsToCommand(final List parts) { + if (CollectionUtils.isEmpty(parts)) { + return new FoundCommandResult(null, parts, null, 0.0, FoundCommandResult.ResultStatus.MISSING_BASE_COMMAND); + } + + CommandDescription base = getBaseCommand(parts.get(0)); + if (base == null) { + return new FoundCommandResult(null, parts, null, 0.0, FoundCommandResult.ResultStatus.MISSING_BASE_COMMAND); + } + + // Prefer labels: /register help goes to "Help command", not "Register command" with argument 'help' + List remaining = parts.subList(1, parts.size()); + CommandDescription childCommand = returnSuitableChild(base, remaining); + if (childCommand != null) { + return new FoundCommandResult(childCommand, parts.subList(2, parts.size()), parts.subList(0, 2)); + } else if (isSuitableArgumentCount(base, remaining.size())) { + return new FoundCommandResult(base, parts.subList(1, parts.size()), parts.subList(0, 1)); + } + + // TODO: return getCommandWithSmallestDifference() + return null; - sender.sendMessage(ChatColor.DARK_RED + "Unknown command, assuming " + ChatColor.GOLD + "/" - + CommandUtils.labelsToString(assumedCommandParts) + ChatColor.DARK_RED + "!"); } + + // TODO: Return FoundCommandDescription immediately + private CommandDescription getCommandWithSmallestDifference(CommandDescription base, List parts) { + final String label = parts.get(0); + final int argumentCount = parts.size() - 1; + + double minDifference = Double.POSITIVE_INFINITY; + CommandDescription closestCommand = null; + for (CommandDescription child : base.getChildren()) { + double argumentDifference = getArgumentCountDifference(child, argumentCount); + double labelDifference = getLabelDifference(child, label); + // Weigh argument difference less + double difference = labelDifference + argumentCount / 2; + if (difference < minDifference) { + minDifference = difference; + closestCommand = child; + } + } + return closestCommand; + } + + private static boolean isSuitableArgumentCount(CommandDescription command, int argumentCount) { + int minArgs = CommandUtils.getMinNumberOfArguments(command); + int maxArgs = CommandUtils.getMaxNumberOfArguments(command); + + return argumentCount >= minArgs && argumentCount <= maxArgs; + } + + private static double getLabelDifference(CommandDescription command, String givenLabel) { + double minDifference = Double.POSITIVE_INFINITY; + for (String commandLabel : command.getLabels()) { + double difference = StringUtils.getDifference(commandLabel, givenLabel); + if (difference < minDifference) { + minDifference = difference; + } + } + return minDifference; + } + + private static int getArgumentCountDifference(CommandDescription commandDescription, int givenArgumentsCount) { + return Math.min( + Math.abs(givenArgumentsCount - CommandUtils.getMinNumberOfArguments(commandDescription)), + Math.abs(givenArgumentsCount - CommandUtils.getMaxNumberOfArguments(commandDescription))); + } + + // Is the given command a suitable match for the given parts? parts is for example [changepassword, newpw, newpw] + public CommandDescription returnSuitableChild(CommandDescription baseCommand, List parts) { + if (CollectionUtils.isEmpty(parts)) { + return null; + } + + final String label = parts.get(0).toLowerCase(); + final int argumentCount = parts.size() - 1; + + for (CommandDescription child : baseCommand.getChildren()) { + if (child.hasLabel(label) && isSuitableArgumentCount(child, argumentCount)) { + return child; + } + } + return null; + } + + private CommandDescription getBaseCommand(String label) { + String baseLabel = label.toLowerCase(); + for (CommandDescription command : baseCommands) { + if (command.hasLabel(baseLabel)) { + return command; + } + } + return null; + } + } diff --git a/src/main/java/fr/xephi/authme/command/CommandMapper.java b/src/main/java/fr/xephi/authme/command/CommandMapper.java deleted file mode 100644 index a6a74551..00000000 --- a/src/main/java/fr/xephi/authme/command/CommandMapper.java +++ /dev/null @@ -1,128 +0,0 @@ -package fr.xephi.authme.command; - -import fr.xephi.authme.util.CollectionUtils; -import fr.xephi.authme.util.StringUtils; - -import java.util.ArrayList; -import java.util.List; - -/** - * Class responsible for mapping incoming arguments to a {@link CommandDescription}. - */ -public class CommandMapper { - - /** - * The threshold for assuming an existing command. If the difference is below this value, we assume - * that the user meant the similar command and we will run it. - */ - private static final double ASSUME_COMMAND_THRESHOLD = 0.12; - - /** - * The threshold for suggesting a similar command. If the difference is below this value, we will - * ask the player whether he meant the similar command. - */ - private static final double SUGGEST_COMMAND_THRESHOLD = 0.75; - - /** - * Map incoming command parts to an actual command. - * - * @param parts The parts to process - * @return The generated result - */ - public FoundCommandResult mapPartsToCommand(final List parts) { - if (CollectionUtils.isEmpty(parts)) { - return null; // TODO pass on the information that the base could not be mapped - } - - CommandDescription base = getBaseCommand(parts.get(0)); - if (base == null) { - return null; // TODO Pass on the information that base could not be mapped - } - - List remaining = parts.subList(1, parts.size()); - - // Prefer labels: /register help goes to "Help command", not "Register command" with argument 'help' - CommandDescription childCommand = returnSuitableChild(base, remaining); - if (childCommand != null) { - // return childcommand: it's valid... - } else if (isSuitableArgumentCount(base, remaining.size())) { - // return base... it's valid - } - - // TODO: return getCommandWithSmallestDifference() - return null; - - } - - // TODO: Return FoundCommandDescription immediately - private CommandDescription getCommandWithSmallestDifference(CommandDescription base, List parts) { - final String label = parts.get(0); - final int argumentCount = parts.size() - 1; - - double minDifference = Double.POSITIVE_INFINITY; - CommandDescription closestCommand = null; - for (CommandDescription child : base.getChildren()) { - double argumentDifference = getArgumentCountDifference(child, argumentCount); - double labelDifference = getLabelDifference(child, label); - // Weigh argument difference less - double difference = labelDifference + argumentCount / 2; - if (difference < minDifference) { - minDifference = difference; - closestCommand = child; - } - } - return closestCommand; - } - - private static boolean isSuitableArgumentCount(CommandDescription command, int argumentCount) { - int minArgs = CommandUtils.getMinNumberOfArguments(command); - int maxArgs = CommandUtils.getMaxNumberOfArguments(command); - - return argumentCount >= minArgs && argumentCount <= maxArgs; - } - - private static double getLabelDifference(CommandDescription command, String givenLabel) { - double minDifference = Double.POSITIVE_INFINITY; - for (String commandLabel : command.getLabels()) { - double difference = StringUtils.getDifference(commandLabel, givenLabel); - if (difference < minDifference) { - minDifference = difference; - } - } - return minDifference; - } - - private static int getArgumentCountDifference(CommandDescription commandDescription, int givenArgumentsCount) { - return Math.min( - Math.abs(givenArgumentsCount - CommandUtils.getMinNumberOfArguments(commandDescription)), - Math.abs(givenArgumentsCount - CommandUtils.getMaxNumberOfArguments(commandDescription))); - } - - // Is the given command a suitable match for the given parts? parts is for example [changepassword, newpw, newpw] - public CommandDescription returnSuitableChild(CommandDescription baseCommand, List parts) { - if (CollectionUtils.isEmpty(parts)) { - return null; - } - - final String label = parts.get(0).toLowerCase(); - final int argumentCount = parts.size() - 1; - - for (CommandDescription child : baseCommand.getChildren()) { - if (child.getLabels().contains(label) && isSuitableArgumentCount(child, argumentCount)) { - return child; - } - } - return null; - } - - public CommandDescription getBaseCommand(String label) { - String baseLabel = label.toLowerCase(); - for (CommandDescription command : CommandInitializer.getBaseCommands()) { - if (command.getLabels().contains(baseLabel)) { - return command; - } - } - return null; - } - -} From 2f153fb85c48a86931da9698706fce1af30defaa Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sat, 12 Dec 2015 00:43:55 +0100 Subject: [PATCH 05/18] =?UTF-8?q?#305=20Modularize=20logic=20/=20separate?= =?UTF-8?q?=20from=20data=20classes=20(wip=20=E2=80=93=20doesn't=20compile?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove permission logic on command side; make PermissionsManager handle checks for all CommandSender objects (not only Player), cf. #314 - Remove unnecessary redundancies in passed arguments ("command references" that can be inferred from the FoundResult) - Extend FoundCommandResult to represent all possible error cases --- src/main/java/fr/xephi/authme/AuthMe.java | 19 ++- .../authme/command/CommandDescription.java | 69 +++++---- .../xephi/authme/command/CommandHandler.java | 127 +++++++++-------- .../fr/xephi/authme/command/CommandUtils.java | 25 ---- .../authme/command/FoundCommandResult.java | 134 +++++------------- .../authme/permission/PermissionsManager.java | 27 ++-- .../authme/permission/PermissionsService.java | 9 +- ...ndPartsTest.java => CommandUtilsTest.java} | 13 +- 8 files changed, 178 insertions(+), 245 deletions(-) rename src/test/java/fr/xephi/authme/command/{CommandPartsTest.java => CommandUtilsTest.java} (62%) diff --git a/src/main/java/fr/xephi/authme/AuthMe.java b/src/main/java/fr/xephi/authme/AuthMe.java index 655a1f33..3a482185 100644 --- a/src/main/java/fr/xephi/authme/AuthMe.java +++ b/src/main/java/fr/xephi/authme/AuthMe.java @@ -214,11 +214,9 @@ public class AuthMe extends JavaPlugin { plugin = this; setupConstants(); - // Set up the permissions manager - setupPermissionsManager(); - - // Set up and initialize the command handler - setupCommandHandler(); + // Set up the permissions manager and command handler + permsMan = initializePermissionsManager(); + commandHandler = new CommandHandler(CommandInitializer.getBaseCommands(), permsMan); // Set up the module manager setupModuleManager(); @@ -433,8 +431,8 @@ public class AuthMe extends JavaPlugin { /** * Set up the command handler. */ - private void setupCommandHandler() { - this.commandHandler = new CommandHandler(CommandInitializer.getBaseCommands()); + private void setupCommandHandler(PermissionsManager permissionsManager) { + this.commandHandler = new CommandHandler(CommandInitializer.getBaseCommands(), permissionsManager); } /** @@ -606,9 +604,10 @@ public class AuthMe extends JavaPlugin { /** * Set up the permissions manager. */ - public void setupPermissionsManager() { - this.permsMan = new PermissionsManager(Bukkit.getServer(), this, getLogger()); - this.permsMan.setup(); + private PermissionsManager initializePermissionsManager() { + PermissionsManager manager = new PermissionsManager(Bukkit.getServer(), this, getLogger()); + manager.setup(); + return manager; } /** diff --git a/src/main/java/fr/xephi/authme/command/CommandDescription.java b/src/main/java/fr/xephi/authme/command/CommandDescription.java index a523dfb4..e2037574 100644 --- a/src/main/java/fr/xephi/authme/command/CommandDescription.java +++ b/src/main/java/fr/xephi/authme/command/CommandDescription.java @@ -14,6 +14,7 @@ import java.util.Comparator; import java.util.List; import static com.google.common.base.Objects.firstNonNull; +import static java.util.Arrays.asList; /** * Command description - defines which labels ("names") will lead to a command and points to the @@ -31,15 +32,15 @@ public class CommandDescription { */ private List labels; /** - * Command description. + * Short description of the command. */ private String description; /** - * Detailed description of the command. + * Detailed description of what the command does. */ private String detailedDescription; /** - * The executable command instance. + * The executable command instance described by this object. */ private ExecutableCommand executableCommand; /** @@ -55,7 +56,7 @@ public class CommandDescription { */ private List arguments; /** - * Defines the command permissions. + * Command permissions required to execute this command. */ private CommandPermissions permissions; @@ -106,9 +107,10 @@ public class CommandDescription { } /** - * Get all relative command labels. + * Get all relative labels of this command. For example, if this object describes "/authme register" and + * "/authme r", then "r" and "register" are the relative labels, whereas "authme" is the label of the parent. * - * @return All relative labels labels. + * @return All relative labels. */ public List getLabels() { return this.labels; @@ -117,9 +119,9 @@ public class CommandDescription { /** * Check whether this command description has a specific command. * - * @param commandLabel Command to check for. + * @param commandLabel The label to check for. * - * @return True if this command label equals to the param command. + * @return {@code true} if this command contains the given label, {@code false} otherwise. */ public boolean hasLabel(String commandLabel) { for (String label : labels) { @@ -131,25 +133,25 @@ public class CommandDescription { } /** - * Get the executable command. + * Return the {@link ExecutableCommand} instance defined by the command description. * - * @return The executable command. + * @return The executable command object. */ public ExecutableCommand getExecutableCommand() { - return this.executableCommand; + return executableCommand; } /** - * Get the parent command if this command description has a parent. + * Return the parent. * - * @return Parent command, or null + * @return The parent command, or null for base commands. */ public CommandDescription getParent() { - return this.parent; + return parent; } /** - * Get all command children. + * Return all command children. * * @return Command children. */ @@ -159,7 +161,7 @@ public class CommandDescription { /** - * Get all command arguments. + * Return all arguments the command takes. * * @return Command arguments. */ @@ -168,16 +170,7 @@ public class CommandDescription { } /** - * Check whether this command has any arguments. - * - * @return True if this command has any arguments. - */ - public boolean hasArguments() { - return !getArguments().isEmpty(); - } - - /** - * Get the command description. + * Return a short description of the command. * * @return Command description. */ @@ -186,9 +179,9 @@ public class CommandDescription { } /** - * Get the command detailed description. + * Return a detailed description of the command. * - * @return Command detailed description. + * @return Detailed description. */ public String getDetailedDescription() { return detailedDescription; @@ -196,14 +189,19 @@ public class CommandDescription { /** - * Get the command permissions. Return null if the command doesn't require any permission. + * Return the permissions required to execute the command. * - * @return The command permissions. + * @return The command permissions, or null if none are required to execute the command. */ public CommandPermissions getCommandPermissions() { return this.permissions; } + /** + * Return a builder instance to create a new command description. + * + * @return The builder + */ public static CommandBuilder builder() { return new CommandBuilder(); } @@ -221,12 +219,11 @@ public class CommandDescription { private CommandPermissions permissions; /** - * Build a CommandDescription from the builder or throw an exception if mandatory - * fields have not been set. + * Build a CommandDescription from the builder or throw an exception if a mandatory + * field has not been set. * * @return The generated CommandDescription object */ - // TODO ljacqu 20151206 Move validation to the create instance method public CommandDescription build() { return createInstance( getOrThrow(labels, "labels"), @@ -245,7 +242,7 @@ public class CommandDescription { } public CommandBuilder labels(String... labels) { - return labels(asMutableList(labels)); + return labels(asList(labels)); } public CommandBuilder description(String description) { @@ -274,7 +271,7 @@ public class CommandDescription { * * @param label The label of the argument (single word name of the argument) * @param description The description of the argument - * @param isOptional True if the argument is option, false if it is mandatory + * @param isOptional True if the argument is optional, false if it is mandatory * * @return The builder */ @@ -291,7 +288,7 @@ public class CommandDescription { @SafeVarargs private static List asMutableList(T... items) { - return new ArrayList<>(Arrays.asList(items)); + return new ArrayList<>(asList(items)); } private static T getOrThrow(T element, String elementName) { diff --git a/src/main/java/fr/xephi/authme/command/CommandHandler.java b/src/main/java/fr/xephi/authme/command/CommandHandler.java index 3b187380..4463d408 100644 --- a/src/main/java/fr/xephi/authme/command/CommandHandler.java +++ b/src/main/java/fr/xephi/authme/command/CommandHandler.java @@ -6,6 +6,7 @@ import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.util.CollectionUtils; import fr.xephi.authme.util.StringUtils; import org.bukkit.ChatColor; +import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import java.util.ArrayList; @@ -56,16 +57,16 @@ public class CommandHandler { FoundCommandResult result = mapPartsToCommand(parts); switch (result.getResultStatus()) { case SUCCESS: - // Check perms + process + executeCommandIfAllowed(sender, result.getCommandDescription(), result.getArguments()); break; case MISSING_BASE_COMMAND: sender.sendMessage(ChatColor.DARK_RED + "Failed to parse " + AuthMe.getPluginName() + " command!"); return false; case INCORRECT_ARGUMENTS: - // sendImproperArgumentsMessage(sender, result); + sendImproperArgumentsMessage(sender, result); break; case UNKNOWN_LABEL: - // sendUnknownCommandMessage(sender); + sendUnknownCommandMessage(sender, result); break; default: throw new RuntimeException("Unknown result '" + result.getResultStatus() + "'"); @@ -74,6 +75,14 @@ public class CommandHandler { return true; } + private void executeCommandIfAllowed(CommandSender sender, CommandDescription command, List arguments) { + if (permissionsManager.hasPermission(sender, command)) { + command.getExecutableCommand().executeCommand(sender, arguments); + } else { + sendPermissionDeniedError(sender); + } + } + /** * Skip all entries of the given array that are simply whitespace. * @@ -81,7 +90,7 @@ public class CommandHandler { * @return List of the items that are not empty */ private static List skipEmptyArguments(String[] args) { - List cleanArguments = new ArrayList<>(args.length); + List cleanArguments = new ArrayList<>(); for (String argument : args) { if (!StringUtils.isEmpty(argument)) { cleanArguments.add(argument); @@ -90,16 +99,14 @@ public class CommandHandler { return cleanArguments; } - /** * Show an "unknown command" to the user and suggests an existing command if its similarity is within * the defined threshold. * * @param sender The command sender * @param result The command that was found during the mapping process - * @param baseCommand The base command */ - private static void sendUnknownCommandMessage(CommandSender sender, FoundCommandResult result, String baseCommand) { + private static void sendUnknownCommandMessage(CommandSender sender, FoundCommandResult result) { sender.sendMessage(ChatColor.DARK_RED + "Unknown command!"); // Show a command suggestion if available and the difference isn't too big @@ -109,27 +116,29 @@ public class CommandHandler { // TODO: Define a proper string representation of command description } - sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/" + baseCommand + " help" - + ChatColor.YELLOW + " to view help."); + sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/" + result.getLabels().get(0) + + " help" + ChatColor.YELLOW + " to view help."); } - private static void sendImproperArgumentsMessage(CommandSender sender, FoundCommandResult result, - CommandParts commandReference, String baseCommand) { - // Get the command and the suggested command reference - // FIXME List suggestedCommandReference = - // result.getCommandDescription().getCommandReference(commandReference).getList(); - // List helpCommandReference = CollectionUtils.getRange(suggestedCommandReference, 1); - - // Show the invalid arguments warning - sender.sendMessage(ChatColor.DARK_RED + "Incorrect command arguments!"); + private void sendImproperArgumentsMessage(CommandSender sender, FoundCommandResult result) { + CommandDescription command = result.getCommandDescription(); + if (!permissionsManager.hasPermission(sender, command)) { + sendPermissionDeniedError(sender); + return; + } // Show the command argument help - // HelpProvider.showHelp(sender, commandReference, new CommandParts(suggestedCommandReference), - // true, false, true, false, false, false); + sender.sendMessage(ChatColor.DARK_RED + "Incorrect command arguments!"); + // TODO: Define showHelp(CommandSender, CommandDescription, List, boolean, boolean, ...) + List labels = result.getLabels(); + HelpProvider.showHelp(sender, command, labels, true, false, true, false, false, false); + sender.sendMessage(ChatColor.GOLD + "Detailed help: " + ChatColor.WHITE + "/" + labels.get(0) + + " help " + CommandUtils.labelsToString(labels.subList(1, labels.size()))); + } - // Show the command to use for detailed help - // sender.sendMessage(ChatColor.GOLD + "Detailed help: " + ChatColor.WHITE + "/" + baseCommand - // + " help " + CommandUtils.labelsToString(helpCommandReference)); + // TODO ljacqu 20151212: Remove me once I am a MessageKey + private void sendPermissionDeniedError(CommandSender sender) { + sender.sendMessage(ChatColor.DARK_RED + "You don't have permission to use this command!"); } public FoundCommandResult mapPartsToCommand(final List parts) { @@ -144,64 +153,50 @@ public class CommandHandler { // Prefer labels: /register help goes to "Help command", not "Register command" with argument 'help' List remaining = parts.subList(1, parts.size()); - CommandDescription childCommand = returnSuitableChild(base, remaining); + CommandDescription childCommand = getSuitableChild(base, remaining); if (childCommand != null) { return new FoundCommandResult(childCommand, parts.subList(2, parts.size()), parts.subList(0, 2)); } else if (isSuitableArgumentCount(base, remaining.size())) { return new FoundCommandResult(base, parts.subList(1, parts.size()), parts.subList(0, 1)); } - // TODO: return getCommandWithSmallestDifference() - return null; - + return getCommandWithSmallestDifference(base, parts); } - // TODO: Return FoundCommandDescription immediately - private CommandDescription getCommandWithSmallestDifference(CommandDescription base, List parts) { + private FoundCommandResult getCommandWithSmallestDifference(CommandDescription base, List parts) { final String label = parts.get(0); final int argumentCount = parts.size() - 1; double minDifference = Double.POSITIVE_INFINITY; CommandDescription closestCommand = null; for (CommandDescription child : base.getChildren()) { - double argumentDifference = getArgumentCountDifference(child, argumentCount); double labelDifference = getLabelDifference(child, label); + double argumentDifference = getArgumentCountDifference(child, argumentCount); // Weigh argument difference less - double difference = labelDifference + argumentCount / 2; + double difference = labelDifference + argumentDifference / 2; if (difference < minDifference) { minDifference = difference; closestCommand = child; } } - return closestCommand; + // TODO: Return the full list of labels and arguments + // TODO: Also compare the base command and suggest it if it's the most similar + return new FoundCommandResult( + closestCommand, null, null, minDifference, FoundCommandResult.ResultStatus.UNKNOWN_LABEL); } - private static boolean isSuitableArgumentCount(CommandDescription command, int argumentCount) { - int minArgs = CommandUtils.getMinNumberOfArguments(command); - int maxArgs = CommandUtils.getMaxNumberOfArguments(command); - - return argumentCount >= minArgs && argumentCount <= maxArgs; - } - - private static double getLabelDifference(CommandDescription command, String givenLabel) { - double minDifference = Double.POSITIVE_INFINITY; - for (String commandLabel : command.getLabels()) { - double difference = StringUtils.getDifference(commandLabel, givenLabel); - if (difference < minDifference) { - minDifference = difference; + private CommandDescription getBaseCommand(String label) { + String baseLabel = label.toLowerCase(); + for (CommandDescription command : baseCommands) { + if (command.hasLabel(baseLabel)) { + return command; } } - return minDifference; - } - - private static int getArgumentCountDifference(CommandDescription commandDescription, int givenArgumentsCount) { - return Math.min( - Math.abs(givenArgumentsCount - CommandUtils.getMinNumberOfArguments(commandDescription)), - Math.abs(givenArgumentsCount - CommandUtils.getMaxNumberOfArguments(commandDescription))); + return null; } // Is the given command a suitable match for the given parts? parts is for example [changepassword, newpw, newpw] - public CommandDescription returnSuitableChild(CommandDescription baseCommand, List parts) { + private CommandDescription getSuitableChild(CommandDescription baseCommand, List parts) { if (CollectionUtils.isEmpty(parts)) { return null; } @@ -217,14 +212,28 @@ public class CommandHandler { return null; } - private CommandDescription getBaseCommand(String label) { - String baseLabel = label.toLowerCase(); - for (CommandDescription command : baseCommands) { - if (command.hasLabel(baseLabel)) { - return command; + private static boolean isSuitableArgumentCount(CommandDescription command, int argumentCount) { + int minArgs = CommandUtils.getMinNumberOfArguments(command); + int maxArgs = CommandUtils.getMaxNumberOfArguments(command); + + return argumentCount >= minArgs && argumentCount <= maxArgs; + } + + private static int getArgumentCountDifference(CommandDescription commandDescription, int givenArgumentsCount) { + return Math.min( + Math.abs(givenArgumentsCount - CommandUtils.getMinNumberOfArguments(commandDescription)), + Math.abs(givenArgumentsCount - CommandUtils.getMaxNumberOfArguments(commandDescription))); + } + + private static double getLabelDifference(CommandDescription command, String givenLabel) { + double minDifference = Double.POSITIVE_INFINITY; + for (String commandLabel : command.getLabels()) { + double difference = StringUtils.getDifference(commandLabel, givenLabel); + if (difference < minDifference) { + minDifference = difference; } } - return null; + return minDifference; } } diff --git a/src/main/java/fr/xephi/authme/command/CommandUtils.java b/src/main/java/fr/xephi/authme/command/CommandUtils.java index 6025a5d9..faed9639 100644 --- a/src/main/java/fr/xephi/authme/command/CommandUtils.java +++ b/src/main/java/fr/xephi/authme/command/CommandUtils.java @@ -1,8 +1,5 @@ package fr.xephi.authme.command; -import java.util.List; - -import fr.xephi.authme.util.CollectionUtils; import fr.xephi.authme.util.StringUtils; public final class CommandUtils { @@ -32,26 +29,4 @@ public final class CommandUtils { return StringUtils.join(" ", labels); } - public static double getDifference(List labels1, List labels2, boolean fullCompare) { - // Make sure the other reference is correct - if (labels1 == null || labels2 == null) { - return -1; - } - - // Get the range to use - int range = Math.min(labels1.size(), labels2.size()); - - // Get and the difference - if (fullCompare) { - return StringUtils.getDifference(CommandUtils.labelsToString(labels1), CommandUtils.labelsToString(labels2)); - } - return StringUtils.getDifference( - labelsToString(CollectionUtils.getRange(labels1, range - 1, 1)), - labelsToString(CollectionUtils.getRange(labels2, range - 1, 1))); - } - - - - - } diff --git a/src/main/java/fr/xephi/authme/command/FoundCommandResult.java b/src/main/java/fr/xephi/authme/command/FoundCommandResult.java index 91551650..99750069 100644 --- a/src/main/java/fr/xephi/authme/command/FoundCommandResult.java +++ b/src/main/java/fr/xephi/authme/command/FoundCommandResult.java @@ -1,6 +1,6 @@ package fr.xephi.authme.command; -import org.bukkit.command.CommandSender; +import java.util.List; /** */ @@ -9,47 +9,39 @@ public class FoundCommandResult { /** * The command description instance. */ - private CommandDescription commandDescription; - /** - * The command reference. - */ - private final CommandParts commandReference; + private final CommandDescription commandDescription; /** * The command arguments. */ - private final CommandParts commandArguments; + private final List arguments; /** - * The original search query reference. + * The labels used to invoke the command. This may be different for the same {@link ExecutableCommand} instance + * if multiple labels have been defined, e.g. "/authme register" and "/authme reg". */ - private final CommandParts queryReference; + private final List labels; + + private final double difference; + + private final ResultStatus resultStatus; /** * Constructor. * * @param commandDescription The command description. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * @param queryReference The original query reference. + * @param arguments The command arguments. + * @param labels The original query reference. */ - public FoundCommandResult(CommandDescription commandDescription, CommandParts commandReference, CommandParts commandArguments, CommandParts queryReference) { + public FoundCommandResult(CommandDescription commandDescription, List arguments, List labels, + double difference, ResultStatus resultStatus) { this.commandDescription = commandDescription; - this.commandReference = commandReference; - this.commandArguments = commandArguments; - this.queryReference = queryReference; + this.arguments = arguments; + this.labels = labels; + this.difference = difference; + this.resultStatus = resultStatus; } - /** - * Check whether the command was suitable. - * - * @return True if the command was suitable, false otherwise. - */ - public boolean hasProperArguments() { - // Make sure the command description is set - if (this.commandDescription == null) - return false; - - // Get and return the result - return getCommandDescription().getSuitableArgumentsDifference(this.queryReference) == 0; + public FoundCommandResult(CommandDescription commandDescription, List arguments, List labels) { + this(commandDescription, arguments, labels, 0.0, ResultStatus.SUCCESS); } /** @@ -61,66 +53,14 @@ public class FoundCommandResult { return this.commandDescription; } - /** - * Check whether the command is executable. - * - * @return True if the command is executable, false otherwise. - */ - public boolean isExecutable() { - return commandDescription != null; - } - - /** - * Execute the command. - * - * @param sender The command sender that executed the command. - * - * @return True on success, false on failure. - */ - public boolean executeCommand(CommandSender sender) { - // Make sure the command description is valid - if (this.commandDescription == null) - return false; - - // Execute the command - return this.commandDescription.execute(sender, this.commandReference, this.commandArguments); - } - - /** - * Check whether a command sender has permission to execute the command. - * - * @param sender The command sender. - * - * @return True if the command sender has permission, false otherwise. - */ - public boolean hasPermission(CommandSender sender) { - if (commandDescription == null) { - return false; - } else if (commandDescription.getCommandPermissions() == null) { - return true; - } - - // TODO: Move permissions check to the permission package; command package should not define permission-checking - // API - return commandDescription.getCommandPermissions().hasPermission(sender); - } - - /** - * Get the command reference. - * - * @return The command reference. - */ - public CommandParts getCommandReference() { - return this.commandReference; - } /** * Get the command arguments. * * @return The command arguments. */ - public CommandParts getCommandArguments() { - return this.commandArguments; + public List getArguments() { + return this.arguments; } /** @@ -128,22 +68,26 @@ public class FoundCommandResult { * * @return Original query reference. */ - public CommandParts getQueryReference() { - return this.queryReference; + public List getLabels() { + return this.labels; } - /** - * Get the difference value between the original query and the result reference. - * - * @return The difference value. - */ public double getDifference() { - // Get the difference through the command found - if (this.commandDescription != null) { - return this.commandDescription.getCommandDifference(this.queryReference); - } + return difference; + } - // Get the difference from the query reference - return CommandUtils.getDifference(queryReference.getList(), commandReference.getList(), true); + public ResultStatus getResultStatus() { + return resultStatus; + } + + public enum ResultStatus { + + SUCCESS, + + INCORRECT_ARGUMENTS, + + UNKNOWN_LABEL, + + MISSING_BASE_COMMAND } } diff --git a/src/main/java/fr/xephi/authme/permission/PermissionsManager.java b/src/main/java/fr/xephi/authme/permission/PermissionsManager.java index 63d755e8..971cd79a 100644 --- a/src/main/java/fr/xephi/authme/permission/PermissionsManager.java +++ b/src/main/java/fr/xephi/authme/permission/PermissionsManager.java @@ -301,19 +301,24 @@ public class PermissionsManager implements PermissionsService { /** - * Check if the player has permission for the given permissions node. If no permissions system is used, - * the player has to be OP in order to have the permission. + * Check if the command sender has permission for the given permissions node. If no permissions system is used or + * if the sender is not a player (e.g. console user), the player has to be OP in order to have the permission. * - * @param player The player. + * @param sender The command sender. * @param permissionNode The permissions node to verify. * - * @return True if the player has the permission, false otherwise. + * @return True if the sender has the permission, false otherwise. */ - public boolean hasPermission(Player player, PermissionNode permissionNode) { - return hasPermission(player, permissionNode, player.isOp()); + public boolean hasPermission(CommandSender sender, PermissionNode permissionNode) { + return hasPermission(sender, permissionNode, sender.isOp()); } - public boolean hasPermission(Player player, PermissionNode permissionNode, boolean def) { + public boolean hasPermission(CommandSender sender, PermissionNode permissionNode, boolean def) { + if (!(sender instanceof Player)) { + return def; + } + + Player player = (Player) sender; return hasPermission(player, permissionNode.getNode(), def) || hasPermission(player, permissionNode.getWildcardNode().getNode(), def); } @@ -327,15 +332,17 @@ public class PermissionsManager implements PermissionsService { return true; } - public boolean hasPermission(Player player, CommandDescription command) { + public boolean hasPermission(CommandSender sender, CommandDescription command) { if (command.getCommandPermissions() == null || CollectionUtils.isEmpty(command.getCommandPermissions().getPermissionNodes())) { return true; } DefaultPermission defaultPermission = command.getCommandPermissions().getDefaultPermission(); - boolean def = evaluateDefaultPermission(defaultPermission, player); - return hasPermission(player, command.getCommandPermissions().getPermissionNodes(), def); + boolean def = evaluateDefaultPermission(defaultPermission, sender); + return (sender instanceof Player) + ? hasPermission((Player) sender, command.getCommandPermissions().getPermissionNodes(), def) + : def; } public static boolean evaluateDefaultPermission(DefaultPermission defaultPermission, CommandSender sender) { diff --git a/src/main/java/fr/xephi/authme/permission/PermissionsService.java b/src/main/java/fr/xephi/authme/permission/PermissionsService.java index 4c630c56..82f24ea0 100644 --- a/src/main/java/fr/xephi/authme/permission/PermissionsService.java +++ b/src/main/java/fr/xephi/authme/permission/PermissionsService.java @@ -1,6 +1,7 @@ package fr.xephi.authme.permission; import fr.xephi.authme.command.CommandDescription; +import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; /** @@ -11,23 +12,23 @@ public interface PermissionsService { /** * Check if the player has the given permission. * - * @param player The player + * @param sender The command sender * @param permission The permission node to check * @param def Default returned if no permissions system is used * * @return True if the player has permission */ - boolean hasPermission(Player player, PermissionNode permission, boolean def); + boolean hasPermission(CommandSender sender, PermissionNode permission, boolean def); /** * Check if the player has the permissions for the given command. * - * @param player The player + * @param sender The command sender * @param command The command whose permissions should be checked * * @return True if the player may execute the command */ - boolean hasPermission(Player player, CommandDescription command); + boolean hasPermission(CommandSender sender, CommandDescription command); /** * Return the permission system the service is working with. diff --git a/src/test/java/fr/xephi/authme/command/CommandPartsTest.java b/src/test/java/fr/xephi/authme/command/CommandUtilsTest.java similarity index 62% rename from src/test/java/fr/xephi/authme/command/CommandPartsTest.java rename to src/test/java/fr/xephi/authme/command/CommandUtilsTest.java index 163f52d4..1d7baaab 100644 --- a/src/test/java/fr/xephi/authme/command/CommandPartsTest.java +++ b/src/test/java/fr/xephi/authme/command/CommandUtilsTest.java @@ -4,22 +4,23 @@ import org.junit.Test; import java.util.Arrays; import java.util.Collections; +import java.util.List; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; /** - * Test for {@link CommandParts}. + * Test for {@link CommandUtils}. */ -public class CommandPartsTest { +public class CommandUtilsTest { @Test public void shouldPrintPartsForStringRepresentation() { // given - CommandParts parts = new CommandParts(Arrays.asList("some", "parts", "for", "test")); + Iterable parts = Arrays.asList("some", "parts", "for", "test"); // when - String str = parts.toString(); + String str = CommandUtils.labelsToString(parts); // then assertThat(str, equalTo("some parts for test")); @@ -28,10 +29,10 @@ public class CommandPartsTest { @Test public void shouldPrintEmptyStringForNoArguments() { // given - CommandParts parts = new CommandParts(Collections.EMPTY_LIST); + List parts = Collections.EMPTY_LIST; // when - String str = parts.toString(); + String str = CommandUtils.labelsToString(parts); // then assertThat(str, equalTo("")); From eecad8074850b6e4a67ddc4c4cae1f4de78c580e Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sat, 12 Dec 2015 11:39:19 +0100 Subject: [PATCH 06/18] =?UTF-8?q?Change=20ExecutableCommand=20interface=20?= =?UTF-8?q?(wip=20=E2=80=93=20doesn't=20compile)=20-=20Change=20interface?= =?UTF-8?q?=20to=20use=20(CommandSender,=20List=20arguments)=20-?= =?UTF-8?q?=20Use=20CommandArgumentDescription#name=20instead=20of=20"labe?= =?UTF-8?q?l"=20(to=20prevent=20confusion=20between=20command=20labels=20a?= =?UTF-8?q?nd=20arguments)=20-=20Simplify=20command=20difference=20computa?= =?UTF-8?q?tion=20in=20CommandHandler=20(no=20longer=20consider=20argument?= =?UTF-8?q?=20difference)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../command/CommandArgumentDescription.java | 18 ++-- .../authme/command/CommandDescription.java | 5 -- .../xephi/authme/command/CommandHandler.java | 35 ++++---- .../authme/command/CommandPermissions.java | 56 ------------ .../authme/command/ExecutableCommand.java | 13 ++- .../executable/authme/AccountsCommand.java | 12 +-- .../executable/authme/AuthMeCommand.java | 9 +- .../authme/ChangePasswordAdminCommand.java | 20 ++--- .../executable/authme/FirstSpawnCommand.java | 8 +- .../executable/authme/ForceLoginCommand.java | 17 ++-- .../executable/authme/GetEmailCommand.java | 23 +---- .../executable/authme/GetIpCommand.java | 17 ++-- .../executable/authme/LastLoginCommand.java | 12 ++- .../authme/PurgeBannedPlayersCommand.java | 15 +--- .../executable/authme/PurgeCommand.java | 25 ++---- .../authme/PurgeLastPositionCommand.java | 18 +--- .../authme/RegisterAdminCommand.java | 2 +- .../executable/authme/ReloadCommand.java | 20 +---- .../executable/authme/SetEmailCommand.java | 28 ++---- .../authme/SetFirstSpawnCommand.java | 17 +--- .../executable/authme/SetSpawnCommand.java | 17 +--- .../executable/authme/SpawnCommand.java | 19 +---- .../authme/SwitchAntiBotCommand.java | 25 ++---- .../authme/UnregisterAdminCommand.java | 22 ++--- .../executable/authme/VersionCommand.java | 18 +--- .../executable/captcha/CaptchaCommand.java | 22 +++-- .../changepassword/ChangePasswordCommand.java | 22 ++--- .../converter/ConverterCommand.java | 85 +++++++------------ .../executable/email/AddEmailCommand.java | 14 ++- .../executable/email/ChangeEmailCommand.java | 12 +-- .../executable/email/RecoverEmailCommand.java | 29 +++---- .../executable/login/LoginCommand.java | 12 ++- .../executable/logout/LogoutCommand.java | 8 +- .../executable/register/RegisterCommand.java | 28 +++--- .../unregister/UnregisterCommand.java | 32 ++----- .../authme/command/help/HelpPrinter.java | 2 +- .../authme/command/help/HelpProvider.java | 13 ++- .../authme/command/help/HelpSyntaxHelper.java | 4 +- .../authme/command/CommandHandlerTest.java | 12 +-- 39 files changed, 249 insertions(+), 517 deletions(-) diff --git a/src/main/java/fr/xephi/authme/command/CommandArgumentDescription.java b/src/main/java/fr/xephi/authme/command/CommandArgumentDescription.java index f846b789..9ae3da4b 100644 --- a/src/main/java/fr/xephi/authme/command/CommandArgumentDescription.java +++ b/src/main/java/fr/xephi/authme/command/CommandArgumentDescription.java @@ -6,9 +6,9 @@ package fr.xephi.authme.command; public class CommandArgumentDescription { /** - * Argument label (one-word description of the argument). + * Argument name (one-word description of the argument). */ - private final String label; + private final String name; /** * Argument description. */ @@ -21,23 +21,23 @@ public class CommandArgumentDescription { /** * Constructor. * - * @param label The argument label. + * @param name The argument name. * @param description The argument description. * @param isOptional True if the argument is optional, false otherwise. */ - public CommandArgumentDescription(String label, String description, boolean isOptional) { - this.label = label; + public CommandArgumentDescription(String name, String description, boolean isOptional) { + this.name = name; this.description = description; this.isOptional = isOptional; } /** - * Get the argument label. + * Get the argument name. * - * @return Argument label. + * @return Argument name. */ - public String getLabel() { - return this.label; + public String getName() { + return this.name; } /** diff --git a/src/main/java/fr/xephi/authme/command/CommandDescription.java b/src/main/java/fr/xephi/authme/command/CommandDescription.java index e2037574..8ea3fac3 100644 --- a/src/main/java/fr/xephi/authme/command/CommandDescription.java +++ b/src/main/java/fr/xephi/authme/command/CommandDescription.java @@ -2,15 +2,10 @@ package fr.xephi.authme.command; import fr.xephi.authme.permission.DefaultPermission; import fr.xephi.authme.permission.PermissionNode; -import fr.xephi.authme.util.CollectionUtils; import fr.xephi.authme.util.StringUtils; -import org.bukkit.command.CommandSender; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; import java.util.List; import static com.google.common.base.Objects.firstNonNull; diff --git a/src/main/java/fr/xephi/authme/command/CommandHandler.java b/src/main/java/fr/xephi/authme/command/CommandHandler.java index 4463d408..61a99188 100644 --- a/src/main/java/fr/xephi/authme/command/CommandHandler.java +++ b/src/main/java/fr/xephi/authme/command/CommandHandler.java @@ -6,7 +6,6 @@ import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.util.CollectionUtils; import fr.xephi.authme.util.StringUtils; import org.bukkit.ChatColor; -import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import java.util.ArrayList; @@ -152,11 +151,11 @@ public class CommandHandler { } // Prefer labels: /register help goes to "Help command", not "Register command" with argument 'help' - List remaining = parts.subList(1, parts.size()); - CommandDescription childCommand = getSuitableChild(base, remaining); + List remainingParts = parts.subList(1, parts.size()); + CommandDescription childCommand = getSuitableChild(base, remainingParts); if (childCommand != null) { return new FoundCommandResult(childCommand, parts.subList(2, parts.size()), parts.subList(0, 2)); - } else if (isSuitableArgumentCount(base, remaining.size())) { + } else if (hasSuitableArgumentCount(base, remainingParts.size())) { return new FoundCommandResult(base, parts.subList(1, parts.size()), parts.subList(0, 1)); } @@ -165,22 +164,17 @@ public class CommandHandler { private FoundCommandResult getCommandWithSmallestDifference(CommandDescription base, List parts) { final String label = parts.get(0); - final int argumentCount = parts.size() - 1; double minDifference = Double.POSITIVE_INFINITY; CommandDescription closestCommand = null; for (CommandDescription child : base.getChildren()) { - double labelDifference = getLabelDifference(child, label); - double argumentDifference = getArgumentCountDifference(child, argumentCount); - // Weigh argument difference less - double difference = labelDifference + argumentDifference / 2; + double difference = getLabelDifference(child, label); if (difference < minDifference) { minDifference = difference; closestCommand = child; } } // TODO: Return the full list of labels and arguments - // TODO: Also compare the base command and suggest it if it's the most similar return new FoundCommandResult( closestCommand, null, null, minDifference, FoundCommandResult.ResultStatus.UNKNOWN_LABEL); } @@ -195,7 +189,16 @@ public class CommandHandler { return null; } - // Is the given command a suitable match for the given parts? parts is for example [changepassword, newpw, newpw] + /** + * Return a child from a base command if the label and the argument count match. + * + * @param baseCommand The base command whose children should be checked + * @param parts The command parts received from the invocation; the first item is the potential label and any + * other items are command arguments. The first initial part that led to the base command should not + * be present. + * + * @return A command if there was a complete match (including proper argument count), null otherwise + */ private CommandDescription getSuitableChild(CommandDescription baseCommand, List parts) { if (CollectionUtils.isEmpty(parts)) { return null; @@ -205,26 +208,20 @@ public class CommandHandler { final int argumentCount = parts.size() - 1; for (CommandDescription child : baseCommand.getChildren()) { - if (child.hasLabel(label) && isSuitableArgumentCount(child, argumentCount)) { + if (child.hasLabel(label) && hasSuitableArgumentCount(child, argumentCount)) { return child; } } return null; } - private static boolean isSuitableArgumentCount(CommandDescription command, int argumentCount) { + private static boolean hasSuitableArgumentCount(CommandDescription command, int argumentCount) { int minArgs = CommandUtils.getMinNumberOfArguments(command); int maxArgs = CommandUtils.getMaxNumberOfArguments(command); return argumentCount >= minArgs && argumentCount <= maxArgs; } - private static int getArgumentCountDifference(CommandDescription commandDescription, int givenArgumentsCount) { - return Math.min( - Math.abs(givenArgumentsCount - CommandUtils.getMinNumberOfArguments(commandDescription)), - Math.abs(givenArgumentsCount - CommandUtils.getMaxNumberOfArguments(commandDescription))); - } - private static double getLabelDifference(CommandDescription command, String givenLabel) { double minDifference = Double.POSITIVE_INFINITY; for (String commandLabel : command.getLabels()) { diff --git a/src/main/java/fr/xephi/authme/command/CommandPermissions.java b/src/main/java/fr/xephi/authme/command/CommandPermissions.java index 2c52f85a..0082b858 100644 --- a/src/main/java/fr/xephi/authme/command/CommandPermissions.java +++ b/src/main/java/fr/xephi/authme/command/CommandPermissions.java @@ -1,11 +1,7 @@ package fr.xephi.authme.command; -import fr.xephi.authme.AuthMe; import fr.xephi.authme.permission.DefaultPermission; -import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.permission.PermissionNode; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; import java.util.List; @@ -42,38 +38,6 @@ public class CommandPermissions { return this.permissionNodes; } - /** - * Check whether this command requires any permission to be executed. This is based on the getPermission() method. - * - * @param sender CommandSender - * - * @return True if this command requires any permission to be executed by a player. - */ - public boolean hasPermission(CommandSender sender) { - // Make sure any permission node is set - if (permissionNodes.isEmpty()) { - return true; - } - - PermissionsManager permissionsManager = AuthMe.getInstance().getPermissionsManager(); - final boolean defaultPermission = getDefaultPermissionCommandSender(sender); - - // Make sure the command sender is a player, if not use the default - if (!(sender instanceof Player)) { - return defaultPermission; - } - - // Get the player instance - Player player = (Player) sender; - - // Get the permissions manager, and make sure it's instance is valid - - if (permissionsManager == null) - return false; - - // Check whether the player has permission, return the result - return permissionsManager.hasPermission(player, this.permissionNodes, defaultPermission); - } /** * Get the default permission if the permission nodes couldn't be used. @@ -85,24 +49,4 @@ public class CommandPermissions { } - /** - * Get the default permission for a specified command sender. - * - * @param sender The command sender to get the default permission for. - * - * @return True if the command sender has permission by default, false otherwise. - */ - public boolean getDefaultPermissionCommandSender(CommandSender sender) { - switch (getDefaultPermission()) { - case ALLOWED: - return true; - - case OP_ONLY: - return sender.isOp(); - - case NOT_ALLOWED: - default: - return false; - } - } } diff --git a/src/main/java/fr/xephi/authme/command/ExecutableCommand.java b/src/main/java/fr/xephi/authme/command/ExecutableCommand.java index 78db5ecf..cffe25b7 100644 --- a/src/main/java/fr/xephi/authme/command/ExecutableCommand.java +++ b/src/main/java/fr/xephi/authme/command/ExecutableCommand.java @@ -2,19 +2,18 @@ package fr.xephi.authme.command; import org.bukkit.command.CommandSender; +import java.util.List; + /** * Base class for AuthMe commands that can be executed. */ public abstract class ExecutableCommand { /** - * Execute the command. + * Execute the command with the given arguments. * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. + * @param sender The command sender. + * @param arguments The arguments. */ - public abstract boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments); + public abstract void executeCommand(CommandSender sender, List arguments); } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java index 26e5959d..09049005 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java @@ -3,7 +3,6 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AuthMe; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.cache.auth.PlayerAuth; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; @@ -12,21 +11,17 @@ import org.bukkit.command.CommandSender; import java.util.List; -/** - */ public class AccountsCommand extends ExecutableCommand { @Override - public boolean executeCommand(final CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(final CommandSender sender, List arguments) { final AuthMe plugin = AuthMe.getInstance(); final Messages m = plugin.getMessages(); - List arguments = commandArguments.getList(); - // Get the player query String playerQuery = sender.getName(); if (arguments.size() >= 1) - playerQuery = commandArguments.get(0); + playerQuery = arguments.get(0); final String playerQueryFinal = playerQuery; // Command logic @@ -70,7 +65,7 @@ public class AccountsCommand extends ExecutableCommand { sender.sendMessage(message.toString()); } }); - return true; + return; } else { Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() { @Override @@ -108,7 +103,6 @@ public class AccountsCommand extends ExecutableCommand { sender.sendMessage(message.toString()); } }); - return true; } } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/AuthMeCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/AuthMeCommand.java index f00ea916..ec78d908 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/AuthMeCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/AuthMeCommand.java @@ -1,21 +1,20 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; -/** - */ +import java.util.List; + public class AuthMeCommand extends ExecutableCommand { @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Show some version info + // FIXME replace use of commandReference sender.sendMessage(ChatColor.GREEN + "This server is running " + AuthMe.getPluginName() + " v" + AuthMe.getPluginVersion() + " b" + AuthMe.getPluginBuildNumber()+ "! " + ChatColor.RED + "<3"); sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/" + commandReference.get(0) + " help" + ChatColor.YELLOW + " to view help."); sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/" + commandReference.get(0) + " about" + ChatColor.YELLOW + " to view about."); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/ChangePasswordAdminCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/ChangePasswordAdminCommand.java index d9889915..3bd48c6f 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/ChangePasswordAdminCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/ChangePasswordAdminCommand.java @@ -4,16 +4,16 @@ import fr.xephi.authme.AuthMe; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerCache; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; -import fr.xephi.authme.security.PasswordSecurity; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; +import fr.xephi.authme.security.PasswordSecurity; import fr.xephi.authme.settings.Settings; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import java.security.NoSuchAlgorithmException; +import java.util.List; /** * Admin command for changing a player's password. @@ -21,14 +21,13 @@ import java.security.NoSuchAlgorithmException; public class ChangePasswordAdminCommand extends ExecutableCommand { @Override - public boolean executeCommand(final CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(final CommandSender sender, List arguments) { final AuthMe plugin = AuthMe.getInstance(); - // Messages instance final Messages m = plugin.getMessages(); // Get the player and password - String playerName = commandArguments.get(0); - final String playerPass = commandArguments.get(1); + String playerName = arguments.get(0); + final String playerPass = arguments.get(1); // Validate the password String playerPassLowerCase = playerPass.toLowerCase(); @@ -38,20 +37,20 @@ public class ChangePasswordAdminCommand extends ExecutableCommand { || playerPassLowerCase.contains(";") || playerPassLowerCase.contains("null") || !playerPassLowerCase.matches(Settings.getPassRegex)) { m.send(sender, MessageKey.PASSWORD_MATCH_ERROR); - return true; + return; } if (playerPassLowerCase.equalsIgnoreCase(playerName)) { m.send(sender, MessageKey.PASSWORD_IS_USERNAME_ERROR); - return true; + return; } if (playerPassLowerCase.length() < Settings.getPasswordMinLen || playerPassLowerCase.length() > Settings.passwordMaxLength) { m.send(sender, MessageKey.INVALID_PASSWORD_LENGTH); - return true; + return; } if (!Settings.unsafePasswords.isEmpty() && Settings.unsafePasswords.contains(playerPassLowerCase)) { m.send(sender, MessageKey.PASSWORD_UNSAFE_ERROR); - return true; + return; } // Set the password final String playerNameLowerCase = playerName.toLowerCase(); @@ -90,6 +89,5 @@ public class ChangePasswordAdminCommand extends ExecutableCommand { } }); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommand.java index 2399a432..73a56a8a 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/FirstSpawnCommand.java @@ -1,18 +1,17 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.ConsoleLogger; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.settings.Spawn; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -/** - */ +import java.util.List; + public class FirstSpawnCommand extends ExecutableCommand { @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Make sure the command executor is a player try { if (sender instanceof Player) { @@ -26,6 +25,5 @@ public class FirstSpawnCommand extends ExecutableCommand { // TODO ljacqu 20151119: Catching NullPointerException is never a good idea. Find what can cause one instead ConsoleLogger.showError(ex.getMessage()); } - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/ForceLoginCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/ForceLoginCommand.java index 8ba109f9..b4f8dd31 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/ForceLoginCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/ForceLoginCommand.java @@ -1,7 +1,6 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.permission.PlayerPermission; import org.bukkit.Bukkit; @@ -15,34 +14,32 @@ import java.util.List; public class ForceLoginCommand extends ExecutableCommand { @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // AuthMe plugin instance final AuthMe plugin = AuthMe.getInstance(); // Get the player query String playerName = sender.getName(); - List arguments = commandArguments.getList(); - if (arguments.size() >= 1) - playerName = commandArguments.get(0); + if (arguments.size() >= 1) { + playerName = arguments.get(0); + } // Command logic try { - @SuppressWarnings("deprecation") + // TODO ljacqu 20151212: Retrieve player via Utils method instead Player player = Bukkit.getPlayer(playerName); if (player == null || !player.isOnline()) { sender.sendMessage("Player needs to be online!"); - return true; + return; } if (!plugin.getPermissionsManager().hasPermission(player, PlayerPermission.CAN_LOGIN_BE_FORCED)) { sender.sendMessage("You cannot force login for the player " + playerName + "!"); - return true; + return; } plugin.getManagement().performLogin(player, "dontneed", true); sender.sendMessage("Force Login for " + playerName + " performed!"); } catch (Exception e) { sender.sendMessage("An error occurred while trying to get that player!"); } - - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java index 2e1389cd..10ec96d3 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/GetEmailCommand.java @@ -2,7 +2,6 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AuthMe; import fr.xephi.authme.cache.auth.PlayerAuth; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; @@ -10,26 +9,11 @@ import org.bukkit.command.CommandSender; import java.util.List; -/** - */ public class GetEmailCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { - // Get the player name - List arguments = commandArguments.getList(); - String playerName = sender.getName(); - if (arguments.size() >= 1) - playerName = commandArguments.get(0); + public void executeCommand(CommandSender sender, List arguments) { + String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0); // Get the authenticated user AuthMe plugin = AuthMe.getInstance(); @@ -37,11 +21,10 @@ public class GetEmailCommand extends ExecutableCommand { PlayerAuth auth = plugin.database.getAuth(playerName.toLowerCase()); if (auth == null) { m.send(sender, MessageKey.UNKNOWN_USER); - return true; + return; } // Show the email address sender.sendMessage("[AuthMe] " + playerName + "'s email: " + auth.getEmail()); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/GetIpCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/GetIpCommand.java index 3e6e5e6e..a4c0cec5 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/GetIpCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/GetIpCommand.java @@ -1,7 +1,6 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; @@ -9,25 +8,25 @@ import org.bukkit.entity.Player; import java.util.List; -/** - */ public class GetIpCommand extends ExecutableCommand { @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { final AuthMe plugin = AuthMe.getInstance(); - List arguments = commandArguments.getList(); // Get the player query String playerName = (arguments.size() >= 1) ? arguments.get(0) : sender.getName(); + // TODO ljacqu 20151212: Use the Utils function instead Player player = Bukkit.getPlayer(playerName); if (player == null) { - sender.sendMessage("This player is not actually online"); - return true; + sender.sendMessage("The player is not online"); + return; } - sender.sendMessage(player.getName() + "'s actual IP is : " + player.getAddress().getAddress().getHostAddress() + ":" + player.getAddress().getPort()); + + // TODO ljacqu 20151212: Revise the messages (actual IP vs. real IP...?) + sender.sendMessage(player.getName() + "'s actual IP is : " + player.getAddress().getAddress().getHostAddress() + + ":" + player.getAddress().getPort()); sender.sendMessage(player.getName() + "'s real IP is : " + plugin.getIP(player)); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java index 36fa096f..3696187c 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java @@ -2,7 +2,6 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AuthMe; import fr.xephi.authme.cache.auth.PlayerAuth; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; @@ -16,9 +15,8 @@ import java.util.List; public class LastLoginCommand extends ExecutableCommand { @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Get the player - List arguments = commandArguments.getList(); String playerName = (arguments.size() >= 1) ? arguments.get(0) : sender.getName(); // Validate the player @@ -30,11 +28,11 @@ public class LastLoginCommand extends ExecutableCommand { auth = plugin.database.getAuth(playerName.toLowerCase()); } catch (NullPointerException e) { m.send(sender, MessageKey.UNKNOWN_USER); - return true; + return; } if (auth == null) { m.send(sender, MessageKey.USER_NOT_REGISTERED); - return true; + return; } // Get the last login date @@ -45,7 +43,8 @@ public class LastLoginCommand extends ExecutableCommand { final long diff = System.currentTimeMillis() - lastLogin; // Build the message - final String msg = (int) (diff / 86400000) + " days " + (int) (diff / 3600000 % 24) + " hours " + (int) (diff / 60000 % 60) + " mins " + (int) (diff / 1000 % 60) + " secs."; + final String msg = (int) (diff / 86400000) + " days " + (int) (diff / 3600000 % 24) + " hours " + + (int) (diff / 60000 % 60) + " mins " + (int) (diff / 1000 % 60) + " secs."; // Get the player's last IP String lastIP = auth.getIp(); @@ -54,6 +53,5 @@ public class LastLoginCommand extends ExecutableCommand { sender.sendMessage("[AuthMe] " + playerName + " last login : " + date.toString()); sender.sendMessage("[AuthMe] The player " + auth.getNickname() + " is unlogged since " + msg); sender.sendMessage("[AuthMe] Last Player's IP: " + lastIP); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeBannedPlayersCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeBannedPlayersCommand.java index 5ecaad8c..6293ef7a 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeBannedPlayersCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeBannedPlayersCommand.java @@ -1,7 +1,6 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.settings.Settings; import org.bukkit.OfflinePlayer; @@ -10,21 +9,10 @@ import org.bukkit.command.CommandSender; import java.util.ArrayList; import java.util.List; -/** - */ public class PurgeBannedPlayersCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // AuthMe plugin instance final AuthMe plugin = AuthMe.getInstance(); @@ -47,6 +35,5 @@ public class PurgeBannedPlayersCommand extends ExecutableCommand { // Show a status message sender.sendMessage("[AuthMe] Database has been purged correctly"); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeCommand.java index 69dd80d3..696e045d 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeCommand.java @@ -1,7 +1,6 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.settings.Settings; import org.bukkit.ChatColor; @@ -10,40 +9,29 @@ import org.bukkit.command.CommandSender; import java.util.Calendar; import java.util.List; -/** - */ public class PurgeCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // AuthMe plugin instance AuthMe plugin = AuthMe.getInstance(); // Get the days parameter - String daysStr = commandArguments.get(0); + String daysStr = arguments.get(0); // Convert the days string to an integer value, and make sure it's valid int days; try { - days = Integer.valueOf(daysStr); - } catch (Exception ex) { + days = Integer.parseInt(daysStr); + } catch (NumberFormatException ex) { sender.sendMessage(ChatColor.RED + "The value you've entered is invalid!"); - return true; + return; } // Validate the value if (days < 30) { sender.sendMessage(ChatColor.RED + "You can only purge data older than 30 days"); - return true; + return; } // Create a calender instance to determine the date @@ -69,6 +57,5 @@ public class PurgeCommand extends ExecutableCommand { // Show a status message sender.sendMessage(ChatColor.GREEN + "[AuthMe] Database has been purged correctly"); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommand.java index d49b5a2f..844b7897 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/PurgeLastPositionCommand.java @@ -3,7 +3,6 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AuthMe; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.cache.auth.PlayerAuth; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; @@ -12,25 +11,13 @@ import org.bukkit.entity.Player; import java.util.List; -/** - */ public class PurgeLastPositionCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(final CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(final CommandSender sender, List arguments) { final AuthMe plugin = AuthMe.getInstance(); final Messages m = plugin.getMessages(); - List arguments = commandArguments.getList(); String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0); // Get the player @@ -42,7 +29,7 @@ public class PurgeLastPositionCommand extends ExecutableCommand { PlayerAuth auth = plugin.database.getAuth(playerNameLowerCase); if (auth == null) { m.send(sender, MessageKey.UNKNOWN_USER); - return true; + return; } // Set the last position @@ -61,6 +48,5 @@ public class PurgeLastPositionCommand extends ExecutableCommand { if (sender instanceof Player) sender.sendMessage("An error occurred while trying to reset location or player do not exist, please see logs"); } - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java index 1d7302d1..b3ea9a2c 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java @@ -5,9 +5,9 @@ import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; -import fr.xephi.authme.security.PasswordSecurity; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; +import fr.xephi.authme.security.PasswordSecurity; import fr.xephi.authme.settings.Settings; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/ReloadCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/ReloadCommand.java index 1eaf3717..1da59f7d 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/ReloadCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/ReloadCommand.java @@ -1,10 +1,7 @@ package fr.xephi.authme.command.executable.authme; -//import org.bukkit.ChatColor; - import fr.xephi.authme.AuthMe; import fr.xephi.authme.ConsoleLogger; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; @@ -12,21 +9,12 @@ import fr.xephi.authme.settings.Settings; import fr.xephi.authme.util.Profiler; import org.bukkit.command.CommandSender; -/** - */ +import java.util.List; + public class ReloadCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Profile the reload process Profiler p = new Profiler(true); @@ -48,7 +36,6 @@ public class ReloadCommand extends ExecutableCommand { ConsoleLogger.showError("Fatal error occurred! AuthMe instance ABORTED!"); ConsoleLogger.writeStackTrace(e); plugin.stopOrUnload(); - return false; } // Show a status message @@ -57,6 +44,5 @@ public class ReloadCommand extends ExecutableCommand { // AuthMeReloaded reloaded, show a status message // sender.sendMessage(ChatColor.GREEN + "AuthMeReloaded has been reloaded successfully, took " + p.getTimeFormatted() + "!"); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java index 278bf13c..08d8278a 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java @@ -3,28 +3,18 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AuthMe; import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerCache; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; import fr.xephi.authme.settings.Settings; import org.bukkit.command.CommandSender; -/** - */ +import java.util.List; + public class SetEmailCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // AuthMe plugin instance AuthMe plugin = AuthMe.getInstance(); @@ -32,27 +22,27 @@ public class SetEmailCommand extends ExecutableCommand { Messages m = plugin.getMessages(); // Get the player name and email address - String playerName = commandArguments.get(0); - String playerEmail = commandArguments.get(1); + String playerName = arguments.get(0); + String playerEmail = arguments.get(1); // Validate the email address if (!Settings.isEmailCorrect(playerEmail)) { m.send(sender, MessageKey.INVALID_EMAIL); - return true; + return; } // Validate the user PlayerAuth auth = plugin.database.getAuth(playerName.toLowerCase()); if (auth == null) { m.send(sender, MessageKey.UNKNOWN_USER); - return true; + return; } // Set the email address auth.setEmail(playerEmail); if (!plugin.database.updateEmail(auth)) { m.send(sender, MessageKey.ERROR); - return true; + return; } // Update the player cache @@ -61,6 +51,6 @@ public class SetEmailCommand extends ExecutableCommand { // Show a status message m.send(sender, MessageKey.EMAIL_CHANGED_SUCCESS); - return true; + return; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/SetFirstSpawnCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/SetFirstSpawnCommand.java index 279941d7..d1cea3de 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/SetFirstSpawnCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/SetFirstSpawnCommand.java @@ -1,27 +1,17 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.ConsoleLogger; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.settings.Spawn; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -/** - */ +import java.util.List; + public class SetFirstSpawnCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { try { if (sender instanceof Player) { if (Spawn.getInstance().setFirstSpawn(((Player) sender).getLocation())) @@ -33,6 +23,5 @@ public class SetFirstSpawnCommand extends ExecutableCommand { } catch (NullPointerException ex) { ConsoleLogger.showError(ex.getMessage()); } - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/SetSpawnCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/SetSpawnCommand.java index 35576356..63029db0 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/SetSpawnCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/SetSpawnCommand.java @@ -1,27 +1,17 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.ConsoleLogger; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.settings.Spawn; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -/** - */ +import java.util.List; + public class SetSpawnCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Make sure the command executor is a player try { if (sender instanceof Player) { @@ -36,6 +26,5 @@ public class SetSpawnCommand extends ExecutableCommand { } catch (NullPointerException ex) { ConsoleLogger.showError(ex.getMessage()); } - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/SpawnCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/SpawnCommand.java index 67854f87..93272658 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/SpawnCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/SpawnCommand.java @@ -1,27 +1,17 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.ConsoleLogger; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.settings.Spawn; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -/** - */ +import java.util.List; + public class SpawnCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Make sure the command executor is a player try { if (sender instanceof Player) { @@ -29,11 +19,10 @@ public class SpawnCommand extends ExecutableCommand { ((Player) sender).teleport(Spawn.getInstance().getSpawn()); else sender.sendMessage("[AuthMe] Spawn has failed, please try to define the spawn"); } else { - sender.sendMessage("[AuthMe] Please use that command in game"); + sender.sendMessage("[AuthMe] Please use the command in game"); } } catch (NullPointerException ex) { ConsoleLogger.showError(ex.getMessage()); } - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommand.java index 38123681..4f541a9e 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommand.java @@ -1,7 +1,6 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AntiBot; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.CommandUtils; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.command.help.HelpProvider; @@ -11,56 +10,44 @@ import org.bukkit.command.CommandSender; import java.util.List; -/** - */ public class SwitchAntiBotCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(final CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(final CommandSender sender, List arguments) { // Get the new state String newState = null; - List arguments = commandArguments.getList(); if (arguments.size() == 1) { - newState = commandArguments.get(0); + newState = arguments.get(0); } else if (arguments.size() == 0) { sender.sendMessage("[AuthMe] AntiBot status: " + AntiBot.getAntiBotStatus().name()); - return true; + return; } // Enable the mod if ("ON".equalsIgnoreCase(newState)) { AntiBot.overrideAntiBotStatus(true); sender.sendMessage("[AuthMe] AntiBot Manual Override: enabled!"); - return true; + return; } // Disable the mod if ("OFF".equalsIgnoreCase(newState)) { AntiBot.overrideAntiBotStatus(false); sender.sendMessage("[AuthMe] AntiBotMod Manual Override: disabled!"); - return true; + return; } // Show the invalid arguments warning sender.sendMessage(ChatColor.DARK_RED + "Invalid AntiBot mode!"); // Show the command argument help + // FIXME fix help reference HelpProvider.showHelp(sender, commandReference, commandReference, true, false, true, false, false, false); // Show the command to use for detailed help List helpCommandReference = CollectionUtils.getRange(commandReference.getList(), 1); sender.sendMessage(ChatColor.GOLD + "Detailed help: " + ChatColor.WHITE + "/" + commandReference.get(0) + " help " + CommandUtils.labelsToString(helpCommandReference)); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/UnregisterAdminCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/UnregisterAdminCommand.java index 8d2b1e11..0ef44a58 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/UnregisterAdminCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/UnregisterAdminCommand.java @@ -4,7 +4,6 @@ import fr.xephi.authme.AuthMe; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.cache.limbo.LimboCache; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; @@ -20,22 +19,16 @@ import org.bukkit.potion.PotionEffectType; import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.scheduler.BukkitTask; +import java.util.List; + /** * Admin command to unregister a player. */ public class UnregisterAdminCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ + @Override - public boolean executeCommand(final CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(final CommandSender sender, List arguments) { // AuthMe plugin instance final AuthMe plugin = AuthMe.getInstance(); @@ -43,19 +36,19 @@ public class UnregisterAdminCommand extends ExecutableCommand { final Messages m = plugin.getMessages(); // Get the player name - String playerName = commandArguments.get(0); + String playerName = arguments.get(0); String playerNameLowerCase = playerName.toLowerCase(); // Make sure the user is valid if (!plugin.database.isAuthAvailable(playerNameLowerCase)) { m.send(sender, MessageKey.UNKNOWN_USER); - return true; + return; } // Remove the player if (!plugin.database.removeAuth(playerNameLowerCase)) { m.send(sender, MessageKey.ERROR); - return true; + return; } // Unregister the player @@ -88,6 +81,5 @@ public class UnregisterAdminCommand extends ExecutableCommand { // Show a status message m.send(sender, MessageKey.UNREGISTERED_SUCCESS); ConsoleLogger.info(playerName + " unregistered"); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/VersionCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/VersionCommand.java index fc92ac8f..9e728f20 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/VersionCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/VersionCommand.java @@ -1,30 +1,19 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.settings.Settings; - import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -/** - */ +import java.util.List; + public class VersionCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Show some version info sender.sendMessage(ChatColor.GOLD + "==========[ " + Settings.helpHeader.toUpperCase() + " ABOUT ]=========="); sender.sendMessage(ChatColor.GOLD + "Version: " + ChatColor.WHITE + AuthMe.getPluginName() + " v" + AuthMe.getPluginVersion() + ChatColor.GRAY + " (build: " + AuthMe.getPluginBuildNumber() + ")"); @@ -37,7 +26,6 @@ public class VersionCommand extends ExecutableCommand { sender.sendMessage(ChatColor.GOLD + "Website: " + ChatColor.WHITE + "http://dev.bukkit.org/bukkit-plugins/authme-reloaded/"); sender.sendMessage(ChatColor.GOLD + "License: " + ChatColor.WHITE + "GNU GPL v3.0" + ChatColor.GRAY + ChatColor.ITALIC + " (See LICENSE file)"); sender.sendMessage(ChatColor.GOLD + "Copyright: " + ChatColor.WHITE + "Copyright (c) Xephi 2015. All rights reserved."); - return true; } /** diff --git a/src/main/java/fr/xephi/authme/command/executable/captcha/CaptchaCommand.java b/src/main/java/fr/xephi/authme/command/executable/captcha/CaptchaCommand.java index 69677353..cca74066 100644 --- a/src/main/java/fr/xephi/authme/command/executable/captcha/CaptchaCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/captcha/CaptchaCommand.java @@ -2,25 +2,24 @@ package fr.xephi.authme.command.executable.captcha; import fr.xephi.authme.AuthMe; import fr.xephi.authme.cache.auth.PlayerCache; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; -import fr.xephi.authme.security.RandomString; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; +import fr.xephi.authme.security.RandomString; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.util.Wrapper; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -/** - */ +import java.util.List; + public class CaptchaCommand extends ExecutableCommand { @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Make sure the current command executor is a player if (!(sender instanceof Player)) { - return true; + return; } // Get the player instance and name @@ -28,7 +27,7 @@ public class CaptchaCommand extends ExecutableCommand { final String playerNameLowerCase = player.getName().toLowerCase(); // Get the parameter values - String captcha = commandArguments.get(0); + String captcha = arguments.get(0); // AuthMe plugin instance final Wrapper wrapper = Wrapper.getInstance(); @@ -40,18 +39,18 @@ public class CaptchaCommand extends ExecutableCommand { // Command logic if (PlayerCache.getInstance().isAuthenticated(playerNameLowerCase)) { m.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR); - return true; + return; } if (!Settings.useCaptcha) { m.send(player, MessageKey.USAGE_LOGIN); - return true; + return; } if (!plugin.cap.containsKey(playerNameLowerCase)) { m.send(player, MessageKey.USAGE_LOGIN); - return true; + return; } if (Settings.useCaptcha && !captcha.equals(plugin.cap.get(playerNameLowerCase))) { @@ -61,7 +60,7 @@ public class CaptchaCommand extends ExecutableCommand { for (String s : m.retrieve(MessageKey.CAPTCHA_WRONG_ERROR)) { player.sendMessage(s.replace("THE_CAPTCHA", plugin.cap.get(playerNameLowerCase))); } - return true; + return; } plugin.captcha.remove(playerNameLowerCase); @@ -70,6 +69,5 @@ public class CaptchaCommand extends ExecutableCommand { // Show a status message m.send(player, MessageKey.CAPTCHA_SUCCESS); m.send(player, MessageKey.LOGIN_MESSAGE); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommand.java b/src/main/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommand.java index f9219aba..67fd1180 100644 --- a/src/main/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommand.java @@ -2,7 +2,6 @@ package fr.xephi.authme.command.executable.changepassword; import fr.xephi.authme.AuthMe; import fr.xephi.authme.cache.auth.PlayerCache; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; @@ -12,24 +11,26 @@ import fr.xephi.authme.util.Wrapper; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import java.util.List; + /** * The command for a player to change his password with. */ public class ChangePasswordCommand extends ExecutableCommand { @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Make sure the current command executor is a player if (!(sender instanceof Player)) { - return true; + return; } final Wrapper wrapper = Wrapper.getInstance(); final Messages m = wrapper.getMessages(); // Get the passwords - String oldPassword = commandArguments.get(0); - String newPassword = commandArguments.get(1); + String oldPassword = arguments.get(0); + String newPassword = arguments.get(1); // Get the player instance and make sure he's authenticated Player player = (Player) sender; @@ -37,7 +38,7 @@ public class ChangePasswordCommand extends ExecutableCommand { final PlayerCache playerCache = wrapper.getPlayerCache(); if (!playerCache.isAuthenticated(name)) { m.send(player, MessageKey.NOT_LOGGED_IN); - return true; + return; } // Make sure the password is allowed @@ -48,26 +49,25 @@ public class ChangePasswordCommand extends ExecutableCommand { || playerPassLowerCase.contains(";") || playerPassLowerCase.contains("null") || !playerPassLowerCase.matches(Settings.getPassRegex)) { m.send(player, MessageKey.PASSWORD_MATCH_ERROR); - return true; + return; } if (playerPassLowerCase.equalsIgnoreCase(name)) { m.send(player, MessageKey.PASSWORD_IS_USERNAME_ERROR); - return true; + return; } if (playerPassLowerCase.length() < Settings.getPasswordMinLen || playerPassLowerCase.length() > Settings.passwordMaxLength) { m.send(player, MessageKey.INVALID_PASSWORD_LENGTH); - return true; + return; } if (!Settings.unsafePasswords.isEmpty() && Settings.unsafePasswords.contains(playerPassLowerCase)) { m.send(player, MessageKey.PASSWORD_UNSAFE_ERROR); - return true; + return; } // Set the password final AuthMe plugin = wrapper.getAuthMe(); wrapper.getScheduler().runTaskAsynchronously(plugin, new ChangePasswordTask(plugin, player, oldPassword, newPassword)); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/converter/ConverterCommand.java b/src/main/java/fr/xephi/authme/command/executable/converter/ConverterCommand.java index 88314997..b877e301 100644 --- a/src/main/java/fr/xephi/authme/command/executable/converter/ConverterCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/converter/ConverterCommand.java @@ -1,29 +1,27 @@ package fr.xephi.authme.command.executable.converter; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; -import fr.xephi.authme.converter.*; +import fr.xephi.authme.converter.Converter; +import fr.xephi.authme.converter.CrazyLoginConverter; +import fr.xephi.authme.converter.FlatToSql; +import fr.xephi.authme.converter.FlatToSqlite; +import fr.xephi.authme.converter.RakamakConverter; +import fr.xephi.authme.converter.RoyalAuthConverter; +import fr.xephi.authme.converter.SqlToFlat; +import fr.xephi.authme.converter.vAuthConverter; +import fr.xephi.authme.converter.xAuthConverter; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; -/** - */ +import java.util.List; + public class ConverterCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // AuthMe plugin instance final AuthMe plugin = AuthMe.getInstance(); @@ -31,40 +29,40 @@ public class ConverterCommand extends ExecutableCommand { final Messages m = plugin.getMessages(); // Get the conversion job - String job = commandArguments.get(0); + String job = arguments.get(0); // Determine the job type ConvertType jobType = ConvertType.fromName(job); if (jobType == null) { m.send(sender, MessageKey.ERROR); - return true; + return; } // Get the proper converter instance Converter converter = null; switch (jobType) { - case ftsql: + case FTSQL: converter = new FlatToSql(); break; - case ftsqlite: + case FTSQLITE: converter = new FlatToSqlite(sender); break; - case xauth: + case XAUTH: converter = new xAuthConverter(plugin, sender); break; - case crazylogin: + case CRAZYLOGIN: converter = new CrazyLoginConverter(plugin, sender); break; - case rakamak: + case RAKAMAK: converter = new RakamakConverter(plugin, sender); break; - case royalauth: + case ROYALAUTH: converter = new RoyalAuthConverter(plugin); break; - case vauth: + case VAUTH: converter = new vAuthConverter(plugin, sender); break; - case sqltoflat: + case SQLTOFLAT: converter = new SqlToFlat(plugin, sender); break; default: @@ -76,52 +74,33 @@ public class ConverterCommand extends ExecutableCommand { // Show a status message sender.sendMessage("[AuthMe] Successfully converted from " + jobType.getName()); - return true; } - /** - */ public enum ConvertType { - ftsql("flattosql"), - ftsqlite("flattosqlite"), - xauth("xauth"), - crazylogin("crazylogin"), - rakamak("rakamak"), - royalauth("royalauth"), - vauth("vauth"), - sqltoflat("sqltoflat"); + FTSQL("flattosql"), + FTSQLITE("flattosqlite"), + XAUTH("xauth"), + CRAZYLOGIN("crazylogin"), + RAKAMAK("rakamak"), + ROYALAUTH("royalauth"), + VAUTH("vauth"), + SQLTOFLAT("sqltoflat"); final String name; - /** - * Constructor for ConvertType. - * - * @param name String - */ ConvertType(String name) { this.name = name; } - /** - * Method fromName. - * - * @param name String - * - * @return ConvertType - */ public static ConvertType fromName(String name) { for (ConvertType type : ConvertType.values()) { - if (type.getName().equalsIgnoreCase(name)) + if (type.getName().equalsIgnoreCase(name)) { return type; + } } return null; } - /** - * Method getName. - * - * @return String - */ String getName() { return this.name; } diff --git a/src/main/java/fr/xephi/authme/command/executable/email/AddEmailCommand.java b/src/main/java/fr/xephi/authme/command/executable/email/AddEmailCommand.java index 6e724db1..b94e3f28 100644 --- a/src/main/java/fr/xephi/authme/command/executable/email/AddEmailCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/email/AddEmailCommand.java @@ -1,31 +1,29 @@ package fr.xephi.authme.command.executable.email; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.util.Wrapper; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -/** - */ +import java.util.List; + public class AddEmailCommand extends ExecutableCommand { @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Make sure the current command executor is a player if (!(sender instanceof Player)) { - return true; + return; } // Get the parameter values - String playerMail = commandArguments.get(0); - String playerMailVerify = commandArguments.get(1); + String playerMail = arguments.get(0); + String playerMailVerify = arguments.get(1); // Get the player and perform email addition final AuthMe plugin = Wrapper.getInstance().getAuthMe(); final Player player = (Player) sender; plugin.getManagement().performAddEmail(player, playerMail, playerMailVerify); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/email/ChangeEmailCommand.java b/src/main/java/fr/xephi/authme/command/executable/email/ChangeEmailCommand.java index f78910e7..31dc9046 100644 --- a/src/main/java/fr/xephi/authme/command/executable/email/ChangeEmailCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/email/ChangeEmailCommand.java @@ -1,31 +1,31 @@ package fr.xephi.authme.command.executable.email; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.util.Wrapper; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import java.util.List; + /** */ public class ChangeEmailCommand extends ExecutableCommand { @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Make sure the current command executor is a player if (!(sender instanceof Player)) { - return true; + return; } // Get the parameter values - String playerMailOld = commandArguments.get(0); - String playerMailNew = commandArguments.get(1); + String playerMailOld = arguments.get(0); + String playerMailNew = arguments.get(1); // Get the player instance and execute action final AuthMe plugin = Wrapper.getInstance().getAuthMe(); final Player player = (Player) sender; plugin.getManagement().performChangeEmail(player, playerMailOld, playerMailNew); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/email/RecoverEmailCommand.java b/src/main/java/fr/xephi/authme/command/executable/email/RecoverEmailCommand.java index 2af4f65a..09815c42 100644 --- a/src/main/java/fr/xephi/authme/command/executable/email/RecoverEmailCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/email/RecoverEmailCommand.java @@ -4,32 +4,30 @@ import fr.xephi.authme.AuthMe; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerCache; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; -import fr.xephi.authme.security.PasswordSecurity; -import fr.xephi.authme.security.RandomString; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; +import fr.xephi.authme.security.PasswordSecurity; +import fr.xephi.authme.security.RandomString; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.util.Wrapper; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import java.security.NoSuchAlgorithmException; +import java.util.List; -/** - */ public class RecoverEmailCommand extends ExecutableCommand { @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Make sure the current command executor is a player if (!(sender instanceof Player)) { - return true; + return; } // Get the parameter values - String playerMail = commandArguments.get(0); + String playerMail = arguments.get(0); // Get the player instance and name final Player player = (Player) sender; @@ -42,12 +40,12 @@ public class RecoverEmailCommand extends ExecutableCommand { if (plugin.mail == null) { m.send(player, MessageKey.ERROR); - return true; + return; } if (plugin.database.isAuthAvailable(playerName)) { if (PlayerCache.getInstance().isAuthenticated(playerName)) { m.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR); - return true; + return; } try { RandomString rand = new RandomString(Settings.getRecoveryPassLength); @@ -60,16 +58,17 @@ public class RecoverEmailCommand extends ExecutableCommand { auth = plugin.database.getAuth(playerName); } else { m.send(player, MessageKey.UNKNOWN_USER); - return true; + return; } if (Settings.getmailAccount.equals("") || Settings.getmailAccount.isEmpty()) { m.send(player, MessageKey.ERROR); - return true; + return; } - if (!playerMail.equalsIgnoreCase(auth.getEmail()) || playerMail.equalsIgnoreCase("your@email.com") || auth.getEmail().equalsIgnoreCase("your@email.com")) { + if (!playerMail.equalsIgnoreCase(auth.getEmail()) || playerMail.equalsIgnoreCase("your@email.com") + || auth.getEmail().equalsIgnoreCase("your@email.com")) { m.send(player, MessageKey.INVALID_EMAIL); - return true; + return; } auth.setHash(hashNew); plugin.database.updatePassword(auth); @@ -83,7 +82,5 @@ public class RecoverEmailCommand extends ExecutableCommand { } else { m.send(player, MessageKey.REGISTER_EMAIL_MESSAGE); } - - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/login/LoginCommand.java b/src/main/java/fr/xephi/authme/command/executable/login/LoginCommand.java index b57b0bdc..21e8dc79 100644 --- a/src/main/java/fr/xephi/authme/command/executable/login/LoginCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/login/LoginCommand.java @@ -1,30 +1,28 @@ package fr.xephi.authme.command.executable.login; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.util.Wrapper; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -/** - */ +import java.util.List; + public class LoginCommand extends ExecutableCommand { @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Make sure the current command executor is a player if (!(sender instanceof Player)) { - return true; + return; } // Get the necessary objects final AuthMe plugin = Wrapper.getInstance().getAuthMe(); final Player player = (Player) sender; - final String password = commandArguments.get(0); + final String password = arguments.get(0); // Log the player in plugin.getManagement().performLogin(player, password, false); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/logout/LogoutCommand.java b/src/main/java/fr/xephi/authme/command/executable/logout/LogoutCommand.java index e1918d07..5adba4dc 100644 --- a/src/main/java/fr/xephi/authme/command/executable/logout/LogoutCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/logout/LogoutCommand.java @@ -1,21 +1,22 @@ package fr.xephi.authme.command.executable.logout; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.util.Wrapper; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import java.util.List; + /** */ public class LogoutCommand extends ExecutableCommand { @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Make sure the current command executor is a player if (!(sender instanceof Player)) { - return true; + return; } // Get the player instance @@ -24,6 +25,5 @@ public class LogoutCommand extends ExecutableCommand { // Logout the player plugin.getManagement().performLogout(player); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/register/RegisterCommand.java b/src/main/java/fr/xephi/authme/command/executable/register/RegisterCommand.java index b240bf04..0aa3e31b 100644 --- a/src/main/java/fr/xephi/authme/command/executable/register/RegisterCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/register/RegisterCommand.java @@ -1,12 +1,11 @@ package fr.xephi.authme.command.executable.register; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; -import fr.xephi.authme.process.Management; -import fr.xephi.authme.security.RandomString; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; +import fr.xephi.authme.process.Management; +import fr.xephi.authme.security.RandomString; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.util.Wrapper; import org.bukkit.command.CommandSender; @@ -14,20 +13,16 @@ import org.bukkit.entity.Player; import java.util.List; -/** - */ public class RegisterCommand extends ExecutableCommand { @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(CommandSender sender, List arguments) { // Make sure the sender is a player if (!(sender instanceof Player)) { sender.sendMessage("Player Only! Use 'authme register ' instead"); - return true; + return; } - List arguments = commandArguments.getList(); - final Wrapper wrapper = Wrapper.getInstance(); final AuthMe plugin = wrapper.getAuthMe(); final Messages m = wrapper.getMessages(); @@ -36,31 +31,30 @@ public class RegisterCommand extends ExecutableCommand { final Player player = (Player) sender; if (arguments.isEmpty() || (Settings.getEnablePasswordVerifier && arguments.size() < 2)) { m.send(player, MessageKey.USAGE_REGISTER); - return true; + return; } final Management management = plugin.getManagement(); if (Settings.emailRegistration && !Settings.getmailAccount.isEmpty()) { if (Settings.doubleEmailCheck && arguments.size() < 2 || !arguments.get(0).equals(arguments.get(1))) { m.send(player, MessageKey.USAGE_REGISTER); - return true; + return; } final String email = arguments.get(0); if (!Settings.isEmailCorrect(email)) { m.send(player, MessageKey.INVALID_EMAIL); - return true; + return; } final String thePass = new RandomString(Settings.getRecoveryPassLength).nextString(); management.performRegister(player, thePass, email); - return true; + return; } if (arguments.size() > 1 && Settings.getEnablePasswordVerifier) { - if (!arguments.get(0).equals(commandArguments.get(1))) { + if (!arguments.get(0).equals(arguments.get(1))) { m.send(player, MessageKey.PASSWORD_MATCH_ERROR); - return true; + return; } } - management.performRegister(player, commandArguments.get(0), ""); - return true; + management.performRegister(player, arguments.get(0), ""); } } diff --git a/src/main/java/fr/xephi/authme/command/executable/unregister/UnregisterCommand.java b/src/main/java/fr/xephi/authme/command/executable/unregister/UnregisterCommand.java index 8ff40ed3..472d4743 100644 --- a/src/main/java/fr/xephi/authme/command/executable/unregister/UnregisterCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/unregister/UnregisterCommand.java @@ -2,41 +2,28 @@ package fr.xephi.authme.command.executable.unregister; import fr.xephi.authme.AuthMe; import fr.xephi.authme.cache.auth.PlayerCache; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -/** - */ +import java.util.List; + public class UnregisterCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { - // AuthMe plugin instance - final AuthMe plugin = AuthMe.getInstance(); - - // Messages instance - final Messages m = plugin.getMessages(); - + public void executeCommand(CommandSender sender, List arguments) { // Make sure the current command executor is a player if (!(sender instanceof Player)) { - return true; + return; } + final AuthMe plugin = AuthMe.getInstance(); + final Messages m = plugin.getMessages(); + // Get the password - String playerPass = commandArguments.get(0); + String playerPass = arguments.get(0); // Get the player instance and name final Player player = (Player) sender; @@ -45,11 +32,10 @@ public class UnregisterCommand extends ExecutableCommand { // Make sure the player is authenticated if (!PlayerCache.getInstance().isAuthenticated(playerNameLowerCase)) { m.send(player, MessageKey.NOT_LOGGED_IN); - return true; + return; } // Unregister the player plugin.getManagement().performUnregister(player, playerPass, false); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/help/HelpPrinter.java b/src/main/java/fr/xephi/authme/command/help/HelpPrinter.java index 56ad48d8..ae39ac5b 100644 --- a/src/main/java/fr/xephi/authme/command/help/HelpPrinter.java +++ b/src/main/java/fr/xephi/authme/command/help/HelpPrinter.java @@ -69,7 +69,7 @@ public class HelpPrinter { for (CommandArgumentDescription arg : command.getArguments()) { // Create a string builder to build the syntax in StringBuilder argString = new StringBuilder(); - argString.append(" " + ChatColor.YELLOW + ChatColor.ITALIC + arg.getLabel() + " : " + ChatColor.WHITE + arg.getDescription()); + argString.append(" " + ChatColor.YELLOW + ChatColor.ITALIC + arg.getName() + " : " + ChatColor.WHITE + arg.getDescription()); // Suffix a note if the command is optional if (arg.isOptional()) diff --git a/src/main/java/fr/xephi/authme/command/help/HelpProvider.java b/src/main/java/fr/xephi/authme/command/help/HelpProvider.java index 7f088acf..44afbefa 100644 --- a/src/main/java/fr/xephi/authme/command/help/HelpProvider.java +++ b/src/main/java/fr/xephi/authme/command/help/HelpProvider.java @@ -29,6 +29,13 @@ public class HelpProvider { showHelp(sender, reference, helpQuery, true, true, true, true, true, true); } + public static void showHelp(CommandSender sender, CommandParts reference, CommandParts helpQuery, + boolean showCommand, boolean showDescription, boolean showArguments, + boolean showPermissions, boolean showAlternatives, boolean showCommands) { + showHelp(sender, reference.getList(), helpQuery.getList(), showCommand, showDescription, showArguments, + showPermissions, showAlternatives, showCommands); + } + /** * Show help for a specific command. * @@ -42,7 +49,9 @@ public class HelpProvider { * @param showAlternatives True to show the command alternatives. * @param showCommands True to show the child commands. */ - public static void showHelp(CommandSender sender, CommandParts reference, CommandParts helpQuery, boolean showCommand, boolean showDescription, boolean showArguments, boolean showPermissions, boolean showAlternatives, boolean showCommands) { + public static void showHelp(CommandSender sender, List reference, List helpQuery, + boolean showCommand, boolean showDescription, boolean showArguments, + boolean showPermissions, boolean showAlternatives, boolean showCommands) { // Find the command for this help query, one with and one without a prefixed base command FoundCommandResult result = AuthMe.getInstance().getCommandHandler().findCommand(new CommandParts(helpQuery.getList())); @@ -77,7 +86,7 @@ public class HelpProvider { } // Get the proper command reference to use for the help page - CommandParts commandReference = command.getCommandReference(result.getQueryReference()); + CommandParts commandReference = command.getCommandReference(result.getLabels()); // Get the base command String baseCommand = commandReference.get(0); diff --git a/src/main/java/fr/xephi/authme/command/help/HelpSyntaxHelper.java b/src/main/java/fr/xephi/authme/command/help/HelpSyntaxHelper.java index d2f5f545..6d1b1d7d 100644 --- a/src/main/java/fr/xephi/authme/command/help/HelpSyntaxHelper.java +++ b/src/main/java/fr/xephi/authme/command/help/HelpSyntaxHelper.java @@ -73,8 +73,8 @@ public final class HelpSyntaxHelper { private static String formatArgument(CommandArgumentDescription argument) { if (argument.isOptional()) { - return " [" + argument.getLabel() + "]"; + return " [" + argument.getName() + "]"; } - return " <" + argument.getLabel() + ">"; + return " <" + argument.getName() + ">"; } } diff --git a/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java b/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java index 02e65f50..e64ad84d 100644 --- a/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java +++ b/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java @@ -1,6 +1,7 @@ package fr.xephi.authme.command; import fr.xephi.authme.permission.DefaultPermission; +import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.permission.PlayerPermission; import fr.xephi.authme.util.WrapperMock; import org.bukkit.command.CommandSender; @@ -21,7 +22,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.stringContainsInOrder; import static org.mockito.BDDMockito.given; -import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyListOf; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; @@ -35,6 +36,7 @@ public class CommandHandlerTest { private static Set commands; private static CommandHandler handler; + private static PermissionsManager permissionsManagerMock; @BeforeClass public static void setUpCommandHandler() { @@ -47,7 +49,8 @@ public class CommandHandlerTest { CommandDescription testBase = createCommand(null, null, singletonList("test"), newArgument("test", true)); commands = new HashSet<>(asList(authMeBase, testBase)); - handler = new CommandHandler(commands); + permissionsManagerMock = mock(PermissionsManager.class); + handler = new CommandHandler(commands, permissionsManagerMock); } @Test @@ -65,8 +68,7 @@ public class CommandHandlerTest { // then final CommandDescription loginCmd = getChildWithLabel("login", getCommandWithLabel("authme", commands)); verify(sender, never()).sendMessage(anyString()); - verify(loginCmd.getExecutableCommand()).executeCommand( - eq(sender), any(CommandParts.class), any(CommandParts.class)); + verify(loginCmd.getExecutableCommand()).executeCommand(eq(sender), anyListOf(String.class)); } @Test @@ -98,7 +100,7 @@ public class CommandHandlerTest { if (arguments != null && arguments.length > 0) { for (CommandArgumentDescription argument : arguments) { - command.withArgument(argument.getLabel(), "Test description", argument.isOptional()); + command.withArgument(argument.getName(), "Test description", argument.isOptional()); } } From d5b2058124413a76918d67fc0b1374289e91427e Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sat, 12 Dec 2015 12:48:39 +0100 Subject: [PATCH 07/18] =?UTF-8?q?Change=20ExecutableCommand=20interface=20?= =?UTF-8?q?(wip=20=E2=80=93=20doesn't=20compile)=20-=20Change=20interface?= =?UTF-8?q?=20to=20use=20(CommandSender,=20List=20arguments)=20-?= =?UTF-8?q?=20Use=20CommandArgumentDescription#name=20instead=20of=20"labe?= =?UTF-8?q?l"=20(to=20prevent=20confusion=20between=20command=20labels=20a?= =?UTF-8?q?nd=20arguments)=20-=20Simplify=20command=20difference=20computa?= =?UTF-8?q?tion=20in=20CommandHandler=20(no=20longer=20consider=20argument?= =?UTF-8?q?=20difference)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../authme/command/CommandInitializer.java | 6 +- .../fr/xephi/authme/command/CommandParts.java | 70 ------------------- .../command/executable/HelpCommand.java | 1 - .../executable/authme/AuthMeCommand.java | 14 ++-- .../authme/RegisterAdminCommand.java | 26 +++---- .../executable/authme/ResetNameCommand.java | 44 ------------ .../authme/command/help/HelpPrinter.java | 1 - .../authme/command/help/HelpProvider.java | 1 - .../authme/command/help/HelpSyntaxHelper.java | 1 - .../captcha/CaptchaCommandTest.java | 1 - .../ChangePasswordCommandTest.java | 1 - .../executable/email/AddEmailCommandTest.java | 1 - .../email/ChangeEmailCommandTest.java | 1 - .../email/RecoverEmailCommandTest.java | 1 - .../executable/login/LoginCommandTest.java | 1 - .../executable/logout/LogoutCommandTest.java | 1 - .../register/RegisterCommandTest.java | 1 - .../command/help/HelpSyntaxHelperTest.java | 1 - 18 files changed, 21 insertions(+), 152 deletions(-) delete mode 100644 src/main/java/fr/xephi/authme/command/CommandParts.java delete mode 100644 src/main/java/fr/xephi/authme/command/executable/authme/ResetNameCommand.java diff --git a/src/main/java/fr/xephi/authme/command/CommandInitializer.java b/src/main/java/fr/xephi/authme/command/CommandInitializer.java index 9381499c..b3db5c1c 100644 --- a/src/main/java/fr/xephi/authme/command/CommandInitializer.java +++ b/src/main/java/fr/xephi/authme/command/CommandInitializer.java @@ -1,5 +1,6 @@ package fr.xephi.authme.command; +import com.google.common.collect.ImmutableSet; import fr.xephi.authme.command.executable.HelpCommand; import fr.xephi.authme.command.executable.authme.AccountsCommand; import fr.xephi.authme.command.executable.authme.AuthMeCommand; @@ -37,6 +38,7 @@ import fr.xephi.authme.util.Wrapper; import java.util.*; +import static com.google.common.collect.Sets.newHashSet; import static fr.xephi.authme.permission.DefaultPermission.ALLOWED; import static fr.xephi.authme.permission.DefaultPermission.OP_ONLY; @@ -495,7 +497,7 @@ public final class CommandInitializer { .build(); // Add the base commands to the commands array - baseCommands = new HashSet<>(Arrays.asList( + baseCommands = ImmutableSet.of( AUTHME_BASE, LOGIN_BASE, LOGOUT_BASE, @@ -504,6 +506,6 @@ public final class CommandInitializer { CHANGE_PASSWORD_BASE, EMAIL_BASE, CAPTCHA_BASE, - CONVERTER_BASE)); + CONVERTER_BASE); } } diff --git a/src/main/java/fr/xephi/authme/command/CommandParts.java b/src/main/java/fr/xephi/authme/command/CommandParts.java deleted file mode 100644 index b34df6b1..00000000 --- a/src/main/java/fr/xephi/authme/command/CommandParts.java +++ /dev/null @@ -1,70 +0,0 @@ -package fr.xephi.authme.command; - -import fr.xephi.authme.util.StringUtils; - -import java.util.ArrayList; -import java.util.List; - -/** - */ -public class CommandParts { - - /** - * The list of parts for this command. - */ - private final List parts = new ArrayList<>(); - - /** - * Constructor. - * - * @param part The part to add. - */ - public CommandParts(String part) { - this.parts.add(part); - } - - /** - * Constructor. - * - * @param parts The list of parts. - */ - public CommandParts(List parts) { - this.parts.addAll(parts); - } - - /** - * Get the command parts. - * - * @return Command parts. - */ - public List getList() { - return this.parts; - } - - /** - * Get a part by its index. - * - * @param i Part index. - * - * @return The part. - */ - public String get(int i) { - // Make sure the index is in-bound - if (i < 0 || i >= parts.size()) { - return null; - } - - // Get and return the argument - return this.parts.get(i); - } - - /** - * Convert the parts to a string. - * - * @return The part as a string. - */ - @Override - public String toString() { - return StringUtils.join(" ", this.parts); - } -} diff --git a/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java b/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java index d8982fa9..ff7a9130 100644 --- a/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java @@ -1,6 +1,5 @@ package fr.xephi.authme.command.executable; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.command.help.HelpProvider; import org.bukkit.command.CommandSender; diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/AuthMeCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/AuthMeCommand.java index ec78d908..3cd42839 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/AuthMeCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/AuthMeCommand.java @@ -7,14 +7,18 @@ import org.bukkit.command.CommandSender; import java.util.List; +/** + * AuthMe base command; shows the version and some command pointers. + */ public class AuthMeCommand extends ExecutableCommand { @Override public void executeCommand(CommandSender sender, List arguments) { - // Show some version info - // FIXME replace use of commandReference - sender.sendMessage(ChatColor.GREEN + "This server is running " + AuthMe.getPluginName() + " v" + AuthMe.getPluginVersion() + " b" + AuthMe.getPluginBuildNumber()+ "! " + ChatColor.RED + "<3"); - sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/" + commandReference.get(0) + " help" + ChatColor.YELLOW + " to view help."); - sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/" + commandReference.get(0) + " about" + ChatColor.YELLOW + " to view about."); + sender.sendMessage(ChatColor.GREEN + "This server is running " + AuthMe.getPluginName() + " v" + + AuthMe.getPluginVersion() + " b" + AuthMe.getPluginBuildNumber()+ "! " + ChatColor.RED + "<3"); + sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/authme help" + ChatColor.YELLOW + + " to view help."); + sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/authme about" + ChatColor.YELLOW + + " to view about."); } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java index b3ea9a2c..590db3d8 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java @@ -3,7 +3,6 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AuthMe; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.cache.auth.PlayerAuth; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; @@ -13,23 +12,15 @@ import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import java.security.NoSuchAlgorithmException; +import java.util.List; /** * Admin command to register a user. */ public class RegisterAdminCommand extends ExecutableCommand { - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ @Override - public boolean executeCommand(final CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { + public void executeCommand(final CommandSender sender, List arguments) { // AuthMe plugin instance final AuthMe plugin = AuthMe.getInstance(); @@ -37,8 +28,8 @@ public class RegisterAdminCommand extends ExecutableCommand { final Messages m = plugin.getMessages(); // Get the player name and password - final String playerName = commandArguments.get(0); - final String playerPass = commandArguments.get(1); + final String playerName = arguments.get(0); + final String playerPass = arguments.get(1); final String playerNameLowerCase = playerName.toLowerCase(); final String playerPassLowerCase = playerPass.toLowerCase(); @@ -49,20 +40,20 @@ public class RegisterAdminCommand extends ExecutableCommand { || playerPassLowerCase.contains(";") || playerPassLowerCase.contains("null") || !playerPassLowerCase.matches(Settings.getPassRegex)) { m.send(sender, MessageKey.PASSWORD_MATCH_ERROR); - return true; + return; } if (playerPassLowerCase.equalsIgnoreCase(playerName)) { m.send(sender, MessageKey.PASSWORD_IS_USERNAME_ERROR); - return true; + return; } if (playerPassLowerCase.length() < Settings.getPasswordMinLen || playerPassLowerCase.length() > Settings.passwordMaxLength) { m.send(sender, MessageKey.INVALID_PASSWORD_LENGTH); - return true; + return; } if (!Settings.unsafePasswords.isEmpty()) { if (Settings.unsafePasswords.contains(playerPassLowerCase)) { m.send(sender, MessageKey.PASSWORD_UNSAFE_ERROR); - return true; + return; } } plugin.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() { @@ -95,6 +86,5 @@ public class RegisterAdminCommand extends ExecutableCommand { } }); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/ResetNameCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/ResetNameCommand.java deleted file mode 100644 index ae1f3840..00000000 --- a/src/main/java/fr/xephi/authme/command/executable/authme/ResetNameCommand.java +++ /dev/null @@ -1,44 +0,0 @@ -package fr.xephi.authme.command.executable.authme; - -import fr.xephi.authme.AuthMe; -import fr.xephi.authme.cache.auth.PlayerAuth; -import fr.xephi.authme.command.CommandParts; -import fr.xephi.authme.command.ExecutableCommand; -import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; - -import java.util.List; - -/** - */ -public class ResetNameCommand extends ExecutableCommand { - - /** - * Execute the command. - * - * @param sender The command sender. - * @param commandReference The command reference. - * @param commandArguments The command arguments. - * - * @return True if the command was executed successfully, false otherwise. - */ - @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { - // AuthMe plugin instance - final AuthMe plugin = AuthMe.getInstance(); - - // Command logic - Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() { - @Override - public void run() { - List authentications = plugin.database.getAllAuths(); - for (PlayerAuth auth : authentications) { - auth.setRealName("Player"); - plugin.database.updateSession(auth); - } - } - }); - - return true; - } -} diff --git a/src/main/java/fr/xephi/authme/command/help/HelpPrinter.java b/src/main/java/fr/xephi/authme/command/help/HelpPrinter.java index e45b4186..fa683524 100644 --- a/src/main/java/fr/xephi/authme/command/help/HelpPrinter.java +++ b/src/main/java/fr/xephi/authme/command/help/HelpPrinter.java @@ -12,7 +12,6 @@ import org.bukkit.entity.Player; import fr.xephi.authme.AuthMe; import fr.xephi.authme.command.CommandArgumentDescription; import fr.xephi.authme.command.CommandDescription; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.CommandPermissions; import fr.xephi.authme.permission.PermissionNode; import fr.xephi.authme.util.CollectionUtils; diff --git a/src/main/java/fr/xephi/authme/command/help/HelpProvider.java b/src/main/java/fr/xephi/authme/command/help/HelpProvider.java index 44afbefa..501a8426 100644 --- a/src/main/java/fr/xephi/authme/command/help/HelpProvider.java +++ b/src/main/java/fr/xephi/authme/command/help/HelpProvider.java @@ -2,7 +2,6 @@ package fr.xephi.authme.command.help; import fr.xephi.authme.AuthMe; import fr.xephi.authme.command.CommandDescription; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.CommandUtils; import fr.xephi.authme.command.FoundCommandResult; import fr.xephi.authme.settings.Settings; diff --git a/src/main/java/fr/xephi/authme/command/help/HelpSyntaxHelper.java b/src/main/java/fr/xephi/authme/command/help/HelpSyntaxHelper.java index 6d1b1d7d..cc7a7d6e 100644 --- a/src/main/java/fr/xephi/authme/command/help/HelpSyntaxHelper.java +++ b/src/main/java/fr/xephi/authme/command/help/HelpSyntaxHelper.java @@ -2,7 +2,6 @@ package fr.xephi.authme.command.help; import fr.xephi.authme.command.CommandArgumentDescription; import fr.xephi.authme.command.CommandDescription; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.CommandUtils; import fr.xephi.authme.util.CollectionUtils; import fr.xephi.authme.util.StringUtils; diff --git a/src/test/java/fr/xephi/authme/command/executable/captcha/CaptchaCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/captcha/CaptchaCommandTest.java index 6b183e35..4a8af38d 100644 --- a/src/test/java/fr/xephi/authme/command/executable/captcha/CaptchaCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/captcha/CaptchaCommandTest.java @@ -1,7 +1,6 @@ package fr.xephi.authme.command.executable.captcha; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; diff --git a/src/test/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommandTest.java index 5c9c295c..da8f82ce 100644 --- a/src/test/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommandTest.java @@ -3,7 +3,6 @@ package fr.xephi.authme.command.executable.changepassword; import fr.xephi.authme.AuthMe; import fr.xephi.authme.ReflectionTestUtils; import fr.xephi.authme.cache.auth.PlayerCache; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; import fr.xephi.authme.settings.Settings; diff --git a/src/test/java/fr/xephi/authme/command/executable/email/AddEmailCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/email/AddEmailCommandTest.java index d377fc0f..38c7d046 100644 --- a/src/test/java/fr/xephi/authme/command/executable/email/AddEmailCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/email/AddEmailCommandTest.java @@ -1,7 +1,6 @@ package fr.xephi.authme.command.executable.email; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.process.Management; import fr.xephi.authme.util.WrapperMock; import org.bukkit.command.BlockCommandSender; diff --git a/src/test/java/fr/xephi/authme/command/executable/email/ChangeEmailCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/email/ChangeEmailCommandTest.java index 2dc25c96..183f3ad1 100644 --- a/src/test/java/fr/xephi/authme/command/executable/email/ChangeEmailCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/email/ChangeEmailCommandTest.java @@ -1,7 +1,6 @@ package fr.xephi.authme.command.executable.email; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.process.Management; import fr.xephi.authme.util.WrapperMock; import org.bukkit.command.BlockCommandSender; diff --git a/src/test/java/fr/xephi/authme/command/executable/email/RecoverEmailCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/email/RecoverEmailCommandTest.java index a1403c5a..73711de9 100644 --- a/src/test/java/fr/xephi/authme/command/executable/email/RecoverEmailCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/email/RecoverEmailCommandTest.java @@ -1,6 +1,5 @@ package fr.xephi.authme.command.executable.email; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.util.WrapperMock; import org.bukkit.command.BlockCommandSender; import org.bukkit.command.CommandSender; diff --git a/src/test/java/fr/xephi/authme/command/executable/login/LoginCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/login/LoginCommandTest.java index 52a71891..4e6c268d 100644 --- a/src/test/java/fr/xephi/authme/command/executable/login/LoginCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/login/LoginCommandTest.java @@ -1,6 +1,5 @@ package fr.xephi.authme.command.executable.login; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.process.Management; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.util.WrapperMock; diff --git a/src/test/java/fr/xephi/authme/command/executable/logout/LogoutCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/logout/LogoutCommandTest.java index 65f24639..82ffd1a7 100644 --- a/src/test/java/fr/xephi/authme/command/executable/logout/LogoutCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/logout/LogoutCommandTest.java @@ -1,7 +1,6 @@ package fr.xephi.authme.command.executable.logout; import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.process.Management; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.util.WrapperMock; diff --git a/src/test/java/fr/xephi/authme/command/executable/register/RegisterCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/register/RegisterCommandTest.java index 6dd19eb2..cbc12369 100644 --- a/src/test/java/fr/xephi/authme/command/executable/register/RegisterCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/register/RegisterCommandTest.java @@ -1,6 +1,5 @@ package fr.xephi.authme.command.executable.register; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.process.Management; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.Messages; diff --git a/src/test/java/fr/xephi/authme/command/help/HelpSyntaxHelperTest.java b/src/test/java/fr/xephi/authme/command/help/HelpSyntaxHelperTest.java index 3ca665f4..185bf08b 100644 --- a/src/test/java/fr/xephi/authme/command/help/HelpSyntaxHelperTest.java +++ b/src/test/java/fr/xephi/authme/command/help/HelpSyntaxHelperTest.java @@ -1,7 +1,6 @@ package fr.xephi.authme.command.help; import fr.xephi.authme.command.CommandDescription; -import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.command.executable.authme.RegisterAdminCommand; import org.junit.Test; From d26cbfbd1469aba617b4245aed21fb25b4deff91 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sat, 12 Dec 2015 22:28:05 +0100 Subject: [PATCH 08/18] Use Guava for CommandDescription builder validation --- .../authme/command/CommandDescription.java | 47 +++++-------------- 1 file changed, 11 insertions(+), 36 deletions(-) diff --git a/src/main/java/fr/xephi/authme/command/CommandDescription.java b/src/main/java/fr/xephi/authme/command/CommandDescription.java index 8ea3fac3..b9736352 100644 --- a/src/main/java/fr/xephi/authme/command/CommandDescription.java +++ b/src/main/java/fr/xephi/authme/command/CommandDescription.java @@ -2,13 +2,13 @@ package fr.xephi.authme.command; import fr.xephi.authme.permission.DefaultPermission; import fr.xephi.authme.permission.PermissionNode; +import fr.xephi.authme.util.CollectionUtils; import fr.xephi.authme.util.StringUtils; import java.util.ArrayList; -import java.util.Collection; import java.util.List; -import static com.google.common.base.Objects.firstNonNull; +import static com.google.common.base.Preconditions.checkArgument; import static java.util.Arrays.asList; /** @@ -220,15 +220,14 @@ public class CommandDescription { * @return The generated CommandDescription object */ public CommandDescription build() { - return createInstance( - getOrThrow(labels, "labels"), - firstNonNull(description, ""), - firstNonNull(detailedDescription, ""), - getOrThrow(executableCommand, "executableCommand"), - firstNonNull(parent, null), - arguments, - permissions - ); + checkArgument(!CollectionUtils.isEmpty(labels), "Labels may not be empty"); + checkArgument(!StringUtils.isEmpty(description), "Description may not be empty"); + checkArgument(!StringUtils.isEmpty(detailedDescription), "Detailed description may not be empty"); + checkArgument(executableCommand != null, "Executable command must be set"); + // parents and permissions may be null; arguments may be empty + + return createInstance(labels, description, detailedDescription, executableCommand, + parent, arguments, permissions); } public CommandBuilder labels(List labels) { @@ -277,33 +276,9 @@ public class CommandDescription { public CommandBuilder permissions(DefaultPermission defaultPermission, PermissionNode... permissionNodes) { - this.permissions = new CommandPermissions(asMutableList(permissionNodes), defaultPermission); + this.permissions = new CommandPermissions(asList(permissionNodes), defaultPermission); return this; } - - @SafeVarargs - private static List asMutableList(T... items) { - return new ArrayList<>(asList(items)); - } - - private static T getOrThrow(T element, String elementName) { - if (!isEmpty(element)) { - return element; - } - throw new RuntimeException("The element '" + elementName + "' may not be empty in CommandDescription"); - } - - private static boolean isEmpty(T element) { - if (element == null) { - return true; - } else if (element instanceof Collection) { - return ((Collection) element).isEmpty(); - } else if (element instanceof String) { - return StringUtils.isEmpty((String) element); - } - return false; - } - } } From 01cba2a508ca9590e539076da3ae3f8858fa12ee Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sat, 12 Dec 2015 22:50:07 +0100 Subject: [PATCH 09/18] #315 #305 Refactor HelpProvider - add bit flags, reduce duplication (wip) --- .../authme/command/CommandDescription.java | 24 +- .../xephi/authme/command/CommandHandler.java | 12 +- .../authme/command/help/HelpProvider.java | 301 ++++++++++++------ .../authme/permission/DefaultPermission.java | 23 +- 4 files changed, 242 insertions(+), 118 deletions(-) diff --git a/src/main/java/fr/xephi/authme/command/CommandDescription.java b/src/main/java/fr/xephi/authme/command/CommandDescription.java index b9736352..6903916d 100644 --- a/src/main/java/fr/xephi/authme/command/CommandDescription.java +++ b/src/main/java/fr/xephi/authme/command/CommandDescription.java @@ -65,7 +65,7 @@ public class CommandDescription { } /** - * Create an instance for internal use. + * Create an instance. * * @param labels List of command labels. * @param description Command description. @@ -108,7 +108,7 @@ public class CommandDescription { * @return All relative labels. */ public List getLabels() { - return this.labels; + return labels; } /** @@ -145,23 +145,34 @@ public class CommandDescription { return parent; } + /** + * Return the number of parents that precede the command description. + * + * @return The number of parents, e.g. for "/authme abc def" the parent count is 2 ("/authme abc", "/authme") + */ + public int getParentCount() { + if (parent == null) { + return 0; + } + return parent.getParentCount() + 1; + } + /** * Return all command children. * * @return Command children. */ public List getChildren() { - return this.children; + return children; } - /** * Return all arguments the command takes. * * @return Command arguments. */ public List getArguments() { - return this.arguments; + return arguments; } /** @@ -182,14 +193,13 @@ public class CommandDescription { return detailedDescription; } - /** * Return the permissions required to execute the command. * * @return The command permissions, or null if none are required to execute the command. */ public CommandPermissions getCommandPermissions() { - return this.permissions; + return permissions; } /** diff --git a/src/main/java/fr/xephi/authme/command/CommandHandler.java b/src/main/java/fr/xephi/authme/command/CommandHandler.java index 61a99188..d8047a6b 100644 --- a/src/main/java/fr/xephi/authme/command/CommandHandler.java +++ b/src/main/java/fr/xephi/authme/command/CommandHandler.java @@ -128,11 +128,15 @@ public class CommandHandler { // Show the command argument help sender.sendMessage(ChatColor.DARK_RED + "Incorrect command arguments!"); - // TODO: Define showHelp(CommandSender, CommandDescription, List, boolean, boolean, ...) + List lines = HelpProvider.printHelp(result, HelpProvider.SHOW_ARGUMENTS); + for (String line : lines) { + sender.sendMessage(line); + } + List labels = result.getLabels(); - HelpProvider.showHelp(sender, command, labels, true, false, true, false, false, false); - sender.sendMessage(ChatColor.GOLD + "Detailed help: " + ChatColor.WHITE + "/" + labels.get(0) - + " help " + CommandUtils.labelsToString(labels.subList(1, labels.size()))); + String childLabel = labels.size() >= 2 ? labels.get(1) : ""; + sender.sendMessage(ChatColor.GOLD + "Detailed help: " + ChatColor.WHITE + + "/" + labels.get(0) + " help " + childLabel); } // TODO ljacqu 20151212: Remove me once I am a MessageKey diff --git a/src/main/java/fr/xephi/authme/command/help/HelpProvider.java b/src/main/java/fr/xephi/authme/command/help/HelpProvider.java index 501a8426..97556ab3 100644 --- a/src/main/java/fr/xephi/authme/command/help/HelpProvider.java +++ b/src/main/java/fr/xephi/authme/command/help/HelpProvider.java @@ -1,141 +1,234 @@ package fr.xephi.authme.command.help; -import fr.xephi.authme.AuthMe; +import com.google.common.collect.ImmutableList; +import fr.xephi.authme.command.CommandArgumentDescription; import fr.xephi.authme.command.CommandDescription; +import fr.xephi.authme.command.CommandPermissions; import fr.xephi.authme.command.CommandUtils; import fr.xephi.authme.command.FoundCommandResult; +import fr.xephi.authme.permission.DefaultPermission; +import fr.xephi.authme.permission.PermissionNode; +import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.settings.Settings; - import fr.xephi.authme.util.CollectionUtils; +import fr.xephi.authme.util.StringUtils; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.List; +import static java.util.Collections.singletonList; + /** + * Help syntax generator for AuthMe commands. */ -public class HelpProvider { +public final class HelpProvider { - /** - * Show help for a specific command. - * - * @param sender The command sender the help needs to be shown to. - * @param reference The command reference to the help command. - * @param helpQuery The query to show help for. - */ - public static void showHelp(CommandSender sender, CommandParts reference, CommandParts helpQuery) { - showHelp(sender, reference, helpQuery, true, true, true, true, true, true); + // --- Bit flags --- + /** Set to not show the command. */ + public static final int HIDE_COMMAND = 0x001; + /** Set to show the detailed description of a command. */ + public static final int SHOW_LONG_DESCRIPTION = 0x002; + /** Set to include the arguments the command takes. */ + public static final int SHOW_ARGUMENTS = 0x004; + /** Set to show the permissions required to execute the command. */ + public static final int SHOW_PERMISSIONS = 0x008; + /** Set to show alternative labels for the command. */ + public static final int SHOW_ALTERNATIVES = 0x010; + /** Set to show the child commands of the command. */ + public static final int SHOW_CHILDREN = 0x020; + + /** Shortcut for setting all options apart from {@link HelpProvider#HIDE_COMMAND}. */ + public static final int ALL_OPTIONS = ~HIDE_COMMAND; + + private HelpProvider() { } - public static void showHelp(CommandSender sender, CommandParts reference, CommandParts helpQuery, - boolean showCommand, boolean showDescription, boolean showArguments, - boolean showPermissions, boolean showAlternatives, boolean showCommands) { - showHelp(sender, reference.getList(), helpQuery.getList(), showCommand, showDescription, showArguments, - showPermissions, showAlternatives, showCommands); + public static List printHelp(FoundCommandResult foundCommand, int options) { + return printHelp(foundCommand, null, null, options); } - /** - * Show help for a specific command. - * - * @param sender The command sender the help needs to be shown to. - * @param reference The command reference to the help command. - * @param helpQuery The query to show help for. - * @param showCommand True to show the command. - * @param showDescription True to show the command description, both the short and detailed description. - * @param showArguments True to show the command argument help. - * @param showPermissions True to show the command permission help. - * @param showAlternatives True to show the command alternatives. - * @param showCommands True to show the child commands. - */ - public static void showHelp(CommandSender sender, List reference, List helpQuery, - boolean showCommand, boolean showDescription, boolean showArguments, - boolean showPermissions, boolean showAlternatives, boolean showCommands) { - // Find the command for this help query, one with and one without a prefixed base command - FoundCommandResult result = AuthMe.getInstance().getCommandHandler().findCommand(new CommandParts(helpQuery.getList())); - - // TODO ljacqu 20151204 Fix me to nicer code - List parts = new ArrayList<>(helpQuery.getList()); - parts.add(0, reference.get(0)); - CommandParts commandReferenceOther = new CommandParts(parts); - - FoundCommandResult resultOther = AuthMe.getInstance().getCommandHandler().findCommand(commandReferenceOther); - if (resultOther != null) { - if (result == null) - result = resultOther; - - else if (result.getDifference() > resultOther.getDifference()) - result = resultOther; + // sender and permissions manager may be null if SHOW_PERMISSIONS is not set + public static List printHelp(FoundCommandResult foundCommand, CommandSender sender, + PermissionsManager permissionsManager, int options) { + if (foundCommand.getCommandDescription() == null) { + return singletonList(ChatColor.DARK_RED + "Failed to retrieve any help information!"); } - // Make sure a result was found - if (result == null) { - // Show a warning message - sender.sendMessage(ChatColor.DARK_RED + "" + ChatColor.ITALIC + helpQuery); - sender.sendMessage(ChatColor.DARK_RED + "Couldn't show any help information for this help query."); + List lines = new ArrayList<>(); + lines.add(ChatColor.GOLD + "==========[ " + Settings.helpHeader + " HELP ]=========="); + + CommandDescription command = foundCommand.getCommandDescription(); + // TODO ljacqu 20151212: Remove immutability once class is stable. We don't want mutability but the overhead + // isn't worth it either. This is just a temporary safeguard during development + List labels = ImmutableList.copyOf(foundCommand.getLabels()); + + if (!hasFlag(HIDE_COMMAND, options)) { + printCommand(command, labels, lines); // FIXME: Pass `correctLabels` and not `labels` + } + if (hasFlag(SHOW_LONG_DESCRIPTION, options)) { + printDetailedDescription(command, lines); + } + if (hasFlag(SHOW_ARGUMENTS, options)) { + printArguments(command, lines); + } + if (hasFlag(SHOW_PERMISSIONS, options) && sender != null && permissionsManager != null) { + printPermissions(command, sender, permissionsManager, lines); + } + if (hasFlag(SHOW_ALTERNATIVES, options)) { + printAlternatives(command, labels, lines); + } + if (hasFlag(SHOW_CHILDREN, options)) { + printChildren(command, labels, lines); + } + + return lines; + } + + private static void printCommand(CommandDescription command, List correctLabels, List lines) { + // Ensure that we have all labels to go to the command + int requiredLabels = command.getParentCount() + 1; + List givenLabels = new ArrayList<>(correctLabels); + // Only case this is possible: givenLabels.size() == 1 && requiredLabels == 2, + // since command.getParentCount() never exceeds 1 in AuthMe + // FIXME: Might be smart to put this logic outside and to pass it as `correctLabels`? We will need this at a few + // places annotated with a FIXME + if (givenLabels.size() < requiredLabels) { + givenLabels.add(command.getLabels().get(0)); + } + + // FIXME: Create highlight logic to mark arguments and the 2nd label as yellow + String syntaxLine = "/" + CommandUtils.labelsToString(givenLabels); + for (CommandArgumentDescription argument : command.getArguments()) { + syntaxLine += " " + formatArgument(argument); + } + lines.add(syntaxLine); + } + + private static void printDetailedDescription(CommandDescription command, List lines) { + lines.add(ChatColor.GOLD + "Short Description: " + ChatColor.WHITE + command.getDescription()); + lines.add(ChatColor.GOLD + "Detailed Description:"); + lines.add(ChatColor.WHITE + " " + command.getDetailedDescription()); + } + + private static void printArguments(CommandDescription command, List lines) { + if (!command.getArguments().isEmpty()) { return; } - // Get the command description, and make sure it's valid - CommandDescription command = result.getCommandDescription(); - if (command == null) { - // Show a warning message - sender.sendMessage(ChatColor.DARK_RED + "Failed to retrieve any help information!"); - return; - } + lines.add(ChatColor.GOLD + "Arguments:"); + for (CommandArgumentDescription argument : command.getArguments()) { + StringBuilder argString = new StringBuilder(); + argString.append(" ").append(ChatColor.YELLOW).append(ChatColor.ITALIC).append(argument.getName()) + .append(": ").append(ChatColor.WHITE).append(argument.getDescription()); - // Get the proper command reference to use for the help page - CommandParts commandReference = command.getCommandReference(result.getLabels()); - - // Get the base command - String baseCommand = commandReference.get(0); - - // Make sure the difference between the command reference and the actual command isn't too big - final double commandDifference = result.getDifference(); - if (commandDifference > 0.20) { - // Show the unknown command warning - sender.sendMessage(ChatColor.DARK_RED + "No help found for '" + helpQuery + "'!"); - - // Show a command suggestion if available and the difference isn't too big - if (commandDifference < 0.75 && result.getCommandDescription() != null) { - // Get the suggested command - List suggestedCommandParts = CollectionUtils.getRange( - result.getCommandDescription().getCommandReference(commandReference).getList(), 1); - sender.sendMessage(ChatColor.YELLOW + "Did you mean " + ChatColor.GOLD + "/" + baseCommand - + " help " + CommandUtils.labelsToString(suggestedCommandParts) + ChatColor.YELLOW + "?"); + if (argument.isOptional()) { + argString.append(ChatColor.GRAY).append(ChatColor.ITALIC).append(" (Optional)"); } + lines.add(argString.toString()); + } + } - // Show the help command - sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/" + baseCommand + " help" + ChatColor.YELLOW + " to view help."); + // FIXME: labels is currently assumed to be only the ones leading to the given command, but we have scenarios where + // we're guessing the command, so the final label isn't any existing one + private static void printAlternatives(CommandDescription command, List labels, List lines) { + if (command.getLabels().size() <= 1) { return; } - // Show a message when the command handler is assuming a command - if (commandDifference > 0) { - // Get the suggested command - List suggestedCommandParts = CollectionUtils.getRange( - result.getCommandDescription().getCommandReference(commandReference).getList(), 1); + // Print the header + lines.add(ChatColor.GOLD + "Alternatives:"); - // Show the suggested command - sender.sendMessage(ChatColor.DARK_RED + "No help found, assuming '" + ChatColor.GOLD - + CommandUtils.labelsToString(suggestedCommandParts) + ChatColor.DARK_RED + "'!"); + // Get the label used + // fixme this is not correct if help is triggered by incorrect number of arguments + final String usedLabel = labels.get(labels.size() - 1); + + // Create a list of alternatives + List alternatives = new ArrayList<>(); + for (String entry : command.getLabels()) { + if (!entry.equalsIgnoreCase(usedLabel)) { + alternatives.add(entry); + } } - // Print the help header - sender.sendMessage(ChatColor.GOLD + "==========[ " + Settings.helpHeader.toUpperCase() + " HELP ]=========="); + // Sort the alternatives + Collections.sort(alternatives, new Comparator() { + // TODO ljacqu 20151212: This computes the difference each time anew. It might make sense to compute the + // difference once and to store it in some map-like structure (Guava has some interesting ones) + @Override + public int compare(String o1, String o2) { + return Double.compare(StringUtils.getDifference(usedLabel, o1), + StringUtils.getDifference(usedLabel, o2)); + } + }); - // Print the command help information - if (showCommand) - HelpPrinter.printCommand(sender, command, commandReference); - if (showDescription) - HelpPrinter.printCommandDescription(sender, command); - if (showArguments) - HelpPrinter.printArguments(sender, command); - if (showPermissions) - HelpPrinter.printPermissions(sender, command); - if (showAlternatives) - HelpPrinter.printAlternatives(sender, command, commandReference); - if (showCommands) - HelpPrinter.printChildren(sender, command, commandReference); + // Print each alternative with proper syntax + for (String alternative : alternatives) { + // fixme add highlight functionality (see commented old line) + // sender.sendMessage(" " + _HelpSyntaxHelper.getCommandSyntax(command, commandReference, alternative, true)); + lines.add(" " + CommandUtils.labelsToString(labels) + " " + alternative); + } } + + public static void printPermissions(CommandDescription command, CommandSender sender, + PermissionsManager permissionsManager, List lines) { + CommandPermissions permissions = command.getCommandPermissions(); + if (permissions == null || CollectionUtils.isEmpty(permissions.getPermissionNodes())) { + return; + } + lines.add(ChatColor.GOLD + "Permissions:"); + + for (PermissionNode node : permissions.getPermissionNodes()) { + boolean hasPermission = permissionsManager.hasPermission(sender, node); + final String nodePermsString = "" + ChatColor.GRAY + ChatColor.ITALIC + + (hasPermission ? " (You have permission)" : " (No permission)"); + lines.add(" " + ChatColor.YELLOW + ChatColor.ITALIC + node.getNode() + nodePermsString); + } + + // Addendum to the line to specify whether the sender has permission or not when default is OP_ONLY + final DefaultPermission defaultPermission = permissions.getDefaultPermission(); + String addendum = ""; + if (DefaultPermission.OP_ONLY.equals(defaultPermission)) { + addendum = PermissionsManager.evaluateDefaultPermission(defaultPermission, sender) + ? " (You have permission)" + : " (No permission)"; + } + lines.add(ChatColor.GOLD + "Default: " + ChatColor.GRAY + ChatColor.ITALIC + + defaultPermission.getTitle() + addendum); + + // Evaluate if the sender has permission to the command + if (permissionsManager.hasPermission(sender, command)) { + lines.add(ChatColor.GOLD + " Result: " + ChatColor.GREEN + ChatColor.ITALIC + "You have permission"); + } else { + lines.add(ChatColor.GOLD + " Result: " + ChatColor.DARK_RED + ChatColor.ITALIC + "No permission"); + } + } + + private static void printChildren(CommandDescription command, List parentLabels, List lines) { + if (command.getChildren().isEmpty()) { + return; + } + + lines.add(ChatColor.GOLD + "Commands:"); + String parentCommandPath = CommandUtils.labelsToString(parentLabels); + for (CommandDescription child : command.getChildren()) { + lines.add(" " + parentCommandPath + child.getLabels().get(0) + + ChatColor.GRAY + ChatColor.ITALIC + ": " + child.getDescription()); + } + } + + private static String formatArgument(CommandArgumentDescription argument) { + if (argument.isOptional()) { + return " [" + argument.getName() + "]"; + } + return " <" + argument.getName() + ">"; + } + + private static boolean hasFlag(int flag, int options) { + return (flag & options) != 0; + } + } diff --git a/src/main/java/fr/xephi/authme/permission/DefaultPermission.java b/src/main/java/fr/xephi/authme/permission/DefaultPermission.java index 09f0856a..f09de526 100644 --- a/src/main/java/fr/xephi/authme/permission/DefaultPermission.java +++ b/src/main/java/fr/xephi/authme/permission/DefaultPermission.java @@ -6,11 +6,28 @@ package fr.xephi.authme.permission; public enum DefaultPermission { /** No one can execute the command. */ - NOT_ALLOWED, + NOT_ALLOWED("No permission"), /** Only players with the OP status may execute the command. */ - OP_ONLY, + OP_ONLY("OP's only"), /** The command can be executed by anyone. */ - ALLOWED + ALLOWED("Everyone allowed"); + + /** Textual representation of the default permission. */ + private final String title; + + /** + * Constructor. + * @param title The textual representation + */ + DefaultPermission(String title) { + this.title = title; + } + + /** Return the textual representation. */ + public String getTitle() { + return title; + } + } From c48c56f08cc649813102c4596d81e4b5be3e4c3f Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sun, 13 Dec 2015 10:12:54 +0100 Subject: [PATCH 10/18] Change to new HelpProvider, adjust classes to new methods --- .../xephi/authme/command/CommandHandler.java | 3 +- .../authme/command/FoundCommandResult.java | 12 ++ .../command/executable/HelpCommand.java | 50 +++-- .../executable/authme/AccountsCommand.java | 21 +- .../executable/authme/SetEmailCommand.java | 3 +- .../authme/SwitchAntiBotCommand.java | 44 ++-- .../authme/command/help/HelpPrinter.java | 193 ------------------ .../authme/command/help/HelpSyntaxHelper.java | 79 ------- .../command/CommandInitializerTest.java | 6 +- .../captcha/CaptchaCommandTest.java | 8 +- .../ChangePasswordCommandTest.java | 31 ++- .../executable/email/AddEmailCommandTest.java | 9 +- .../email/ChangeEmailCommandTest.java | 8 +- .../email/RecoverEmailCommandTest.java | 4 +- .../executable/login/LoginCommandTest.java | 12 +- .../executable/logout/LogoutCommandTest.java | 5 +- .../register/RegisterCommandTest.java | 10 +- .../command/help/HelpSyntaxHelperTest.java | 131 ------------ 18 files changed, 117 insertions(+), 512 deletions(-) delete mode 100644 src/main/java/fr/xephi/authme/command/help/HelpPrinter.java delete mode 100644 src/main/java/fr/xephi/authme/command/help/HelpSyntaxHelper.java delete mode 100644 src/test/java/fr/xephi/authme/command/help/HelpSyntaxHelperTest.java diff --git a/src/main/java/fr/xephi/authme/command/CommandHandler.java b/src/main/java/fr/xephi/authme/command/CommandHandler.java index d8047a6b..bf97d173 100644 --- a/src/main/java/fr/xephi/authme/command/CommandHandler.java +++ b/src/main/java/fr/xephi/authme/command/CommandHandler.java @@ -178,7 +178,8 @@ public class CommandHandler { closestCommand = child; } } - // TODO: Return the full list of labels and arguments + // FIXME: Return the full list of labels and arguments + // FIXME: Return INVALID_ARGUMENTS instead of UNKNOWN_LABEL when more accurate return new FoundCommandResult( closestCommand, null, null, minDifference, FoundCommandResult.ResultStatus.UNKNOWN_LABEL); } diff --git a/src/main/java/fr/xephi/authme/command/FoundCommandResult.java b/src/main/java/fr/xephi/authme/command/FoundCommandResult.java index 99750069..e35a3f25 100644 --- a/src/main/java/fr/xephi/authme/command/FoundCommandResult.java +++ b/src/main/java/fr/xephi/authme/command/FoundCommandResult.java @@ -3,6 +3,18 @@ package fr.xephi.authme.command; import java.util.List; /** + * Result of a command mapping by {@link CommandHandler}. An object of this class represents a successful mapping + * as well as erroneous ones, as communicated with {@link ResultStatus}. + *

+ * Fields other than {@link ResultStatus} are available depending, among other factors, on the status: + *

    + *
  • {@link ResultStatus#SUCCESS} entails that mapping the input to a command was successful. Therefore, + * the command description, labels and arguments are set. The difference is 0.0.
  • + *
  • {@link ResultStatus#INCORRECT_ARGUMENTS}
  • + *
  • {@link ResultStatus#UNKNOWN_LABEL}
  • + *
  • {@link ResultStatus#MISSING_BASE_COMMAND} should never occur. Any other fields may not be present and any + * processing of the object should be aborted.
  • + *
*/ public class FoundCommandResult { diff --git a/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java b/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java index ff7a9130..0282751a 100644 --- a/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java @@ -1,28 +1,54 @@ package fr.xephi.authme.command.executable; +import fr.xephi.authme.AuthMe; +import fr.xephi.authme.command.CommandHandler; +import fr.xephi.authme.command.CommandUtils; import fr.xephi.authme.command.ExecutableCommand; +import fr.xephi.authme.command.FoundCommandResult; import fr.xephi.authme.command.help.HelpProvider; +import fr.xephi.authme.permission.PermissionsManager; +import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import java.util.List; -/** - */ +import static fr.xephi.authme.command.FoundCommandResult.ResultStatus.*; + public class HelpCommand extends ExecutableCommand { + // Convention: arguments is not the actual invoked arguments but the command that was invoked, + // e.g. "/authme help register" would typically be arguments = [register], but here we pass [authme, register] @Override - public boolean executeCommand(CommandSender sender, CommandParts commandReference, CommandParts commandArguments) { - // Check whether quick help should be shown - List arguments = commandArguments.getList(); + public void executeCommand(CommandSender sender, List arguments) { + // TODO #306 ljacqu 20151213: Get command handler from non-static context + CommandHandler commandHandler = AuthMe.getInstance().getCommandHandler(); + FoundCommandResult foundCommandResult = commandHandler.mapPartsToCommand(arguments); - // Set the proper command arguments for the quick help and show it - if (arguments.isEmpty()) { - commandArguments = new CommandParts(commandReference.get(0)); - HelpProvider.showHelp(sender, commandReference, commandArguments, false, false, false, false, false, true); - } else { - HelpProvider.showHelp(sender, commandReference, commandArguments); + // TODO ljacqu 20151213: This is essentially the same logic as in CommandHandler and we'd like to have the same + // messages. Maybe we can have another method in CommandHandler where the end command isn't executed upon + // success. + FoundCommandResult.ResultStatus resultStatus = foundCommandResult.getResultStatus(); + if (MISSING_BASE_COMMAND.equals(resultStatus)) { + sender.sendMessage(ChatColor.DARK_RED + "Could not get base command"); + return; + } else if (INCORRECT_ARGUMENTS.equals(resultStatus) || UNKNOWN_LABEL.equals(resultStatus)) { + if (foundCommandResult.getCommandDescription() != null) { + sender.sendMessage(ChatColor.DARK_RED + "Unknown command"); + return; + } else { + sender.sendMessage(ChatColor.GOLD + "Assuming " + ChatColor.WHITE + "/" + + CommandUtils.labelsToString(foundCommandResult.getCommandDescription().getLabels())); + } + } + + PermissionsManager permissionsManager = AuthMe.getInstance().getPermissionsManager(); + List lines = arguments.size() == 1 + ? HelpProvider.printHelp(foundCommandResult, HelpProvider.SHOW_CHILDREN) + : HelpProvider.printHelp(foundCommandResult, sender, permissionsManager, HelpProvider.ALL_OPTIONS); + for (String line : lines) { + sender.sendMessage(line); } - return true; } + } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java index bae59597..2fc63e0d 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java @@ -16,19 +16,14 @@ public class AccountsCommand extends ExecutableCommand { final AuthMe plugin = AuthMe.getInstance(); final Messages m = plugin.getMessages(); - // Get the player query - String playerQuery = sender.getName(); - if (commandArguments.getCount() >= 1) { - playerQuery = commandArguments.get(0); - } - final String playerQueryFinal = playerQuery; + final String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0); // Command logic - if (!playerQueryFinal.contains(".")) { + if (!playerName.contains(".")) { plugin.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() { @Override public void run() { - PlayerAuth auth = plugin.database.getAuth(playerQueryFinal.toLowerCase()); + PlayerAuth auth = plugin.database.getAuth(playerName.toLowerCase()); if (auth == null) { m.send(sender, MessageKey.UNKNOWN_USER); return; @@ -40,7 +35,7 @@ public class AccountsCommand extends ExecutableCommand { return; } if (accountList.size() == 1) { - sender.sendMessage("[AuthMe] " + playerQueryFinal + " is a single account player"); + sender.sendMessage("[AuthMe] " + playerName + " is a single account player"); return; } int i = 0; @@ -53,7 +48,7 @@ public class AccountsCommand extends ExecutableCommand { message.append('.'); } } - sender.sendMessage("[AuthMe] " + playerQueryFinal + " has " + sender.sendMessage("[AuthMe] " + playerName + " has " + String.valueOf(accountList.size()) + " accounts."); sender.sendMessage(message.toString()); } @@ -63,14 +58,14 @@ public class AccountsCommand extends ExecutableCommand { plugin.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() { @Override public void run() { - List accountList = plugin.database.getAllAuthsByIp(playerQueryFinal); + List accountList = plugin.database.getAllAuthsByIp(playerName); StringBuilder message = new StringBuilder("[AuthMe] "); if (accountList.isEmpty()) { sender.sendMessage("[AuthMe] This IP does not exist in the database."); return; } if (accountList.size() == 1) { - sender.sendMessage("[AuthMe] " + playerQueryFinal + " is a single account player"); + sender.sendMessage("[AuthMe] " + playerName + " is a single account player"); return; } int i = 0; @@ -83,7 +78,7 @@ public class AccountsCommand extends ExecutableCommand { message.append('.'); } } - sender.sendMessage("[AuthMe] " + playerQueryFinal + " has " + sender.sendMessage("[AuthMe] " + playerName + " has " + String.valueOf(accountList.size()) + " accounts."); sender.sendMessage(message.toString()); } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java index e10dd1ab..b52a07eb 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/SetEmailCommand.java @@ -14,7 +14,7 @@ import java.util.List; public class SetEmailCommand extends ExecutableCommand { @Override - public void executeCommand(CommandSender sender, List arguments) { + public void executeCommand(final CommandSender sender, List arguments) { // AuthMe plugin instance final AuthMe plugin = AuthMe.getInstance(); @@ -59,6 +59,5 @@ public class SetEmailCommand extends ExecutableCommand { } }); - return true; } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommand.java index 4f541a9e..73fac3fb 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/SwitchAntiBotCommand.java @@ -1,53 +1,43 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.AntiBot; -import fr.xephi.authme.command.CommandUtils; +import fr.xephi.authme.AuthMe; +import fr.xephi.authme.command.CommandHandler; import fr.xephi.authme.command.ExecutableCommand; +import fr.xephi.authme.command.FoundCommandResult; import fr.xephi.authme.command.help.HelpProvider; -import fr.xephi.authme.util.CollectionUtils; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; +import java.util.Arrays; import java.util.List; public class SwitchAntiBotCommand extends ExecutableCommand { @Override public void executeCommand(final CommandSender sender, List arguments) { - // Get the new state - String newState = null; - - if (arguments.size() == 1) { - newState = arguments.get(0); - } else if (arguments.size() == 0) { + if (arguments.isEmpty()) { sender.sendMessage("[AuthMe] AntiBot status: " + AntiBot.getAntiBotStatus().name()); return; } - // Enable the mod + String newState = arguments.get(0); + + // Enable or disable the mod if ("ON".equalsIgnoreCase(newState)) { AntiBot.overrideAntiBotStatus(true); sender.sendMessage("[AuthMe] AntiBot Manual Override: enabled!"); - return; - } - - // Disable the mod - if ("OFF".equalsIgnoreCase(newState)) { + } else if ("OFF".equalsIgnoreCase(newState)) { AntiBot.overrideAntiBotStatus(false); sender.sendMessage("[AuthMe] AntiBotMod Manual Override: disabled!"); - return; + } else { + sender.sendMessage(ChatColor.DARK_RED + "Invalid AntiBot mode!"); + // TODO ljacqu 20151213: Fix static retrieval of command handler + CommandHandler commandHandler = AuthMe.getInstance().getCommandHandler(); + FoundCommandResult foundCommandResult = + commandHandler.mapPartsToCommand(Arrays.asList("authme", "antibot")); + HelpProvider.printHelp(foundCommandResult, HelpProvider.SHOW_ARGUMENTS); + sender.sendMessage(ChatColor.GOLD + "Detailed help: " + ChatColor.WHITE + "/authme help antibot"); } - - // Show the invalid arguments warning - sender.sendMessage(ChatColor.DARK_RED + "Invalid AntiBot mode!"); - - // Show the command argument help - // FIXME fix help reference - HelpProvider.showHelp(sender, commandReference, commandReference, true, false, true, false, false, false); - - // Show the command to use for detailed help - List helpCommandReference = CollectionUtils.getRange(commandReference.getList(), 1); - sender.sendMessage(ChatColor.GOLD + "Detailed help: " + ChatColor.WHITE + "/" - + commandReference.get(0) + " help " + CommandUtils.labelsToString(helpCommandReference)); } } diff --git a/src/main/java/fr/xephi/authme/command/help/HelpPrinter.java b/src/main/java/fr/xephi/authme/command/help/HelpPrinter.java deleted file mode 100644 index fa683524..00000000 --- a/src/main/java/fr/xephi/authme/command/help/HelpPrinter.java +++ /dev/null @@ -1,193 +0,0 @@ -package fr.xephi.authme.command.help; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -import org.bukkit.ChatColor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import fr.xephi.authme.AuthMe; -import fr.xephi.authme.command.CommandArgumentDescription; -import fr.xephi.authme.command.CommandDescription; -import fr.xephi.authme.command.CommandPermissions; -import fr.xephi.authme.permission.PermissionNode; -import fr.xephi.authme.util.CollectionUtils; -import fr.xephi.authme.util.StringUtils; - -/** - */ -public class HelpPrinter { - - /** - * Print the command help information. - * - * @param sender The command sender to print the help to. - * @param command The command to print. - * @param commandReference The command reference used. - */ - public static void printCommand(CommandSender sender, CommandDescription command, CommandParts commandReference) { - // Print the proper command syntax - sender.sendMessage(ChatColor.GOLD + "Command: " + HelpSyntaxHelper.getCommandSyntax(command, commandReference, null, true)); - } - - /** - * Print the command help description information. This will print both the short, as the detailed description if available. - * - * @param sender The command sender to print the help to. - * @param command The command to print the description help for. - */ - public static void printCommandDescription(CommandSender sender, CommandDescription command) { - sender.sendMessage(ChatColor.GOLD + "Short Description: " + ChatColor.WHITE + command.getDescription()); - - // Print the detailed description, if available - if (!StringUtils.isEmpty(command.getDetailedDescription())) { - sender.sendMessage(ChatColor.GOLD + "Detailed Description:"); - sender.sendMessage(ChatColor.WHITE + " " + command.getDetailedDescription()); - } - } - - /** - * Print the command help arguments information if available. - * - * @param sender The command sender to print the help to. - * @param command The command to print the argument help for. - */ - @SuppressWarnings("StringConcatenationInsideStringBufferAppend") - public static void printArguments(CommandSender sender, CommandDescription command) { - // Make sure there are any commands to print - if (!command.hasArguments()) - return; - - // Print the header - sender.sendMessage(ChatColor.GOLD + "Arguments:"); - - // Print each argument - for (CommandArgumentDescription arg : command.getArguments()) { - // Create a string builder to build the syntax in - StringBuilder argString = new StringBuilder(); - argString.append(" " + ChatColor.YELLOW + ChatColor.ITALIC + arg.getName() + " : " + ChatColor.WHITE + arg.getDescription()); - - // Suffix a note if the command is optional - if (arg.isOptional()) - argString.append(ChatColor.GRAY + "" + ChatColor.ITALIC + " (Optional)"); - - // Print the syntax - sender.sendMessage(argString.toString()); - } - } - - /** - * Print the command help permissions information if available. - * - * @param sender The command sender to print the help to. - * @param command The command to print the permissions help for. - */ - public static void printPermissions(CommandSender sender, CommandDescription command) { - // Get the permissions and make sure they aren't missing - CommandPermissions permissions = command.getCommandPermissions(); - if (permissions == null || CollectionUtils.isEmpty(permissions.getPermissionNodes())) { - return; - } - - // Print the header - sender.sendMessage(ChatColor.GOLD + "Permissions:"); - - // Print each node - for (PermissionNode node : permissions.getPermissionNodes()) { - boolean nodePermission = true; - if (sender instanceof Player) - nodePermission = AuthMe.getInstance().getPermissionsManager().hasPermission((Player) sender, node); - final String nodePermsString = ChatColor.GRAY + (nodePermission ? ChatColor.ITALIC + " (Permission!)" : ChatColor.ITALIC + " (No Permission!)"); - sender.sendMessage(" " + ChatColor.YELLOW + ChatColor.ITALIC + node.getNode() + nodePermsString); - } - - // Print the default permission - // TODO ljacqu 20151205: This is duplicating the logic in PermissionsManager#evaluateDefaultPermission - // Either use the command manager here, or if that's too heavy, look into moving certain permissions logic - // into a Utils class - switch (permissions.getDefaultPermission()) { - case ALLOWED: - sender.sendMessage(ChatColor.GOLD + " Default: " + ChatColor.GRAY + ChatColor.ITALIC + "Permission!"); - break; - - case OP_ONLY: - final String defaultPermsString = ChatColor.GRAY + (sender.isOp() ? ChatColor.ITALIC + " (Permission!)" : ChatColor.ITALIC + " (No Permission!)"); - sender.sendMessage(ChatColor.GOLD + " Default: " + ChatColor.YELLOW + ChatColor.ITALIC + "OP's Only!" + defaultPermsString); - break; - - case NOT_ALLOWED: - default: - sender.sendMessage(ChatColor.GOLD + " Default: " + ChatColor.GRAY + ChatColor.ITALIC + "No Permission!"); - break; - } - - // Print the permission result - if (permissions.hasPermission(sender)) - sender.sendMessage(ChatColor.GOLD + " Result: " + ChatColor.GREEN + ChatColor.ITALIC + "Permission!"); - else - sender.sendMessage(ChatColor.GOLD + " Result: " + ChatColor.DARK_RED + ChatColor.ITALIC + "No Permission!"); - } - - /** - * Print the command help alternatives information if available. - * - * @param sender The command sender to print the help to. - * @param command The command used. - * @param commandReference The original command reference used for this command. - */ - public static void printAlternatives(CommandSender sender, CommandDescription command, CommandParts commandReference) { - // Make sure there are any alternatives - if (command.getLabels().size() <= 1) - return; - - // Print the header - sender.sendMessage(ChatColor.GOLD + "Alternatives:"); - - // Get the label used - final String usedLabel = commandReference.get(command.getParentCount()); - - // Create a list of alternatives - List alternatives = new ArrayList<>(); - for (String entry : command.getLabels()) { - // Exclude the proper argument - if (entry.equalsIgnoreCase(usedLabel)) - continue; - alternatives.add(entry); - } - - // Sort the alternatives - Collections.sort(alternatives, new Comparator() { - @Override - public int compare(String o1, String o2) { - return Double.compare(StringUtils.getDifference(usedLabel, o1), StringUtils.getDifference(usedLabel, o2)); - } - }); - - // Print each alternative with proper syntax - for (String alternative : alternatives) - sender.sendMessage(" " + HelpSyntaxHelper.getCommandSyntax(command, commandReference, alternative, true)); - } - - /** - * Print the command help child's information if available. - * - * @param sender The command sender to print the help to. - * @param command The command to print the help for. - * @param commandReference The original command reference used for this command. - */ - public static void printChildren(CommandSender sender, CommandDescription command, CommandParts commandReference) { - // Make sure there are child's - if (command.getChildren().size() <= 0) - return; - - // Print the header - sender.sendMessage(ChatColor.GOLD + "Commands:"); - - // Loop through each child - for (CommandDescription child : command.getChildren()) - sender.sendMessage(" " + HelpSyntaxHelper.getCommandSyntax(child, commandReference, null, false) + ChatColor.GRAY + ChatColor.ITALIC + " : " + child.getDescription()); - } -} diff --git a/src/main/java/fr/xephi/authme/command/help/HelpSyntaxHelper.java b/src/main/java/fr/xephi/authme/command/help/HelpSyntaxHelper.java deleted file mode 100644 index cc7a7d6e..00000000 --- a/src/main/java/fr/xephi/authme/command/help/HelpSyntaxHelper.java +++ /dev/null @@ -1,79 +0,0 @@ -package fr.xephi.authme.command.help; - -import fr.xephi.authme.command.CommandArgumentDescription; -import fr.xephi.authme.command.CommandDescription; -import fr.xephi.authme.command.CommandUtils; -import fr.xephi.authme.util.CollectionUtils; -import fr.xephi.authme.util.StringUtils; -import org.bukkit.ChatColor; - -import java.util.List; - -/** - * Helper class for formatting a command's structure (name and arguments) - * for a Minecraft user. - */ -public final class HelpSyntaxHelper { - - private HelpSyntaxHelper() { - // Helper class - } - - /** - * Get the formatted syntax for a command. - * - * @param commandDescription The command to build the syntax for. - * @param commandReference The reference of the command. - * @param alternativeLabel The alternative label to use for this command syntax. - * @param highlight True to highlight the important parts of this command. - * - * @return The command with proper syntax. - */ - public static String getCommandSyntax(CommandDescription commandDescription, CommandParts commandReference, - String alternativeLabel, boolean highlight) { - // Create a string builder with white color and prefixed slash - StringBuilder sb = new StringBuilder() - .append(ChatColor.WHITE) - .append("/"); - - // Get the help command reference, and the command label - CommandParts helpCommandReference = commandDescription.getCommandReference(commandReference); - List helpLabels = helpCommandReference.getList(); - - final String parentCommand = CommandUtils.labelsToString( - CollectionUtils.getRange(helpCommandReference.getList(), 0, helpLabels.size() - 1)); - - // Check whether the alternative label should be used - String commandLabel; - if (StringUtils.isEmpty(alternativeLabel)) { - commandLabel = helpLabels.get(helpLabels.size() - 1); - } else { - commandLabel = alternativeLabel; - } - - // Show the important bit of the command, highlight this part if required - sb.append(parentCommand) - .append(" ") - .append(highlight ? ChatColor.YELLOW.toString() + ChatColor.BOLD : "") - .append(commandLabel); - - if (highlight) { - sb.append(ChatColor.YELLOW); - } - - // Add each command argument - for (CommandArgumentDescription arg : commandDescription.getArguments()) { - sb.append(ChatColor.ITALIC).append(formatArgument(arg)); - } - - // Return the build command syntax - return sb.toString(); - } - - private static String formatArgument(CommandArgumentDescription argument) { - if (argument.isOptional()) { - return " [" + argument.getName() + "]"; - } - return " <" + argument.getName() + ">"; - } -} diff --git a/src/test/java/fr/xephi/authme/command/CommandInitializerTest.java b/src/test/java/fr/xephi/authme/command/CommandInitializerTest.java index e364fb9e..66e77450 100644 --- a/src/test/java/fr/xephi/authme/command/CommandInitializerTest.java +++ b/src/test/java/fr/xephi/authme/command/CommandInitializerTest.java @@ -76,7 +76,7 @@ public class CommandInitializerTest { BiConsumer connectionTester = new BiConsumer() { @Override public void accept(CommandDescription command, int depth) { - if (command.hasChildren()) { + if (!command.getChildren().isEmpty()) { for (CommandDescription child : command.getChildren()) { assertThat(command.equals(child.getParent()), equalTo(true)); } @@ -222,7 +222,7 @@ public class CommandInitializerTest { public void accept(CommandDescription command, int depth) { // Fail if the command has children and has arguments at the same time // Exception: If the parent only has one child defining the help label, it is acceptable - if (command.hasChildren() && command.hasArguments() + if (!command.getChildren().isEmpty() && !command.getArguments().isEmpty() && (command.getChildren().size() != 1 || !command.getChildren().get(0).hasLabel("help"))) { fail("Parent command (labels='" + command.getLabels() + "') should not have any arguments"); } @@ -280,7 +280,7 @@ public class CommandInitializerTest { private static void walkThroughCommands(Collection commands, BiConsumer consumer, int depth) { for (CommandDescription command : commands) { consumer.accept(command, depth); - if (command.hasChildren()) { + if (!command.getChildren().isEmpty()) { walkThroughCommands(command.getChildren(), consumer, depth + 1); } } diff --git a/src/test/java/fr/xephi/authme/command/executable/captcha/CaptchaCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/captcha/CaptchaCommandTest.java index 4a8af38d..d076fd03 100644 --- a/src/test/java/fr/xephi/authme/command/executable/captcha/CaptchaCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/captcha/CaptchaCommandTest.java @@ -14,7 +14,7 @@ import org.junit.Ignore; import org.junit.Test; import org.mockito.Mockito; -import java.util.Collections; +import java.util.ArrayList; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; @@ -41,10 +41,9 @@ public class CaptchaCommandTest { ExecutableCommand command = new CaptchaCommand(); // when - boolean result = command.executeCommand(sender, new CommandParts(Collections.EMPTY_LIST), new CommandParts(Collections.EMPTY_LIST)); + command.executeCommand(sender, new ArrayList()); // then - assertThat(result, equalTo(true)); assertThat(wrapperMock.wasMockCalled(AuthMe.class), equalTo(false)); assertThat(wrapperMock.wasMockCalled(Messages.class), equalTo(false)); } @@ -57,10 +56,9 @@ public class CaptchaCommandTest { ExecutableCommand command = new CaptchaCommand(); // when - boolean result = command.executeCommand(player, new CommandParts(Collections.EMPTY_LIST), new CommandParts(Collections.EMPTY_LIST)); + command.executeCommand(player, new ArrayList()); // then - assertThat(result, equalTo(true)); verify(wrapperMock.getMessages()).send(player, MessageKey.USAGE_LOGIN); } diff --git a/src/test/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommandTest.java index da8f82ce..dd7c1b7a 100644 --- a/src/test/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommandTest.java @@ -16,14 +16,19 @@ import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import static java.util.Arrays.asList; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; /** * Test for {@link ChangePasswordCommand}. @@ -52,13 +57,11 @@ public class ChangePasswordCommandTest { // given CommandSender sender = mock(BlockCommandSender.class); ChangePasswordCommand command = new ChangePasswordCommand(); - CommandParts arguments = mock(CommandParts.class); // when - command.executeCommand(sender, newParts(), arguments); + command.executeCommand(sender, new ArrayList()); // then - verify(arguments, never()).get(anyInt()); assertThat(wrapperMock.wasMockCalled(Server.class), equalTo(false)); } @@ -69,7 +72,7 @@ public class ChangePasswordCommandTest { ChangePasswordCommand command = new ChangePasswordCommand(); // when - command.executeCommand(sender, newParts(), new CommandParts("pass")); + command.executeCommand(sender, Collections.singletonList("pass")); // then verify(messagesMock).send(sender, MessageKey.NOT_LOGGED_IN); @@ -83,7 +86,7 @@ public class ChangePasswordCommandTest { ChangePasswordCommand command = new ChangePasswordCommand(); // when - command.executeCommand(sender, newParts(), newParts("old123", "!pass")); + command.executeCommand(sender, Arrays.asList("old123", "!pass")); // then verify(messagesMock).send(sender, MessageKey.PASSWORD_MATCH_ERROR); @@ -98,7 +101,7 @@ public class ChangePasswordCommandTest { ChangePasswordCommand command = new ChangePasswordCommand(); // when - command.executeCommand(sender, newParts(), newParts("old_", "Tester")); + command.executeCommand(sender, Arrays.asList("old_", "Tester")); // then verify(messagesMock).send(sender, MessageKey.PASSWORD_IS_USERNAME_ERROR); @@ -113,7 +116,7 @@ public class ChangePasswordCommandTest { Settings.passwordMaxLength = 3; // when - command.executeCommand(sender, newParts(), newParts("12", "test")); + command.executeCommand(sender, Arrays.asList("12", "test")); // then verify(messagesMock).send(sender, MessageKey.INVALID_PASSWORD_LENGTH); @@ -128,7 +131,7 @@ public class ChangePasswordCommandTest { Settings.getPasswordMinLen = 7; // when - command.executeCommand(sender, newParts(), newParts("oldverylongpassword", "tester")); + command.executeCommand(sender, Arrays.asList("oldverylongpassword", "tester")); // then verify(messagesMock).send(sender, MessageKey.INVALID_PASSWORD_LENGTH); @@ -143,7 +146,7 @@ public class ChangePasswordCommandTest { Settings.unsafePasswords = asList("test", "abc123"); // when - command.executeCommand(sender, newParts(), newParts("oldpw", "abc123")); + command.executeCommand(sender, Arrays.asList("oldpw", "abc123")); // then verify(messagesMock).send(sender, MessageKey.PASSWORD_UNSAFE_ERROR); @@ -157,7 +160,7 @@ public class ChangePasswordCommandTest { ChangePasswordCommand command = new ChangePasswordCommand(); // when - command.executeCommand(sender, newParts(), newParts("abc123", "abc123")); + command.executeCommand(sender, Arrays.asList("abc123", "abc123")); // then verify(messagesMock, never()).send(eq(sender), any(MessageKey.class)); @@ -175,8 +178,4 @@ public class ChangePasswordCommandTest { return player; } - private static CommandParts newParts(String... parts) { - return new CommandParts(Arrays.asList(parts)); - } - } diff --git a/src/test/java/fr/xephi/authme/command/executable/email/AddEmailCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/email/AddEmailCommandTest.java index 38c7d046..64b09b29 100644 --- a/src/test/java/fr/xephi/authme/command/executable/email/AddEmailCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/email/AddEmailCommandTest.java @@ -11,7 +11,6 @@ import org.junit.Test; import org.mockito.Mockito; import java.util.ArrayList; -import java.util.Arrays; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @@ -40,7 +39,7 @@ public class AddEmailCommandTest { AddEmailCommand command = new AddEmailCommand(); // when - command.executeCommand(sender, newParts(), newParts()); + command.executeCommand(sender, new ArrayList()); // then verify(authMeMock, never()).getManagement(); @@ -53,15 +52,11 @@ public class AddEmailCommandTest { AddEmailCommand command = new AddEmailCommand(); // when - command.executeCommand(sender, newParts(), - new CommandParts(Arrays.asList("mail@example", "other_example"))); + command.executeCommand(sender, new ArrayList()); // then verify(authMeMock).getManagement(); verify(managementMock).performAddEmail(sender, "mail@example", "other_example"); } - private static CommandParts newParts() { - return new CommandParts(new ArrayList()); - } } diff --git a/src/test/java/fr/xephi/authme/command/executable/email/ChangeEmailCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/email/ChangeEmailCommandTest.java index 183f3ad1..f4ecd4f8 100644 --- a/src/test/java/fr/xephi/authme/command/executable/email/ChangeEmailCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/email/ChangeEmailCommandTest.java @@ -40,7 +40,7 @@ public class ChangeEmailCommandTest { ChangeEmailCommand command = new ChangeEmailCommand(); // when - command.executeCommand(sender, newParts(), newParts()); + command.executeCommand(sender, new ArrayList()); // then verify(authMeMock, never()).getManagement(); @@ -53,15 +53,11 @@ public class ChangeEmailCommandTest { ChangeEmailCommand command = new ChangeEmailCommand(); // when - command.executeCommand(sender, newParts(), - new CommandParts(Arrays.asList("new.mail@example.org", "old_mail@example.org"))); + command.executeCommand(sender, Arrays.asList("new.mail@example.org", "old_mail@example.org")); // then verify(authMeMock).getManagement(); verify(managementMock).performChangeEmail(sender, "new.mail@example.org", "old_mail@example.org"); } - private static CommandParts newParts() { - return new CommandParts(new ArrayList()); - } } diff --git a/src/test/java/fr/xephi/authme/command/executable/email/RecoverEmailCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/email/RecoverEmailCommandTest.java index 73711de9..eecfaa67 100644 --- a/src/test/java/fr/xephi/authme/command/executable/email/RecoverEmailCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/email/RecoverEmailCommandTest.java @@ -8,7 +8,7 @@ import org.junit.Ignore; import org.junit.Test; import org.mockito.Mockito; -import java.util.Collections; +import java.util.ArrayList; /** * Test for {@link RecoverEmailCommand}. @@ -28,7 +28,7 @@ public class RecoverEmailCommandTest { RecoverEmailCommand command = new RecoverEmailCommand(); // when - command.executeCommand(sender, new CommandParts(Collections.EMPTY_LIST), new CommandParts(Collections.EMPTY_LIST)); + command.executeCommand(sender, new ArrayList()); // then } diff --git a/src/test/java/fr/xephi/authme/command/executable/login/LoginCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/login/LoginCommandTest.java index 4e6c268d..a4773c57 100644 --- a/src/test/java/fr/xephi/authme/command/executable/login/LoginCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/login/LoginCommandTest.java @@ -11,6 +11,7 @@ import org.junit.Test; import org.mockito.Mockito; import java.util.ArrayList; +import java.util.Collections; import static org.mockito.Matchers.*; import static org.mockito.Mockito.mock; @@ -39,7 +40,7 @@ public class LoginCommandTest { LoginCommand command = new LoginCommand(); // when - command.executeCommand(sender, newParts(), newParts()); + command.executeCommand(sender, new ArrayList()); // then Mockito.verify(managementMock, never()).performLogin(any(Player.class), anyString(), anyBoolean()); @@ -52,7 +53,7 @@ public class LoginCommandTest { LoginCommand command = new LoginCommand(); // when - command.executeCommand(sender, newParts(), new CommandParts("password")); + command.executeCommand(sender, Collections.singletonList("password")); // then Mockito.verify(managementMock).performLogin(eq(sender), eq("password"), eq(false)); @@ -65,15 +66,12 @@ public class LoginCommandTest { LoginCommand command = new LoginCommand(); // when - command.executeCommand(sender, newParts(), newParts()); + command.executeCommand(sender, new ArrayList()); // then // TODO ljacqu 20151121: May make sense to handle null password in LoginCommand instead of forwarding the call String password = null; Mockito.verify(managementMock).performLogin(eq(sender), eq(password), eq(false)); } - - private static CommandParts newParts() { - return new CommandParts(new ArrayList()); - } + } diff --git a/src/test/java/fr/xephi/authme/command/executable/logout/LogoutCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/logout/LogoutCommandTest.java index 82ffd1a7..a5dce4d9 100644 --- a/src/test/java/fr/xephi/authme/command/executable/logout/LogoutCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/logout/LogoutCommandTest.java @@ -12,6 +12,7 @@ import org.junit.Test; import org.mockito.Mockito; import java.util.ArrayList; +import java.util.Collections; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; @@ -41,7 +42,7 @@ public class LogoutCommandTest { LogoutCommand command = new LogoutCommand(); // when - command.executeCommand(sender, new CommandParts(new ArrayList()), new CommandParts(new ArrayList())); + command.executeCommand(sender, new ArrayList()); // then Mockito.verify(managementMock, never()).performLogout(any(Player.class)); @@ -54,7 +55,7 @@ public class LogoutCommandTest { LogoutCommand command = new LogoutCommand(); // when - command.executeCommand(sender, new CommandParts(new ArrayList()), new CommandParts("password")); + command.executeCommand(sender, Collections.singletonList("password")); // then Mockito.verify(managementMock).performLogout(sender); diff --git a/src/test/java/fr/xephi/authme/command/executable/register/RegisterCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/register/RegisterCommandTest.java index cbc12369..b6bc992c 100644 --- a/src/test/java/fr/xephi/authme/command/executable/register/RegisterCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/register/RegisterCommandTest.java @@ -14,6 +14,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mockito; import java.util.ArrayList; +import java.util.Collections; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; @@ -49,7 +50,7 @@ public class RegisterCommandTest { ArgumentCaptor messageCaptor = ArgumentCaptor.forClass(String.class); // when - command.executeCommand(sender, newParts(), newParts()); + command.executeCommand(sender, new ArrayList()); // then verify(sender).sendMessage(messageCaptor.capture()); @@ -64,7 +65,7 @@ public class RegisterCommandTest { RegisterCommand command = new RegisterCommand(); // when - command.executeCommand(sender, newParts(), newParts()); + command.executeCommand(sender, new ArrayList()); // then verify(messagesMock).send(sender, MessageKey.USAGE_REGISTER); @@ -78,13 +79,10 @@ public class RegisterCommandTest { RegisterCommand command = new RegisterCommand(); // when - command.executeCommand(sender, newParts(), new CommandParts("password")); + command.executeCommand(sender, Collections.singletonList("password")); // then verify(managementMock).performRegister(sender, "password", ""); } - private static CommandParts newParts() { - return new CommandParts(new ArrayList()); - } } diff --git a/src/test/java/fr/xephi/authme/command/help/HelpSyntaxHelperTest.java b/src/test/java/fr/xephi/authme/command/help/HelpSyntaxHelperTest.java deleted file mode 100644 index 185bf08b..00000000 --- a/src/test/java/fr/xephi/authme/command/help/HelpSyntaxHelperTest.java +++ /dev/null @@ -1,131 +0,0 @@ -package fr.xephi.authme.command.help; - -import fr.xephi.authme.command.CommandDescription; -import fr.xephi.authme.command.ExecutableCommand; -import fr.xephi.authme.command.executable.authme.RegisterAdminCommand; -import org.junit.Test; -import org.mockito.Mockito; - -import java.util.ArrayList; - -import static org.bukkit.ChatColor.BOLD; -import static org.bukkit.ChatColor.ITALIC; -import static org.bukkit.ChatColor.WHITE; -import static org.bukkit.ChatColor.YELLOW; -import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertThat; - -/** - * Test for {@link HelpSyntaxHelper}. - */ -public class HelpSyntaxHelperTest { - - @Test - public void shouldFormatSimpleCommand() { - // given - CommandDescription description = getDescriptionBuilder() - .withArgument("name", "The name", true) - .build(); - - // when - String result = HelpSyntaxHelper.getCommandSyntax(description, newParts(), "", false); - - // then - assertThat(result, equalTo(WHITE + "/authme register" + ITALIC + " [name]")); - } - - @Test - public void shouldFormatSimpleCommandWithOptionalParam() { - // given - CommandDescription description = getDescriptionBuilder() - .withArgument("test", "", false) - .build(); - - // when - String result = HelpSyntaxHelper.getCommandSyntax(description, newParts(), null, false); - - // then - assertThat(result, equalTo(WHITE + "/authme register" + ITALIC + " ")); - } - - @Test - public void shouldFormatCommandWithMultipleParams() { - // given - CommandDescription description = getDescriptionBuilder() - .withArgument("name", "", true) - .withArgument("test", "", false) - .build(); - - // when - String result = HelpSyntaxHelper.getCommandSyntax(description, newParts(), "", false); - - // then - assertThat(result, equalTo(WHITE + "/authme register" + ITALIC + " [name]" + ITALIC + " ")); - } - - @Test - public void shouldHighlightCommandWithMultipleParams() { - // given - CommandDescription description = getDescriptionBuilder() - .withArgument("name", "", true) - .withArgument("test", "", false) - .build(); - - // when - String result = HelpSyntaxHelper.getCommandSyntax(description, newParts(), "", true); - - // then - assertThat(result, equalTo(WHITE + "/authme " - + YELLOW + BOLD + "register" - + YELLOW + ITALIC + " [name]" + ITALIC + " ")); - } - - @Test - public void shouldHighlightCommandWithNoParams() { - // given - CommandDescription description = getDescriptionBuilder().build(); - - // when - String result = HelpSyntaxHelper.getCommandSyntax(description, newParts(), null, true); - - // then - assertThat(result, equalTo(WHITE + "/authme " + YELLOW + BOLD + "register" + YELLOW)); - } - - @Test - public void shouldFormatSimpleCommandWithAlternativeLabel() { - // given - CommandDescription description = getDescriptionBuilder() - .withArgument("name", "The name", true) - .build(); - - // when - String result = HelpSyntaxHelper.getCommandSyntax(description, newParts(), "alt", false); - - // then - assertThat(result, equalTo(WHITE + "/authme alt" + ITALIC + " [name]")); - } - - private static CommandParts newParts() { - // TODO ljacqu 20151204: Remove this method once CommandParts has been removed - return new CommandParts(new ArrayList()); - } - - private static CommandDescription.CommandBuilder getDescriptionBuilder() { - CommandDescription base = CommandDescription.builder() - .labels("authme") - .description("Base command") - .detailedDescription("AuthMe base command") - .parent(null) - .executableCommand(Mockito.mock(ExecutableCommand.class)) - .build(); - - return CommandDescription.builder() - .executableCommand(Mockito.mock(RegisterAdminCommand.class)) - .labels("register", "r") - .description("Register a player") - .detailedDescription("Register the specified player with the specified password.") - .parent(base) - .executableCommand(Mockito.mock(ExecutableCommand.class)); - } -} From 3e928cddf0ead067260784cd602206f1acac982b Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sun, 13 Dec 2015 10:49:15 +0100 Subject: [PATCH 11/18] CommandInitializer - consistent indent and setter order --- .../authme/command/CommandInitializer.java | 430 +++++++++--------- 1 file changed, 215 insertions(+), 215 deletions(-) diff --git a/src/main/java/fr/xephi/authme/command/CommandInitializer.java b/src/main/java/fr/xephi/authme/command/CommandInitializer.java index b3db5c1c..2866669e 100644 --- a/src/main/java/fr/xephi/authme/command/CommandInitializer.java +++ b/src/main/java/fr/xephi/authme/command/CommandInitializer.java @@ -36,9 +36,10 @@ import fr.xephi.authme.permission.AdminPermission; import fr.xephi.authme.permission.PlayerPermission; import fr.xephi.authme.util.Wrapper; -import java.util.*; +import java.util.Arrays; +import java.util.List; +import java.util.Set; -import static com.google.common.collect.Sets.newHashSet; import static fr.xephi.authme.permission.DefaultPermission.ALLOWED; import static fr.xephi.authme.permission.DefaultPermission.OP_ONLY; @@ -158,128 +159,128 @@ public final class CommandInitializer { .labels("getemail", "getmail", "email", "mail") .description("Display player's email") .detailedDescription("Display the email address of the specified player if set.") - .permissions(OP_ONLY, AdminPermission.GET_EMAIL) .withArgument("player", "Player name", true) + .permissions(OP_ONLY, AdminPermission.GET_EMAIL) .executableCommand(new GetEmailCommand()) .build(); // Register the setemail command CommandDescription.builder() - .executableCommand(new SetEmailCommand()) .parent(AUTHME_BASE) .labels("chgemail", "chgmail", "setemail", "setmail") .description("Change player's email") .detailedDescription("Change the email address of the specified player.") - .permissions(OP_ONLY, AdminPermission.CHANGE_EMAIL) .withArgument("player", "Player name", false) .withArgument("email", "Player email", false) + .permissions(OP_ONLY, AdminPermission.CHANGE_EMAIL) + .executableCommand(new SetEmailCommand()) .build(); // Register the getip command CommandDescription.builder() - .executableCommand(new GetIpCommand()) - .parent(AUTHME_BASE) - .labels("getip", "ip") - .description("Get player's IP") - .detailedDescription("Get the IP address of the specified online player.") - .permissions(OP_ONLY, AdminPermission.GET_IP) - .withArgument("player", "Player Name", false) - .build(); + .parent(AUTHME_BASE) + .labels("getip", "ip") + .description("Get player's IP") + .detailedDescription("Get the IP address of the specified online player.") + .withArgument("player", "Player Name", false) + .permissions(OP_ONLY, AdminPermission.GET_IP) + .executableCommand(new GetIpCommand()) + .build(); // Register the spawn command CommandDescription.builder() - .executableCommand(new SpawnCommand()) - .parent(AUTHME_BASE) - .labels("spawn", "home") - .description("Teleport to spawn") - .detailedDescription("Teleport to the spawn.") - .permissions(OP_ONLY, AdminPermission.SPAWN) - .withArgument("player", "Player Name", false) - .build(); + .parent(AUTHME_BASE) + .labels("spawn", "home") + .description("Teleport to spawn") + .detailedDescription("Teleport to the spawn.") + .withArgument("player", "Player Name", false) + .permissions(OP_ONLY, AdminPermission.SPAWN) + .executableCommand(new SpawnCommand()) + .build(); // Register the setspawn command CommandDescription.builder() - .executableCommand(new SetSpawnCommand()) - .parent(AUTHME_BASE) - .labels("setspawn", "chgspawn") - .description("Change the spawn") - .detailedDescription("Change the player's spawn to your current position.") - .permissions(OP_ONLY, AdminPermission.SET_SPAWN) - .build(); + .parent(AUTHME_BASE) + .labels("setspawn", "chgspawn") + .description("Change the spawn") + .detailedDescription("Change the player's spawn to your current position.") + .permissions(OP_ONLY, AdminPermission.SET_SPAWN) + .executableCommand(new SetSpawnCommand()) + .build(); // Register the firstspawn command CommandDescription.builder() - .executableCommand(new FirstSpawnCommand()) - .parent(AUTHME_BASE) - .labels("firstspawn", "firsthome") - .description("Teleport to first spawn") - .detailedDescription("Teleport to the first spawn.") - .permissions(OP_ONLY, AdminPermission.FIRST_SPAWN) - .build(); + .parent(AUTHME_BASE) + .labels("firstspawn", "firsthome") + .description("Teleport to first spawn") + .detailedDescription("Teleport to the first spawn.") + .permissions(OP_ONLY, AdminPermission.FIRST_SPAWN) + .executableCommand(new FirstSpawnCommand()) + .build(); // Register the setfirstspawn command CommandDescription.builder() - .executableCommand(new SetFirstSpawnCommand()) - .parent(AUTHME_BASE) - .labels("setfirstspawn", "chgfirstspawn") - .description("Change the first spawn") - .detailedDescription("Change the first player's spawn to your current position.") - .permissions(OP_ONLY, AdminPermission.SET_FIRST_SPAWN) - .build(); + .parent(AUTHME_BASE) + .labels("setfirstspawn", "chgfirstspawn") + .description("Change the first spawn") + .detailedDescription("Change the first player's spawn to your current position.") + .permissions(OP_ONLY, AdminPermission.SET_FIRST_SPAWN) + .executableCommand(new SetFirstSpawnCommand()) + .build(); // Register the purge command CommandDescription.builder() - .executableCommand(new PurgeCommand()) - .parent(AUTHME_BASE) - .labels("purge", "delete") - .description("Purge old data") - .detailedDescription("Purge old AuthMeReloaded data longer than the specified amount of days ago.") - .permissions(OP_ONLY, AdminPermission.PURGE) - .withArgument("days", "Number of days", false) - .build(); + .parent(AUTHME_BASE) + .labels("purge", "delete") + .description("Purge old data") + .detailedDescription("Purge old AuthMeReloaded data longer than the specified amount of days ago.") + .withArgument("days", "Number of days", false) + .permissions(OP_ONLY, AdminPermission.PURGE) + .executableCommand(new PurgeCommand()) + .build(); // Register the purgelastposition command CommandDescription.builder() - .executableCommand(new PurgeLastPositionCommand()) - .parent(AUTHME_BASE) - .labels("resetpos", "purgelastposition", "purgelastpos", "resetposition", - "resetlastposition", "resetlastpos") - .description("Purge player's last position") - .detailedDescription("Purge the last know position of the specified player.") - .permissions(OP_ONLY, AdminPermission.PURGE_LAST_POSITION) - .withArgument("player", "Player name", false) - .build(); + .parent(AUTHME_BASE) + .labels("resetpos", "purgelastposition", "purgelastpos", "resetposition", + "resetlastposition", "resetlastpos") + .description("Purge player's last position") + .detailedDescription("Purge the last know position of the specified player.") + .withArgument("player", "Player name", false) + .permissions(OP_ONLY, AdminPermission.PURGE_LAST_POSITION) + .executableCommand(new PurgeLastPositionCommand()) + .build(); // Register the purgebannedplayers command CommandDescription.builder() - .executableCommand(new PurgeBannedPlayersCommand()) - .parent(AUTHME_BASE) - .labels("purgebannedplayers", "purgebannedplayer", "deletebannedplayers", "deletebannedplayer") - .description("Purge banned players data") - .detailedDescription("Purge all AuthMeReloaded data for banned players.") - .permissions(OP_ONLY, AdminPermission.PURGE_BANNED_PLAYERS) - .build(); + .parent(AUTHME_BASE) + .labels("purgebannedplayers", "purgebannedplayer", "deletebannedplayers", "deletebannedplayer") + .description("Purge banned players data") + .detailedDescription("Purge all AuthMeReloaded data for banned players.") + .permissions(OP_ONLY, AdminPermission.PURGE_BANNED_PLAYERS) + .executableCommand(new PurgeBannedPlayersCommand()) + .build(); // Register the switchantibot command CommandDescription.builder() - .executableCommand(new SwitchAntiBotCommand()) - .parent(AUTHME_BASE) - .labels("switchantibot", "toggleantibot", "antibot") - .description("Switch AntiBot mode") - .detailedDescription("Switch or toggle the AntiBot mode to the specified state.") - .permissions(OP_ONLY, AdminPermission.SWITCH_ANTIBOT) - .withArgument("mode", "ON / OFF", true) - .build(); + .parent(AUTHME_BASE) + .labels("switchantibot", "toggleantibot", "antibot") + .description("Switch AntiBot mode") + .detailedDescription("Switch or toggle the AntiBot mode to the specified state.") + .withArgument("mode", "ON / OFF", true) + .permissions(OP_ONLY, AdminPermission.SWITCH_ANTIBOT) + .executableCommand(new SwitchAntiBotCommand()) + .build(); // Register the reload command CommandDescription.builder() - .executableCommand(new ReloadCommand()) - .parent(AUTHME_BASE) - .labels("reload", "rld") - .description("Reload plugin") - .detailedDescription("Reload the AuthMeReloaded plugin.") - .permissions(OP_ONLY, AdminPermission.RELOAD) - .build(); + .parent(AUTHME_BASE) + .labels("reload", "rld") + .description("Reload plugin") + .detailedDescription("Reload the AuthMeReloaded plugin.") + .permissions(OP_ONLY, AdminPermission.RELOAD) + .executableCommand(new ReloadCommand()) + .build(); // Register the version command CommandDescription.builder() @@ -293,44 +294,44 @@ public final class CommandInitializer { // Register the base login command final CommandDescription LOGIN_BASE = CommandDescription.builder() - .executableCommand(new LoginCommand()) + .parent(null) .labels("login", "l") .description("Login command") .detailedDescription("Command to log in using AuthMeReloaded.") - .parent(null) - .permissions(ALLOWED, PlayerPermission.LOGIN) .withArgument("password", "Login password", false) + .permissions(ALLOWED, PlayerPermission.LOGIN) + .executableCommand(new LoginCommand()) .build(); // Register the help command CommandDescription.builder() - .executableCommand(helpCommandExecutable) - .parent(LOGIN_BASE) - .labels(helpCommandLabels) - .description("View Help") - .detailedDescription("View detailed help pages about AuthMeReloaded login commands.") - .withArgument("query", "The command or query to view help for.", true) - .build(); + .parent(LOGIN_BASE) + .labels(helpCommandLabels) + .description("View Help") + .detailedDescription("View detailed help pages about AuthMeReloaded login commands.") + .withArgument("query", "The command or query to view help for.", true) + .executableCommand(helpCommandExecutable) + .build(); // Register the base logout command CommandDescription LOGOUT_BASE = CommandDescription.builder() - .executableCommand(new LogoutCommand()) - .parent(null) - .labels("logout") - .description("Logout command") - .detailedDescription("Command to logout using AuthMeReloaded.") - .permissions(ALLOWED, PlayerPermission.LOGOUT) - .build(); + .parent(null) + .labels("logout") + .description("Logout command") + .detailedDescription("Command to logout using AuthMeReloaded.") + .permissions(ALLOWED, PlayerPermission.LOGOUT) + .executableCommand(new LogoutCommand()) + .build(); // Register the help command CommandDescription.builder() - .executableCommand(helpCommandExecutable) - .parent(LOGOUT_BASE) - .labels(helpCommandLabels) - .description("View help") - .detailedDescription("View detailed help pages about AuthMeReloaded logout commands.") - .withArgument("query", "The command or query to view help for.", true) - .build(); + .parent(LOGOUT_BASE) + .labels(helpCommandLabels) + .description("View help") + .detailedDescription("View detailed help pages about AuthMeReloaded logout commands.") + .withArgument("query", "The command or query to view help for.", true) + .executableCommand(helpCommandExecutable) + .build(); // Register the base register command final CommandDescription REGISTER_BASE = CommandDescription.builder() @@ -346,155 +347,154 @@ public final class CommandInitializer { // Register the help command CommandDescription.builder() - .executableCommand(helpCommandExecutable) - .parent(REGISTER_BASE) - .labels(helpCommandLabels) - .description("View help") - .detailedDescription("View detailed help pages about AuthMeReloaded register commands.") - .withArgument("query", "The command or query to view help for.", true) - .build(); + .parent(REGISTER_BASE) + .labels(helpCommandLabels) + .description("View help") + .detailedDescription("View detailed help pages about AuthMeReloaded register commands.") + .withArgument("query", "The command or query to view help for.", true) + .executableCommand(helpCommandExecutable) + .build(); // Register the base unregister command CommandDescription UNREGISTER_BASE = CommandDescription.builder() - .executableCommand(new UnregisterCommand()) - .parent(null) - .labels("unreg", "unregister") - .description("Unregistration Command") - .detailedDescription("Command to unregister using AuthMeReloaded.") - .permissions(ALLOWED, PlayerPermission.UNREGISTER) - .withArgument("password", "Password", false) - .build(); + .parent(null) + .labels("unreg", "unregister") + .description("Unregistration Command") + .detailedDescription("Command to unregister using AuthMeReloaded.") + .withArgument("password", "Password", false) + .permissions(ALLOWED, PlayerPermission.UNREGISTER) + .executableCommand(new UnregisterCommand()) + .build(); // Register the help command CommandDescription.builder() - .executableCommand(helpCommandExecutable) - .parent(UNREGISTER_BASE) - .labels(helpCommandLabels) - .description("View help") - .detailedDescription("View detailed help pages about AuthMeReloaded unregister commands.") - .withArgument("query", "The command or query to view help for.", true) - .build(); + .parent(UNREGISTER_BASE) + .labels(helpCommandLabels) + .description("View help") + .detailedDescription("View detailed help pages about AuthMeReloaded unregister commands.") + .withArgument("query", "The command or query to view help for.", true) + .executableCommand(helpCommandExecutable) + .build(); // Register the base changepassword command final CommandDescription CHANGE_PASSWORD_BASE = CommandDescription.builder() - .executableCommand(new ChangePasswordCommand()) - .parent(null) - .labels("changepassword", "changepass", "cp") - .description("Change password Command") - .detailedDescription("Command to change your password using AuthMeReloaded.") - .permissions(ALLOWED, PlayerPermission.CHANGE_PASSWORD) - .withArgument("password", "Password", false) - .withArgument("verifyPassword", "Verify password.", false) - .build(); + .parent(null) + .labels("changepassword", "changepass", "cp") + .description("Change password Command") + .detailedDescription("Command to change your password using AuthMeReloaded.") + .withArgument("password", "Password", false) + .withArgument("verifyPassword", "Verify password.", false) + .permissions(ALLOWED, PlayerPermission.CHANGE_PASSWORD) + .executableCommand(new ChangePasswordCommand()) + .build(); // Register the help command CommandDescription.builder() - .executableCommand(helpCommandExecutable) - .parent(CHANGE_PASSWORD_BASE) - .labels(helpCommandLabels) - .description("View help") - .detailedDescription("View detailed help pages about AuthMeReloaded changepassword commands.") - .withArgument("query", "The command or query to view help for.", true) - .build(); + .parent(CHANGE_PASSWORD_BASE) + .labels(helpCommandLabels) + .description("View help") + .detailedDescription("View detailed help pages about AuthMeReloaded changepassword commands.") + .withArgument("query", "The command or query to view help for.", true) + .executableCommand(helpCommandExecutable) + .build(); // Register the base Email command CommandDescription EMAIL_BASE = CommandDescription.builder() - .executableCommand(helpCommandExecutable) - .parent(null) - .labels("email", "mail") - .description("Email command") - .detailedDescription("The AuthMeReloaded Email command base.") - .build(); + .parent(null) + .labels("email", "mail") + .description("Email command") + .detailedDescription("The AuthMeReloaded Email command base.") + .executableCommand(helpCommandExecutable) + .build(); // Register the help command CommandDescription.builder() - .executableCommand(helpCommandExecutable) - .parent(EMAIL_BASE) - .labels(helpCommandLabels) - .description("View help") - .detailedDescription("View detailed help pages about AuthMeReloaded email commands.") - .withArgument("query", "The command or query to view help for.", true) - .build(); + .parent(EMAIL_BASE) + .labels(helpCommandLabels) + .description("View help") + .detailedDescription("View detailed help pages about AuthMeReloaded email commands.") + .withArgument("query", "The command or query to view help for.", true) + .executableCommand(helpCommandExecutable) + .build(); // Register the add command CommandDescription.builder() - .executableCommand(new AddEmailCommand()) - .parent(EMAIL_BASE) - .labels("add", "addemail", "addmail") - .description("Add Email") - .detailedDescription("Add a new email address to your account.") - .permissions(ALLOWED, PlayerPermission.ADD_EMAIL) - .withArgument("email", "Email address", false) - .withArgument("verifyEmail", "Email address verification", false) - .build(); + .parent(EMAIL_BASE) + .labels("add", "addemail", "addmail") + .description("Add Email") + .detailedDescription("Add a new email address to your account.") + .withArgument("email", "Email address", false) + .withArgument("verifyEmail", "Email address verification", false) + .permissions(ALLOWED, PlayerPermission.ADD_EMAIL) + .executableCommand(new AddEmailCommand()) + .build(); // Register the change command CommandDescription.builder() - .executableCommand(new ChangeEmailCommand()) - .parent(EMAIL_BASE) - .labels("change", "changeemail", "changemail") - .description("Change Email") - .detailedDescription("Change an email address of your account.") - .permissions(ALLOWED, PlayerPermission.CHANGE_EMAIL) - .withArgument("oldEmail", "Old email address", false) - .withArgument("newEmail", "New email address", false) - .build(); - + .parent(EMAIL_BASE) + .labels("change", "changeemail", "changemail") + .description("Change Email") + .detailedDescription("Change an email address of your account.") + .withArgument("oldEmail", "Old email address", false) + .withArgument("newEmail", "New email address", false) + .permissions(ALLOWED, PlayerPermission.CHANGE_EMAIL) + .executableCommand(new ChangeEmailCommand()) + .build(); // Register the recover command CommandDescription.builder() - .executableCommand(new RecoverEmailCommand()) - .parent(EMAIL_BASE) - .labels("recover", "recovery", "recoveremail", "recovermail") - .description("Recover password using Email") - .detailedDescription("Recover your account using an Email address by sending a mail containing " + - "a new password.") - .permissions(ALLOWED, PlayerPermission.RECOVER_EMAIL) - .withArgument("email", "Email address", false) - .build(); + .parent(EMAIL_BASE) + .labels("recover", "recovery", "recoveremail", "recovermail") + .description("Recover password using Email") + .detailedDescription("Recover your account using an Email address by sending a mail containing " + + "a new password.") + .withArgument("email", "Email address", false) + .permissions(ALLOWED, PlayerPermission.RECOVER_EMAIL) + .executableCommand(new RecoverEmailCommand()) + .build(); // Register the base captcha command CommandDescription CAPTCHA_BASE = CommandDescription.builder() - .executableCommand(new CaptchaCommand()) - .parent(null) - .labels("captcha", "capt") - .description("Captcha Command") - .detailedDescription("Captcha command for AuthMeReloaded.") - .permissions(ALLOWED, PlayerPermission.CAPTCHA) - .withArgument("captcha", "The Captcha", false) - .build(); + .parent(null) + .labels("captcha", "capt") + .description("Captcha Command") + .detailedDescription("Captcha command for AuthMeReloaded.") + .withArgument("captcha", "The Captcha", false) + .permissions(ALLOWED, PlayerPermission.CAPTCHA) + .executableCommand(new CaptchaCommand()) + .build(); // Register the help command CommandDescription.builder() - .executableCommand(helpCommandExecutable) - .parent(CAPTCHA_BASE) - .labels(helpCommandLabels) - .description("View help") - .detailedDescription("View detailed help pages about AuthMeReloaded captcha commands.") - .withArgument("query", "The command or query to view help for.", true) - .build(); + .parent(CAPTCHA_BASE) + .labels(helpCommandLabels) + .description("View help") + .detailedDescription("View detailed help pages about AuthMeReloaded captcha commands.") + .withArgument("query", "The command or query to view help for.", true) + .executableCommand(helpCommandExecutable) + .build(); // Register the base converter command CommandDescription CONVERTER_BASE = CommandDescription.builder() - .executableCommand(new ConverterCommand()) - .parent(null) - .labels("converter", "convert", "conv") - .description("Converter Command") - .detailedDescription("Converter command for AuthMeReloaded.") - .permissions(OP_ONLY, AdminPermission.CONVERTER) - .withArgument("job", "Conversion job: flattosql / flattosqlite /| xauth / crazylogin / rakamak / " + - "royalauth / vauth / sqltoflat", false) - .build(); + .parent(null) + .labels("converter", "convert", "conv") + .description("Converter Command") + .detailedDescription("Converter command for AuthMeReloaded.") + .withArgument("job", "Conversion job: flattosql / flattosqlite /| xauth / crazylogin / rakamak / " + + "royalauth / vauth / sqltoflat", false) + .permissions(OP_ONLY, AdminPermission.CONVERTER) + .executableCommand(new ConverterCommand()) + .build(); // Register the help command CommandDescription.builder() - .executableCommand(helpCommandExecutable) - .parent(CONVERTER_BASE) - .labels(helpCommandLabels) - .description("View help") - .detailedDescription("View detailed help pages about AuthMeReloaded converter commands.") - .withArgument("query", "The command or query to view help for.", true) - .build(); + .parent(CONVERTER_BASE) + .labels(helpCommandLabels) + .description("View help") + .detailedDescription("View detailed help pages about AuthMeReloaded converter commands.") + .withArgument("query", "The command or query to view help for.", true) + .executableCommand(helpCommandExecutable) + .build(); // Add the base commands to the commands array baseCommands = ImmutableSet.of( From cbf0996197782d8f5ca98462b3158610b648cd74 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Thu, 17 Dec 2015 22:23:43 +0100 Subject: [PATCH 12/18] Logic for FoundCommandResult.Status / Add tests for CommandHandler - Fix other tests - Add logic for smaller pending FIXME's --- src/main/java/fr/xephi/authme/AuthMe.java | 7 - .../authme/command/CommandDescription.java | 1 + .../xephi/authme/command/CommandHandler.java | 57 ++++++--- .../authme/command/FoundCommandResult.java | 24 +--- .../authme/command/help/HelpProvider.java | 57 +++++---- .../authme/command/CommandHandlerTest.java | 121 ++++++++++-------- .../ChangePasswordCommandTest.java | 2 +- .../executable/email/AddEmailCommandTest.java | 3 +- .../executable/login/LoginCommandTest.java | 15 --- 9 files changed, 154 insertions(+), 133 deletions(-) diff --git a/src/main/java/fr/xephi/authme/AuthMe.java b/src/main/java/fr/xephi/authme/AuthMe.java index 162c1405..639a1f3a 100644 --- a/src/main/java/fr/xephi/authme/AuthMe.java +++ b/src/main/java/fr/xephi/authme/AuthMe.java @@ -440,13 +440,6 @@ public class AuthMe extends JavaPlugin { new API(this); } - /** - * Set up the command handler. - */ - private void setupCommandHandler(PermissionsManager permissionsManager) { - this.commandHandler = new CommandHandler(CommandInitializer.getBaseCommands(), permissionsManager); - } - /** * Load the plugin's settings. * diff --git a/src/main/java/fr/xephi/authme/command/CommandDescription.java b/src/main/java/fr/xephi/authme/command/CommandDescription.java index 6903916d..6e69c765 100644 --- a/src/main/java/fr/xephi/authme/command/CommandDescription.java +++ b/src/main/java/fr/xephi/authme/command/CommandDescription.java @@ -150,6 +150,7 @@ public class CommandDescription { * * @return The number of parents, e.g. for "/authme abc def" the parent count is 2 ("/authme abc", "/authme") */ + // TODO ljacqu 20151217: If we always use `getParentCount() + 1` rewrite this method to a `getLabelCount()` public int getParentCount() { if (parent == null) { return 0; diff --git a/src/main/java/fr/xephi/authme/command/CommandHandler.java b/src/main/java/fr/xephi/authme/command/CommandHandler.java index bf97d173..1222eeb0 100644 --- a/src/main/java/fr/xephi/authme/command/CommandHandler.java +++ b/src/main/java/fr/xephi/authme/command/CommandHandler.java @@ -12,6 +12,10 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; +import static fr.xephi.authme.command.FoundCommandResult.ResultStatus.INCORRECT_ARGUMENTS; +import static fr.xephi.authme.command.FoundCommandResult.ResultStatus.MISSING_BASE_COMMAND; +import static fr.xephi.authme.command.FoundCommandResult.ResultStatus.UNKNOWN_LABEL; + /** * The AuthMe command handler, responsible for mapping incoming commands to the correct {@link CommandDescription} * or to display help messages for unknown invocations. @@ -41,7 +45,7 @@ public class CommandHandler { * Map a command that was invoked to the proper {@link CommandDescription} or return a useful error * message upon failure. * - * @param sender The command sender (Bukkit). + * @param sender The command sender. * @param bukkitCommandLabel The command label (Bukkit). * @param bukkitArgs The command arguments (Bukkit). * @@ -74,6 +78,13 @@ public class CommandHandler { return true; } + /** + * Check a command's permissions and execute it with the given arguments if the check succeeds. + * + * @param sender The command sender + * @param command The command to process + * @param arguments The arguments to pass to the command + */ private void executeCommandIfAllowed(CommandSender sender, CommandDescription command, List arguments) { if (permissionsManager.hasPermission(sender, command)) { command.getExecutableCommand().executeCommand(sender, arguments); @@ -112,7 +123,7 @@ public class CommandHandler { if (result.getDifference() < SUGGEST_COMMAND_THRESHOLD && result.getCommandDescription() != null) { sender.sendMessage(ChatColor.YELLOW + "Did you mean " + ChatColor.GOLD + "/" + result.getCommandDescription() + ChatColor.YELLOW + "?"); - // TODO: Define a proper string representation of command description + // FIXME: Define a proper string representation of command description } sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/" + result.getLabels().get(0) @@ -144,14 +155,20 @@ public class CommandHandler { sender.sendMessage(ChatColor.DARK_RED + "You don't have permission to use this command!"); } + /** + * Map incoming command parts to a command. This processes all parts and distinguishes the labels from arguments. + * + * @param parts The parts to map to commands and arguments + * @return The generated {@link FoundCommandResult} + */ public FoundCommandResult mapPartsToCommand(final List parts) { if (CollectionUtils.isEmpty(parts)) { - return new FoundCommandResult(null, parts, null, 0.0, FoundCommandResult.ResultStatus.MISSING_BASE_COMMAND); + return new FoundCommandResult(null, parts, null, 0.0, MISSING_BASE_COMMAND); } CommandDescription base = getBaseCommand(parts.get(0)); if (base == null) { - return new FoundCommandResult(null, parts, null, 0.0, FoundCommandResult.ResultStatus.MISSING_BASE_COMMAND); + return new FoundCommandResult(null, parts, null, 0.0, MISSING_BASE_COMMAND); } // Prefer labels: /register help goes to "Help command", not "Register command" with argument 'help' @@ -167,21 +184,31 @@ public class CommandHandler { } private FoundCommandResult getCommandWithSmallestDifference(CommandDescription base, List parts) { - final String label = parts.get(0); - + final String childLabel = parts.size() >= 2 ? parts.get(1) : null; double minDifference = Double.POSITIVE_INFINITY; CommandDescription closestCommand = null; - for (CommandDescription child : base.getChildren()) { - double difference = getLabelDifference(child, label); - if (difference < minDifference) { - minDifference = difference; - closestCommand = child; + + if (childLabel != null) { + for (CommandDescription child : base.getChildren()) { + double difference = getLabelDifference(child, childLabel); + if (difference < minDifference) { + minDifference = difference; + closestCommand = child; + } } } - // FIXME: Return the full list of labels and arguments - // FIXME: Return INVALID_ARGUMENTS instead of UNKNOWN_LABEL when more accurate - return new FoundCommandResult( - closestCommand, null, null, minDifference, FoundCommandResult.ResultStatus.UNKNOWN_LABEL); + + // base command may have no children or no child label was present + if (closestCommand == null) { + return new FoundCommandResult(null, null, parts, minDifference, UNKNOWN_LABEL); + } + + FoundCommandResult.ResultStatus status = (minDifference == 0.0) ? INCORRECT_ARGUMENTS : UNKNOWN_LABEL; + final int partsSize = parts.size(); + List labels = parts.subList(0, Math.min(closestCommand.getParentCount() + 1, partsSize)); + List arguments = parts.subList(Math.min(partsSize - 1, labels.size()), partsSize); + + return new FoundCommandResult(closestCommand, labels, arguments, minDifference, status); } private CommandDescription getBaseCommand(String label) { diff --git a/src/main/java/fr/xephi/authme/command/FoundCommandResult.java b/src/main/java/fr/xephi/authme/command/FoundCommandResult.java index e35a3f25..99361d76 100644 --- a/src/main/java/fr/xephi/authme/command/FoundCommandResult.java +++ b/src/main/java/fr/xephi/authme/command/FoundCommandResult.java @@ -10,9 +10,11 @@ import java.util.List; *
    *
  • {@link ResultStatus#SUCCESS} entails that mapping the input to a command was successful. Therefore, * the command description, labels and arguments are set. The difference is 0.0.
  • - *
  • {@link ResultStatus#INCORRECT_ARGUMENTS}
  • - *
  • {@link ResultStatus#UNKNOWN_LABEL}
  • - *
  • {@link ResultStatus#MISSING_BASE_COMMAND} should never occur. Any other fields may not be present and any + *
  • {@link ResultStatus#INCORRECT_ARGUMENTS}: The received parts could be mapped to a command but the argument + * count doesn't match. Guarantees that the command description field is not null; difference is 0.0
  • + *
  • {@link ResultStatus#UNKNOWN_LABEL}: The labels could not be mapped to a command. The command description may + * be set to the most similar command, or it may be null. Difference is above 0.0.
  • + *
  • {@link ResultStatus#MISSING_BASE_COMMAND} should never occur. All other fields may be null and any further * processing of the object should be aborted.
  • *
*/ @@ -56,30 +58,14 @@ public class FoundCommandResult { this(commandDescription, arguments, labels, 0.0, ResultStatus.SUCCESS); } - /** - * Get the command description. - * - * @return Command description. - */ public CommandDescription getCommandDescription() { return this.commandDescription; } - - /** - * Get the command arguments. - * - * @return The command arguments. - */ public List getArguments() { return this.arguments; } - /** - * Get the original query reference. - * - * @return Original query reference. - */ public List getLabels() { return this.labels; } diff --git a/src/main/java/fr/xephi/authme/command/help/HelpProvider.java b/src/main/java/fr/xephi/authme/command/help/HelpProvider.java index 97556ab3..151f3e1b 100644 --- a/src/main/java/fr/xephi/authme/command/help/HelpProvider.java +++ b/src/main/java/fr/xephi/authme/command/help/HelpProvider.java @@ -1,6 +1,7 @@ package fr.xephi.authme.command.help; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; import fr.xephi.authme.command.CommandArgumentDescription; import fr.xephi.authme.command.CommandDescription; import fr.xephi.authme.command.CommandPermissions; @@ -62,12 +63,11 @@ public final class HelpProvider { lines.add(ChatColor.GOLD + "==========[ " + Settings.helpHeader + " HELP ]=========="); CommandDescription command = foundCommand.getCommandDescription(); - // TODO ljacqu 20151212: Remove immutability once class is stable. We don't want mutability but the overhead - // isn't worth it either. This is just a temporary safeguard during development List labels = ImmutableList.copyOf(foundCommand.getLabels()); + List correctLabels = ImmutableList.copyOf(filterCorrectLabels(command, labels)); if (!hasFlag(HIDE_COMMAND, options)) { - printCommand(command, labels, lines); // FIXME: Pass `correctLabels` and not `labels` + printCommand(command, correctLabels, lines); } if (hasFlag(SHOW_LONG_DESCRIPTION, options)) { printDetailedDescription(command, lines); @@ -79,7 +79,7 @@ public final class HelpProvider { printPermissions(command, sender, permissionsManager, lines); } if (hasFlag(SHOW_ALTERNATIVES, options)) { - printAlternatives(command, labels, lines); + printAlternatives(command, correctLabels, lines); } if (hasFlag(SHOW_CHILDREN, options)) { printChildren(command, labels, lines); @@ -89,19 +89,8 @@ public final class HelpProvider { } private static void printCommand(CommandDescription command, List correctLabels, List lines) { - // Ensure that we have all labels to go to the command - int requiredLabels = command.getParentCount() + 1; - List givenLabels = new ArrayList<>(correctLabels); - // Only case this is possible: givenLabels.size() == 1 && requiredLabels == 2, - // since command.getParentCount() never exceeds 1 in AuthMe - // FIXME: Might be smart to put this logic outside and to pass it as `correctLabels`? We will need this at a few - // places annotated with a FIXME - if (givenLabels.size() < requiredLabels) { - givenLabels.add(command.getLabels().get(0)); - } - // FIXME: Create highlight logic to mark arguments and the 2nd label as yellow - String syntaxLine = "/" + CommandUtils.labelsToString(givenLabels); + String syntaxLine = "/" + CommandUtils.labelsToString(correctLabels); for (CommandArgumentDescription argument : command.getArguments()) { syntaxLine += " " + formatArgument(argument); } @@ -132,19 +121,14 @@ public final class HelpProvider { } } - // FIXME: labels is currently assumed to be only the ones leading to the given command, but we have scenarios where - // we're guessing the command, so the final label isn't any existing one - private static void printAlternatives(CommandDescription command, List labels, List lines) { + private static void printAlternatives(CommandDescription command, List correctLabels, List lines) { if (command.getLabels().size() <= 1) { return; } - // Print the header lines.add(ChatColor.GOLD + "Alternatives:"); - // Get the label used - // fixme this is not correct if help is triggered by incorrect number of arguments - final String usedLabel = labels.get(labels.size() - 1); + final String usedLabel = correctLabels.get(correctLabels.size() - 1); // Create a list of alternatives List alternatives = new ArrayList<>(); @@ -169,11 +153,11 @@ public final class HelpProvider { for (String alternative : alternatives) { // fixme add highlight functionality (see commented old line) // sender.sendMessage(" " + _HelpSyntaxHelper.getCommandSyntax(command, commandReference, alternative, true)); - lines.add(" " + CommandUtils.labelsToString(labels) + " " + alternative); + lines.add(" " + CommandUtils.labelsToString(correctLabels) + " " + alternative); } } - public static void printPermissions(CommandDescription command, CommandSender sender, + private static void printPermissions(CommandDescription command, CommandSender sender, PermissionsManager permissionsManager, List lines) { CommandPermissions permissions = command.getCommandPermissions(); if (permissions == null || CollectionUtils.isEmpty(permissions.getPermissionNodes())) { @@ -220,6 +204,7 @@ public final class HelpProvider { } } + /** Format a command argument with the proper type of brackets. */ private static String formatArgument(CommandArgumentDescription argument) { if (argument.isOptional()) { return " [" + argument.getName() + "]"; @@ -231,4 +216,26 @@ public final class HelpProvider { return (flag & options) != 0; } + private static List filterCorrectLabels(CommandDescription command, List labels) { + List commands = new ArrayList<>(command.getParentCount() + 1); + CommandDescription currentCommand = command; + while (currentCommand != null) { + commands.add(command); + currentCommand = currentCommand.getParent(); + } + commands = Lists.reverse(commands); + + List correctLabels = new ArrayList<>(); + boolean foundIncorrectLabel = false; + for (int i = 0; i < commands.size(); ++i) { + if (!foundIncorrectLabel && i < labels.size() && commands.get(i).hasLabel(labels.get(i))) { + correctLabels.add(labels.get(i)); + } else { + foundIncorrectLabel = true; + correctLabels.add(commands.get(i).getLabels().get(0)); + } + } + return correctLabels; + } + } diff --git a/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java b/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java index e64ad84d..31810210 100644 --- a/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java +++ b/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java @@ -3,14 +3,10 @@ package fr.xephi.authme.command; import fr.xephi.authme.permission.DefaultPermission; import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.permission.PlayerPermission; -import fr.xephi.authme.util.WrapperMock; -import org.bukkit.command.CommandSender; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; +import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; @@ -19,15 +15,11 @@ import java.util.Set; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.stringContainsInOrder; -import static org.mockito.BDDMockito.given; -import static org.mockito.Matchers.anyListOf; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.nullValue; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; /** * Test for {@link CommandHandler}. @@ -40,8 +32,6 @@ public class CommandHandlerTest { @BeforeClass public static void setUpCommandHandler() { - WrapperMock.createInstance(); - CommandDescription authMeBase = createCommand(null, null, singletonList("authme")); createCommand(PlayerPermission.LOGIN, authMeBase, singletonList("login"), newArgument("password", false)); createCommand(PlayerPermission.LOGIN, authMeBase, asList("register", "reg"), @@ -54,48 +44,89 @@ public class CommandHandlerTest { } @Test - @Ignore - public void shouldForwardCommandToExecutable() { + public void shouldMapPartsToLoginChildCommand() { // given - CommandSender sender = Mockito.mock(CommandSender.class); - given(sender.isOp()).willReturn(true); - String bukkitLabel = "authme"; - String[] args = {"login", "password"}; + List parts = Arrays.asList("authme", "login", "test1"); // when - handler.processCommand(sender, bukkitLabel, args); + FoundCommandResult result = handler.mapPartsToCommand(parts); // then - final CommandDescription loginCmd = getChildWithLabel("login", getCommandWithLabel("authme", commands)); - verify(sender, never()).sendMessage(anyString()); - verify(loginCmd.getExecutableCommand()).executeCommand(eq(sender), anyListOf(String.class)); + assertThat(result.getCommandDescription(), equalTo(getChildWithLabel("login", "authme"))); + assertThat(result.getResultStatus(), equalTo(FoundCommandResult.ResultStatus.SUCCESS)); + assertThat(result.getArguments(), contains("test1")); + assertThat(result.getDifference(), equalTo(0.0)); } @Test - @Ignore // TODO ljacqu Fix test --> command classes too tightly coupled at the moment - public void shouldRejectCommandWithTooManyArguments() { + public void shouldMapPartsToCommandWithNoCaseSensitivity() { // given - CommandSender sender = Mockito.mock(CommandSender.class); - given(sender.isOp()).willReturn(true); - String bukkitLabel = "authme"; - String[] args = {"login", "password", "__unneededArgument__"}; + List parts = Arrays.asList("Authme", "REG", "arg1", "arg2"); // when - boolean result = handler.processCommand(sender, bukkitLabel, args); + FoundCommandResult result = handler.mapPartsToCommand(parts); // then - assertThat(result, equalTo(true)); - assertSenderGotMessageContaining("help", sender); + assertThat(result.getCommandDescription(), equalTo(getChildWithLabel("register", "authme"))); + assertThat(result.getResultStatus(), equalTo(FoundCommandResult.ResultStatus.SUCCESS)); + assertThat(result.getArguments(), contains("arg1", "arg2")); + assertThat(result.getDifference(), equalTo(0.0)); } + @Test + public void shouldRejectCommandWithTooManyArguments() { + // given + List parts = Arrays.asList("authme", "register", "pass123", "pass123", "pass123"); + + // when + FoundCommandResult result = handler.mapPartsToCommand(parts); + + // then + assertThat(result.getCommandDescription(), equalTo(getChildWithLabel("register", "authme"))); + assertThat(result.getResultStatus(), equalTo(FoundCommandResult.ResultStatus.INCORRECT_ARGUMENTS)); + assertThat(result.getDifference(), equalTo(0.0)); + } + + @Test + public void shouldSuggestCommandWithSimilarLabel() { + // given + List parts = Arrays.asList("authme", "reh", "pass123", "pass123"); + + // when + FoundCommandResult result = handler.mapPartsToCommand(parts); + + // then + assertThat(result.getCommandDescription(), equalTo(getChildWithLabel("register", "authme"))); + assertThat(result.getResultStatus(), equalTo(FoundCommandResult.ResultStatus.UNKNOWN_LABEL)); + assertThat(result.getDifference() < 0.75, equalTo(true)); + } + + /** In contrast to the previous test, we test a command request with a very apart label. */ + @Test + public void shouldSuggestMostSimilarCommand() { + // given + List parts = Arrays.asList("authme", "asdfawetawty4asdca"); + + // when + FoundCommandResult result = handler.mapPartsToCommand(parts); + + // then + assertThat(result.getCommandDescription(), not(nullValue())); + assertThat(result.getResultStatus(), equalTo(FoundCommandResult.ResultStatus.UNKNOWN_LABEL)); + assertThat(result.getDifference() > 0.75, equalTo(true)); + } + + // ---------- + // Helper methods + // ---------- private static CommandDescription createCommand(PlayerPermission permission, CommandDescription parent, List labels, CommandArgumentDescription... arguments) { CommandDescription.CommandBuilder command = CommandDescription.builder() .labels(labels) .parent(parent) .permissions(DefaultPermission.OP_ONLY, permission) - .description("Test") - .detailedDescription("Test command") + .description(labels.get(0)) + .detailedDescription("'" + labels.get(0) + "' test command") .executableCommand(mock(ExecutableCommand.class)); if (arguments != null && arguments.length > 0) { @@ -111,27 +142,17 @@ public class CommandHandlerTest { return new CommandArgumentDescription(label, "Test description", isOptional); } - private void assertSenderGotMessageContaining(String text, CommandSender sender) { - ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); - verify(sender).sendMessage(captor.capture()); - assertThat(captor.getValue(), stringContainsInOrder(text)); + private static CommandDescription getChildWithLabel(String childLabel, String parentLabel) { + CommandDescription parent = getCommandWithLabel(parentLabel, commands); + return getCommandWithLabel(childLabel, parent.getChildren()); } private static CommandDescription getCommandWithLabel(String label, Collection commands) { - for (CommandDescription command : commands) { - if (command.getLabels().contains(label)) { - return command; - } - } - return null; - } - - private static CommandDescription getChildWithLabel(String label, CommandDescription command) { - for (CommandDescription child : command.getChildren()) { + for (CommandDescription child : commands) { if (child.getLabels().contains(label)) { return child; } } - return null; + throw new RuntimeException("Could not find command with label '" + label + "'"); } } diff --git a/src/test/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommandTest.java index dd7c1b7a..a55ffeb3 100644 --- a/src/test/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommandTest.java @@ -72,7 +72,7 @@ public class ChangePasswordCommandTest { ChangePasswordCommand command = new ChangePasswordCommand(); // when - command.executeCommand(sender, Collections.singletonList("pass")); + command.executeCommand(sender, Arrays.asList("pass", "pass")); // then verify(messagesMock).send(sender, MessageKey.NOT_LOGGED_IN); diff --git a/src/test/java/fr/xephi/authme/command/executable/email/AddEmailCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/email/AddEmailCommandTest.java index 64b09b29..1a9c5a12 100644 --- a/src/test/java/fr/xephi/authme/command/executable/email/AddEmailCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/email/AddEmailCommandTest.java @@ -11,6 +11,7 @@ import org.junit.Test; import org.mockito.Mockito; import java.util.ArrayList; +import java.util.Arrays; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @@ -52,7 +53,7 @@ public class AddEmailCommandTest { AddEmailCommand command = new AddEmailCommand(); // when - command.executeCommand(sender, new ArrayList()); + command.executeCommand(sender, Arrays.asList("mail@example", "other_example")); // then verify(authMeMock).getManagement(); diff --git a/src/test/java/fr/xephi/authme/command/executable/login/LoginCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/login/LoginCommandTest.java index a4773c57..27de64a8 100644 --- a/src/test/java/fr/xephi/authme/command/executable/login/LoginCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/login/LoginCommandTest.java @@ -59,19 +59,4 @@ public class LoginCommandTest { Mockito.verify(managementMock).performLogin(eq(sender), eq("password"), eq(false)); } - @Test - public void shouldHandleMissingPassword() { - // given - Player sender = mock(Player.class); - LoginCommand command = new LoginCommand(); - - // when - command.executeCommand(sender, new ArrayList()); - - // then - // TODO ljacqu 20151121: May make sense to handle null password in LoginCommand instead of forwarding the call - String password = null; - Mockito.verify(managementMock).performLogin(eq(sender), eq(password), eq(false)); - } - } From 01a294a334bfe71de6a2dbbcfc40fad5a3ebb2b7 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Fri, 18 Dec 2015 22:19:26 +0100 Subject: [PATCH 13/18] #305 Adjust behavior of label handling; cleanup - Fix bugs in behavior (wrong labels being shown for help) - Change order of labels and arguments in FoundCommandResult constructors - Move FoundResultStatus enum to its own class - Create test class for HelpProvider --- .../xephi/authme/command/CommandHandler.java | 23 ++--- .../fr/xephi/authme/command/CommandUtils.java | 3 +- .../authme/command/FoundCommandResult.java | 48 ++++------ .../authme/command/FoundResultStatus.java | 16 ++++ .../command/executable/HelpCommand.java | 8 +- .../authme/command/help/HelpProvider.java | 6 +- .../authme/command/CommandHandlerTest.java | 24 +++-- .../authme/command/CommandUtilsTest.java | 89 +++++++++++++++++++ .../authme/command/help/HelpProviderTest.java | 65 ++++++++++++++ 9 files changed, 231 insertions(+), 51 deletions(-) create mode 100644 src/main/java/fr/xephi/authme/command/FoundResultStatus.java create mode 100644 src/test/java/fr/xephi/authme/command/help/HelpProviderTest.java diff --git a/src/main/java/fr/xephi/authme/command/CommandHandler.java b/src/main/java/fr/xephi/authme/command/CommandHandler.java index 1222eeb0..a53a32e1 100644 --- a/src/main/java/fr/xephi/authme/command/CommandHandler.java +++ b/src/main/java/fr/xephi/authme/command/CommandHandler.java @@ -12,9 +12,9 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; -import static fr.xephi.authme.command.FoundCommandResult.ResultStatus.INCORRECT_ARGUMENTS; -import static fr.xephi.authme.command.FoundCommandResult.ResultStatus.MISSING_BASE_COMMAND; -import static fr.xephi.authme.command.FoundCommandResult.ResultStatus.UNKNOWN_LABEL; +import static fr.xephi.authme.command.FoundResultStatus.INCORRECT_ARGUMENTS; +import static fr.xephi.authme.command.FoundResultStatus.MISSING_BASE_COMMAND; +import static fr.xephi.authme.command.FoundResultStatus.UNKNOWN_LABEL; /** * The AuthMe command handler, responsible for mapping incoming commands to the correct {@link CommandDescription} @@ -121,9 +121,8 @@ public class CommandHandler { // Show a command suggestion if available and the difference isn't too big if (result.getDifference() < SUGGEST_COMMAND_THRESHOLD && result.getCommandDescription() != null) { - sender.sendMessage(ChatColor.YELLOW + "Did you mean " + ChatColor.GOLD + "/" - + result.getCommandDescription() + ChatColor.YELLOW + "?"); - // FIXME: Define a proper string representation of command description + sender.sendMessage(ChatColor.YELLOW + "Did you mean " + ChatColor.GOLD + + CommandUtils.constructCommandPath(result.getCommandDescription()) + ChatColor.YELLOW + "?"); } sender.sendMessage(ChatColor.YELLOW + "Use the command " + ChatColor.GOLD + "/" + result.getLabels().get(0) @@ -175,9 +174,9 @@ public class CommandHandler { List remainingParts = parts.subList(1, parts.size()); CommandDescription childCommand = getSuitableChild(base, remainingParts); if (childCommand != null) { - return new FoundCommandResult(childCommand, parts.subList(2, parts.size()), parts.subList(0, 2)); + return new FoundCommandResult(childCommand, parts.subList(0, 2), parts.subList(2, parts.size())); } else if (hasSuitableArgumentCount(base, remainingParts.size())) { - return new FoundCommandResult(base, parts.subList(1, parts.size()), parts.subList(0, 1)); + return new FoundCommandResult(base, parts.subList(0, 1), parts.subList(1, parts.size())); } return getCommandWithSmallestDifference(base, parts); @@ -200,13 +199,15 @@ public class CommandHandler { // base command may have no children or no child label was present if (closestCommand == null) { - return new FoundCommandResult(null, null, parts, minDifference, UNKNOWN_LABEL); + return new FoundCommandResult(null, parts, null, minDifference, UNKNOWN_LABEL); } - FoundCommandResult.ResultStatus status = (minDifference == 0.0) ? INCORRECT_ARGUMENTS : UNKNOWN_LABEL; + FoundResultStatus status = (minDifference == 0.0) ? INCORRECT_ARGUMENTS : UNKNOWN_LABEL; final int partsSize = parts.size(); List labels = parts.subList(0, Math.min(closestCommand.getParentCount() + 1, partsSize)); - List arguments = parts.subList(Math.min(partsSize - 1, labels.size()), partsSize); + List arguments = (labels.size() == partsSize) + ? new ArrayList() + : parts.subList(labels.size(), partsSize); return new FoundCommandResult(closestCommand, labels, arguments, minDifference, status); } diff --git a/src/main/java/fr/xephi/authme/command/CommandUtils.java b/src/main/java/fr/xephi/authme/command/CommandUtils.java index e0ff117d..2e4d02a2 100644 --- a/src/main/java/fr/xephi/authme/command/CommandUtils.java +++ b/src/main/java/fr/xephi/authme/command/CommandUtils.java @@ -1,7 +1,6 @@ package fr.xephi.authme.command; import com.google.common.collect.Lists; -import fr.xephi.authme.util.CollectionUtils; import fr.xephi.authme.util.StringUtils; import java.util.ArrayList; @@ -25,7 +24,7 @@ public final class CommandUtils { /** * Provide a textual representation of a list of labels to show it as a command. For example, a list containing - * the items ["authme", "register", "player"] it will return "authme register player". + * the items ["authme", "register", "player"] will return "authme register player". * * @param labels The labels to format * diff --git a/src/main/java/fr/xephi/authme/command/FoundCommandResult.java b/src/main/java/fr/xephi/authme/command/FoundCommandResult.java index 99361d76..76f63633 100644 --- a/src/main/java/fr/xephi/authme/command/FoundCommandResult.java +++ b/src/main/java/fr/xephi/authme/command/FoundCommandResult.java @@ -4,17 +4,17 @@ import java.util.List; /** * Result of a command mapping by {@link CommandHandler}. An object of this class represents a successful mapping - * as well as erroneous ones, as communicated with {@link ResultStatus}. + * as well as erroneous ones, as communicated with {@link FoundResultStatus}. *

- * Fields other than {@link ResultStatus} are available depending, among other factors, on the status: + * Fields other than {@link FoundResultStatus} are available depending, among other factors, on the status: *

    - *
  • {@link ResultStatus#SUCCESS} entails that mapping the input to a command was successful. Therefore, + *
  • {@link FoundResultStatus#SUCCESS} entails that mapping the input to a command was successful. Therefore, * the command description, labels and arguments are set. The difference is 0.0.
  • - *
  • {@link ResultStatus#INCORRECT_ARGUMENTS}: The received parts could be mapped to a command but the argument + *
  • {@link FoundResultStatus#INCORRECT_ARGUMENTS}: The received parts could be mapped to a command but the argument * count doesn't match. Guarantees that the command description field is not null; difference is 0.0
  • - *
  • {@link ResultStatus#UNKNOWN_LABEL}: The labels could not be mapped to a command. The command description may - * be set to the most similar command, or it may be null. Difference is above 0.0.
  • - *
  • {@link ResultStatus#MISSING_BASE_COMMAND} should never occur. All other fields may be null and any further + *
  • {@link FoundResultStatus#UNKNOWN_LABEL}: The labels could not be mapped to a command. The command description + * may be set to the most similar command, or it may be null. Difference is above 0.0.
  • + *
  • {@link FoundResultStatus#MISSING_BASE_COMMAND} should never occur. All other fields may be null and any further * processing of the object should be aborted.
  • *
*/ @@ -24,38 +24,38 @@ public class FoundCommandResult { * The command description instance. */ private final CommandDescription commandDescription; - /** - * The command arguments. - */ - private final List arguments; /** * The labels used to invoke the command. This may be different for the same {@link ExecutableCommand} instance * if multiple labels have been defined, e.g. "/authme register" and "/authme reg". */ private final List labels; + /** + * The command arguments. + */ + private final List arguments; private final double difference; - private final ResultStatus resultStatus; + private final FoundResultStatus resultStatus; /** * Constructor. * * @param commandDescription The command description. + * @param labels The labels used to access the command. * @param arguments The command arguments. - * @param labels The original query reference. */ - public FoundCommandResult(CommandDescription commandDescription, List arguments, List labels, - double difference, ResultStatus resultStatus) { + public FoundCommandResult(CommandDescription commandDescription, List labels, List arguments, + double difference, FoundResultStatus resultStatus) { this.commandDescription = commandDescription; - this.arguments = arguments; this.labels = labels; + this.arguments = arguments; this.difference = difference; this.resultStatus = resultStatus; } - public FoundCommandResult(CommandDescription commandDescription, List arguments, List labels) { - this(commandDescription, arguments, labels, 0.0, ResultStatus.SUCCESS); + public FoundCommandResult(CommandDescription commandDescription, List labels, List arguments) { + this(commandDescription, labels, arguments, 0.0, FoundResultStatus.SUCCESS); } public CommandDescription getCommandDescription() { @@ -74,18 +74,8 @@ public class FoundCommandResult { return difference; } - public ResultStatus getResultStatus() { + public FoundResultStatus getResultStatus() { return resultStatus; } - public enum ResultStatus { - - SUCCESS, - - INCORRECT_ARGUMENTS, - - UNKNOWN_LABEL, - - MISSING_BASE_COMMAND - } } diff --git a/src/main/java/fr/xephi/authme/command/FoundResultStatus.java b/src/main/java/fr/xephi/authme/command/FoundResultStatus.java new file mode 100644 index 00000000..080a3447 --- /dev/null +++ b/src/main/java/fr/xephi/authme/command/FoundResultStatus.java @@ -0,0 +1,16 @@ +package fr.xephi.authme.command; + +/** + * Result status for mapping command parts. See {@link FoundCommandResult} for a detailed description of the states. + */ +public enum FoundResultStatus { + + SUCCESS, + + INCORRECT_ARGUMENTS, + + UNKNOWN_LABEL, + + MISSING_BASE_COMMAND + +} diff --git a/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java b/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java index 0282751a..95dea98a 100644 --- a/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java @@ -5,6 +5,7 @@ import fr.xephi.authme.command.CommandHandler; import fr.xephi.authme.command.CommandUtils; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.command.FoundCommandResult; +import fr.xephi.authme.command.FoundResultStatus; import fr.xephi.authme.command.help.HelpProvider; import fr.xephi.authme.permission.PermissionsManager; import org.bukkit.ChatColor; @@ -12,7 +13,9 @@ import org.bukkit.command.CommandSender; import java.util.List; -import static fr.xephi.authme.command.FoundCommandResult.ResultStatus.*; +import static fr.xephi.authme.command.FoundResultStatus.INCORRECT_ARGUMENTS; +import static fr.xephi.authme.command.FoundResultStatus.MISSING_BASE_COMMAND; +import static fr.xephi.authme.command.FoundResultStatus.UNKNOWN_LABEL; public class HelpCommand extends ExecutableCommand { @@ -27,8 +30,9 @@ public class HelpCommand extends ExecutableCommand { // TODO ljacqu 20151213: This is essentially the same logic as in CommandHandler and we'd like to have the same // messages. Maybe we can have another method in CommandHandler where the end command isn't executed upon // success. - FoundCommandResult.ResultStatus resultStatus = foundCommandResult.getResultStatus(); + FoundResultStatus resultStatus = foundCommandResult.getResultStatus(); if (MISSING_BASE_COMMAND.equals(resultStatus)) { + // FIXME something wrong - this error appears sender.sendMessage(ChatColor.DARK_RED + "Could not get base command"); return; } else if (INCORRECT_ARGUMENTS.equals(resultStatus) || UNKNOWN_LABEL.equals(resultStatus)) { diff --git a/src/main/java/fr/xephi/authme/command/help/HelpProvider.java b/src/main/java/fr/xephi/authme/command/help/HelpProvider.java index 151f3e1b..a60937cd 100644 --- a/src/main/java/fr/xephi/authme/command/help/HelpProvider.java +++ b/src/main/java/fr/xephi/authme/command/help/HelpProvider.java @@ -1,5 +1,6 @@ package fr.xephi.authme.command.help; +import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import fr.xephi.authme.command.CommandArgumentDescription; @@ -216,11 +217,12 @@ public final class HelpProvider { return (flag & options) != 0; } - private static List filterCorrectLabels(CommandDescription command, List labels) { + @VisibleForTesting + protected static List filterCorrectLabels(CommandDescription command, List labels) { List commands = new ArrayList<>(command.getParentCount() + 1); CommandDescription currentCommand = command; while (currentCommand != null) { - commands.add(command); + commands.add(currentCommand); currentCommand = currentCommand.getParent(); } commands = Lists.reverse(commands); diff --git a/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java b/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java index 31810210..2e46a30a 100644 --- a/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java +++ b/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java @@ -53,7 +53,7 @@ public class CommandHandlerTest { // then assertThat(result.getCommandDescription(), equalTo(getChildWithLabel("login", "authme"))); - assertThat(result.getResultStatus(), equalTo(FoundCommandResult.ResultStatus.SUCCESS)); + assertThat(result.getResultStatus(), equalTo(FoundResultStatus.SUCCESS)); assertThat(result.getArguments(), contains("test1")); assertThat(result.getDifference(), equalTo(0.0)); } @@ -68,7 +68,7 @@ public class CommandHandlerTest { // then assertThat(result.getCommandDescription(), equalTo(getChildWithLabel("register", "authme"))); - assertThat(result.getResultStatus(), equalTo(FoundCommandResult.ResultStatus.SUCCESS)); + assertThat(result.getResultStatus(), equalTo(FoundResultStatus.SUCCESS)); assertThat(result.getArguments(), contains("arg1", "arg2")); assertThat(result.getDifference(), equalTo(0.0)); } @@ -83,7 +83,21 @@ public class CommandHandlerTest { // then assertThat(result.getCommandDescription(), equalTo(getChildWithLabel("register", "authme"))); - assertThat(result.getResultStatus(), equalTo(FoundCommandResult.ResultStatus.INCORRECT_ARGUMENTS)); + assertThat(result.getResultStatus(), equalTo(FoundResultStatus.INCORRECT_ARGUMENTS)); + assertThat(result.getDifference(), equalTo(0.0)); + } + + @Test + public void shouldRejectCommandWithTooFewArguments() { + // given + List parts = Arrays.asList("authme", "Reg"); + + // when + FoundCommandResult result = handler.mapPartsToCommand(parts); + + // then + assertThat(result.getCommandDescription(), equalTo(getChildWithLabel("register", "authme"))); + assertThat(result.getResultStatus(), equalTo(FoundResultStatus.INCORRECT_ARGUMENTS)); assertThat(result.getDifference(), equalTo(0.0)); } @@ -97,7 +111,7 @@ public class CommandHandlerTest { // then assertThat(result.getCommandDescription(), equalTo(getChildWithLabel("register", "authme"))); - assertThat(result.getResultStatus(), equalTo(FoundCommandResult.ResultStatus.UNKNOWN_LABEL)); + assertThat(result.getResultStatus(), equalTo(FoundResultStatus.UNKNOWN_LABEL)); assertThat(result.getDifference() < 0.75, equalTo(true)); } @@ -112,7 +126,7 @@ public class CommandHandlerTest { // then assertThat(result.getCommandDescription(), not(nullValue())); - assertThat(result.getResultStatus(), equalTo(FoundCommandResult.ResultStatus.UNKNOWN_LABEL)); + assertThat(result.getResultStatus(), equalTo(FoundResultStatus.UNKNOWN_LABEL)); assertThat(result.getDifference() > 0.75, equalTo(true)); } diff --git a/src/test/java/fr/xephi/authme/command/CommandUtilsTest.java b/src/test/java/fr/xephi/authme/command/CommandUtilsTest.java index 1d7baaab..0f4dff18 100644 --- a/src/test/java/fr/xephi/authme/command/CommandUtilsTest.java +++ b/src/test/java/fr/xephi/authme/command/CommandUtilsTest.java @@ -8,6 +8,7 @@ import java.util.List; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; /** * Test for {@link CommandUtils}. @@ -37,4 +38,92 @@ public class CommandUtilsTest { // then assertThat(str, equalTo("")); } + + @Test + public void shouldPrintLabels() { + // given + List labels = Arrays.asList("authme", "help", "reload"); + + // when + String result = CommandUtils.labelsToString(labels); + + // then + assertThat(result, equalTo("authme help reload")); + } + + @Test + public void shouldReturnCommandPath() { + // given + CommandDescription base = CommandDescription.builder() + .labels("authme", "auth") + .description("Base") + .detailedDescription("Test base command.") + .executableCommand(mock(ExecutableCommand.class)) + .build(); + CommandDescription command = CommandDescription.builder() + .parent(base) + .labels("help", "h", "?") + .description("Child") + .detailedDescription("Test child command.") + .executableCommand(mock(ExecutableCommand.class)) + .build(); + + // when + String commandPath = CommandUtils.constructCommandPath(command); + + // then + assertThat(commandPath, equalTo("/authme help")); + } + + + // ------ + // min / max arguments + // ------ + @Test + public void shouldComputeMinAndMaxOnEmptyCommand() { + // given + CommandDescription command = getBuilderForArgsTest().build(); + + // when / then + checkArgumentCount(command, 0, 0); + } + + @Test + public void shouldComputeMinAndMaxOnCommandWithMandatoryArgs() { + // given + CommandDescription command = getBuilderForArgsTest() + .withArgument("Test", "Arg description", false) + .withArgument("Test22", "Arg description 2", false) + .build(); + + // when / then + checkArgumentCount(command, 2, 2); + } + + @Test + public void shouldComputeMinAndMaxOnCommandIncludingOptionalArgs() { + // given + CommandDescription command = getBuilderForArgsTest() + .withArgument("arg1", "Arg description", false) + .withArgument("arg2", "Arg description 2", true) + .withArgument("arg3", "Arg description 3", true) + .build(); + + // when / then + checkArgumentCount(command, 1, 3); + } + + + private static void checkArgumentCount(CommandDescription command, int expectedMin, int expectedMax) { + assertThat(CommandUtils.getMinNumberOfArguments(command), equalTo(expectedMin)); + assertThat(CommandUtils.getMaxNumberOfArguments(command), equalTo(expectedMax)); + } + + private static CommandDescription.CommandBuilder getBuilderForArgsTest() { + return CommandDescription.builder() + .labels("authme", "auth") + .description("Base") + .detailedDescription("Test base command.") + .executableCommand(mock(ExecutableCommand.class)); + } } diff --git a/src/test/java/fr/xephi/authme/command/help/HelpProviderTest.java b/src/test/java/fr/xephi/authme/command/help/HelpProviderTest.java new file mode 100644 index 00000000..dbc62dc8 --- /dev/null +++ b/src/test/java/fr/xephi/authme/command/help/HelpProviderTest.java @@ -0,0 +1,65 @@ +package fr.xephi.authme.command.help; + +import fr.xephi.authme.command.CommandDescription; +import fr.xephi.authme.command.ExecutableCommand; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.hamcrest.Matchers.contains; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; + +/** + * Test for {@link HelpProvider}. + */ +public class HelpProviderTest { + + private static CommandDescription parent; + private static CommandDescription child; + + @BeforeClass + public static void setUpCommands() { + parent = CommandDescription.builder() + .executableCommand(mock(ExecutableCommand.class)) + .labels("base", "b") + .description("Parent") + .detailedDescription("Test base command.") + .build(); + child = CommandDescription.builder() + .executableCommand(mock(ExecutableCommand.class)) + .parent(parent) + .labels("child", "c") + .description("Child") + .detailedDescription("Child test command.") + .withArgument("Argument", "The argument", false) + .build(); + } + + @Test + public void shouldRetainCorrectLabels() { + // given + List labels = Arrays.asList("b", "child"); + + // when + List result = HelpProvider.filterCorrectLabels(child, labels); + + // then + assertThat(result, contains("b", "child")); + } + + @Test + public void shouldReplaceIncorrectLabels() { + // given + List labels = Arrays.asList("base", "wrong"); + + // when + List result = HelpProvider.filterCorrectLabels(child, labels); + + // then + assertThat(result, contains("base", "child")); + } + +} From bf9724dd34aa0702baa24b1809dcbd59be91e65a Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sat, 19 Dec 2015 10:35:02 +0100 Subject: [PATCH 14/18] Fix label handling issues after reformatting - Pass the correct arguments to HelpCommand - Fix minor formatting / conditional check issues --- .../xephi/authme/command/CommandHandler.java | 19 ++++++++++++++++++- .../fr/xephi/authme/command/CommandUtils.java | 16 +++++++++++++--- .../command/executable/HelpCommand.java | 16 +++++++--------- .../authme/command/help/HelpProvider.java | 14 +++----------- 4 files changed, 41 insertions(+), 24 deletions(-) diff --git a/src/main/java/fr/xephi/authme/command/CommandHandler.java b/src/main/java/fr/xephi/authme/command/CommandHandler.java index a53a32e1..09ccbd3c 100644 --- a/src/main/java/fr/xephi/authme/command/CommandHandler.java +++ b/src/main/java/fr/xephi/authme/command/CommandHandler.java @@ -1,6 +1,7 @@ package fr.xephi.authme.command; import fr.xephi.authme.AuthMe; +import fr.xephi.authme.command.executable.HelpCommand; import fr.xephi.authme.command.help.HelpProvider; import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.util.CollectionUtils; @@ -28,6 +29,8 @@ public class CommandHandler { */ private static final double SUGGEST_COMMAND_THRESHOLD = 0.75; + private static final Class HELP_COMMAND_CLASS = HelpCommand.class; + private final Set baseCommands; private final PermissionsManager permissionsManager; @@ -174,7 +177,10 @@ public class CommandHandler { List remainingParts = parts.subList(1, parts.size()); CommandDescription childCommand = getSuitableChild(base, remainingParts); if (childCommand != null) { - return new FoundCommandResult(childCommand, parts.subList(0, 2), parts.subList(2, parts.size())); + FoundCommandResult result = new FoundCommandResult( + childCommand, parts.subList(0, 2), parts.subList(2, parts.size())); + transformResultForHelp(result); + return result; } else if (hasSuitableArgumentCount(base, remainingParts.size())) { return new FoundCommandResult(base, parts.subList(0, 1), parts.subList(1, parts.size())); } @@ -248,6 +254,17 @@ public class CommandHandler { return null; } + private static void transformResultForHelp(FoundCommandResult result) { + if (result.getCommandDescription() != null + && HELP_COMMAND_CLASS.equals(result.getCommandDescription().getExecutableCommand().getClass())) { + // For "/authme help register" we have labels = [authme, help] and arguments = [register] + // But for the help command we want labels = [authme, help] and arguments = [authme, register], + // so we can use the arguments as the labels to the command to show help for + final String baseLabel = result.getLabels().get(0); + result.getArguments().add(0, baseLabel); + } + } + private static boolean hasSuitableArgumentCount(CommandDescription command, int argumentCount) { int minArgs = CommandUtils.getMinNumberOfArguments(command); int maxArgs = CommandUtils.getMaxNumberOfArguments(command); diff --git a/src/main/java/fr/xephi/authme/command/CommandUtils.java b/src/main/java/fr/xephi/authme/command/CommandUtils.java index 2e4d02a2..905e8922 100644 --- a/src/main/java/fr/xephi/authme/command/CommandUtils.java +++ b/src/main/java/fr/xephi/authme/command/CommandUtils.java @@ -35,12 +35,22 @@ public final class CommandUtils { } public static String constructCommandPath(CommandDescription command) { - List labels = new ArrayList<>(); + StringBuilder sb = new StringBuilder(); + String prefix = "/"; + for (CommandDescription ancestor : constructParentList(command)) { + sb.append(prefix).append(ancestor.getLabels().get(0)); + prefix = " "; + } + return sb.toString(); + } + + public static List constructParentList(CommandDescription command) { + List commands = new ArrayList<>(); CommandDescription currentCommand = command; while (currentCommand != null) { - labels.add(currentCommand.getLabels().get(0)); + commands.add(currentCommand); currentCommand = currentCommand.getParent(); } - return "/" + labelsToString(Lists.reverse(labels)); + return Lists.reverse(commands); } } diff --git a/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java b/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java index 95dea98a..793803e5 100644 --- a/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java @@ -1,6 +1,5 @@ package fr.xephi.authme.command.executable; -import fr.xephi.authme.AuthMe; import fr.xephi.authme.command.CommandHandler; import fr.xephi.authme.command.CommandUtils; import fr.xephi.authme.command.ExecutableCommand; @@ -8,12 +7,12 @@ import fr.xephi.authme.command.FoundCommandResult; import fr.xephi.authme.command.FoundResultStatus; import fr.xephi.authme.command.help.HelpProvider; import fr.xephi.authme.permission.PermissionsManager; +import fr.xephi.authme.util.Wrapper; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import java.util.List; -import static fr.xephi.authme.command.FoundResultStatus.INCORRECT_ARGUMENTS; import static fr.xephi.authme.command.FoundResultStatus.MISSING_BASE_COMMAND; import static fr.xephi.authme.command.FoundResultStatus.UNKNOWN_LABEL; @@ -24,7 +23,7 @@ public class HelpCommand extends ExecutableCommand { @Override public void executeCommand(CommandSender sender, List arguments) { // TODO #306 ljacqu 20151213: Get command handler from non-static context - CommandHandler commandHandler = AuthMe.getInstance().getCommandHandler(); + CommandHandler commandHandler = Wrapper.getInstance().getAuthMe().getCommandHandler(); FoundCommandResult foundCommandResult = commandHandler.mapPartsToCommand(arguments); // TODO ljacqu 20151213: This is essentially the same logic as in CommandHandler and we'd like to have the same @@ -32,20 +31,19 @@ public class HelpCommand extends ExecutableCommand { // success. FoundResultStatus resultStatus = foundCommandResult.getResultStatus(); if (MISSING_BASE_COMMAND.equals(resultStatus)) { - // FIXME something wrong - this error appears sender.sendMessage(ChatColor.DARK_RED + "Could not get base command"); return; - } else if (INCORRECT_ARGUMENTS.equals(resultStatus) || UNKNOWN_LABEL.equals(resultStatus)) { - if (foundCommandResult.getCommandDescription() != null) { + } else if (UNKNOWN_LABEL.equals(resultStatus)) { + if (foundCommandResult.getCommandDescription() == null) { sender.sendMessage(ChatColor.DARK_RED + "Unknown command"); return; } else { - sender.sendMessage(ChatColor.GOLD + "Assuming " + ChatColor.WHITE + "/" - + CommandUtils.labelsToString(foundCommandResult.getCommandDescription().getLabels())); + sender.sendMessage(ChatColor.GOLD + "Assuming " + ChatColor.WHITE + + CommandUtils.constructCommandPath(foundCommandResult.getCommandDescription())); } } - PermissionsManager permissionsManager = AuthMe.getInstance().getPermissionsManager(); + PermissionsManager permissionsManager = Wrapper.getInstance().getAuthMe().getPermissionsManager(); List lines = arguments.size() == 1 ? HelpProvider.printHelp(foundCommandResult, HelpProvider.SHOW_CHILDREN) : HelpProvider.printHelp(foundCommandResult, sender, permissionsManager, HelpProvider.ALL_OPTIONS); diff --git a/src/main/java/fr/xephi/authme/command/help/HelpProvider.java b/src/main/java/fr/xephi/authme/command/help/HelpProvider.java index a60937cd..73fd957a 100644 --- a/src/main/java/fr/xephi/authme/command/help/HelpProvider.java +++ b/src/main/java/fr/xephi/authme/command/help/HelpProvider.java @@ -2,7 +2,6 @@ package fr.xephi.authme.command.help; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; import fr.xephi.authme.command.CommandArgumentDescription; import fr.xephi.authme.command.CommandDescription; import fr.xephi.authme.command.CommandPermissions; @@ -208,9 +207,9 @@ public final class HelpProvider { /** Format a command argument with the proper type of brackets. */ private static String formatArgument(CommandArgumentDescription argument) { if (argument.isOptional()) { - return " [" + argument.getName() + "]"; + return "[" + argument.getName() + "]"; } - return " <" + argument.getName() + ">"; + return "<" + argument.getName() + ">"; } private static boolean hasFlag(int flag, int options) { @@ -219,14 +218,7 @@ public final class HelpProvider { @VisibleForTesting protected static List filterCorrectLabels(CommandDescription command, List labels) { - List commands = new ArrayList<>(command.getParentCount() + 1); - CommandDescription currentCommand = command; - while (currentCommand != null) { - commands.add(currentCommand); - currentCommand = currentCommand.getParent(); - } - commands = Lists.reverse(commands); - + List commands = CommandUtils.constructParentList(command); List correctLabels = new ArrayList<>(); boolean foundIncorrectLabel = false; for (int i = 0; i < commands.size(); ++i) { From 42c34c56a0caf60f5c707e52fba27139ccf8d189 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sat, 19 Dec 2015 12:20:52 +0100 Subject: [PATCH 15/18] Fix command formatting after refactor - Fix spacing issues (too few or too many spaces) - Handle base commands with invalid arguments properly - Add highlighting function for command syntax --- .../xephi/authme/command/CommandHandler.java | 20 ++++--- .../command/help/CommandSyntaxHelper.java | 36 +++++++++++++ .../authme/command/help/HelpProvider.java | 54 ++++--------------- 3 files changed, 57 insertions(+), 53 deletions(-) create mode 100644 src/main/java/fr/xephi/authme/command/help/CommandSyntaxHelper.java diff --git a/src/main/java/fr/xephi/authme/command/CommandHandler.java b/src/main/java/fr/xephi/authme/command/CommandHandler.java index 09ccbd3c..78a8e78b 100644 --- a/src/main/java/fr/xephi/authme/command/CommandHandler.java +++ b/src/main/java/fr/xephi/authme/command/CommandHandler.java @@ -189,17 +189,21 @@ public class CommandHandler { } private FoundCommandResult getCommandWithSmallestDifference(CommandDescription base, List parts) { - final String childLabel = parts.size() >= 2 ? parts.get(1) : null; + // Return the base command with incorrect arg count error if we only have one part + if (parts.size() <= 1) { + return new FoundCommandResult( + base, parts, new ArrayList(), 0.0, FoundResultStatus.INCORRECT_ARGUMENTS); + } + + final String childLabel = parts.get(1); double minDifference = Double.POSITIVE_INFINITY; CommandDescription closestCommand = null; - if (childLabel != null) { - for (CommandDescription child : base.getChildren()) { - double difference = getLabelDifference(child, childLabel); - if (difference < minDifference) { - minDifference = difference; - closestCommand = child; - } + for (CommandDescription child : base.getChildren()) { + double difference = getLabelDifference(child, childLabel); + if (difference < minDifference) { + minDifference = difference; + closestCommand = child; } } diff --git a/src/main/java/fr/xephi/authme/command/help/CommandSyntaxHelper.java b/src/main/java/fr/xephi/authme/command/help/CommandSyntaxHelper.java new file mode 100644 index 00000000..40bb2185 --- /dev/null +++ b/src/main/java/fr/xephi/authme/command/help/CommandSyntaxHelper.java @@ -0,0 +1,36 @@ +package fr.xephi.authme.command.help; + +import fr.xephi.authme.command.CommandArgumentDescription; +import fr.xephi.authme.command.CommandDescription; +import org.bukkit.ChatColor; + +import java.util.List; + +/** + * Helper class for displaying the syntax of a command properly to a user. + */ +class CommandSyntaxHelper { + + private CommandSyntaxHelper() { + } + + public static String getSyntax(CommandDescription command, List correctLabels) { + String commandSyntax = ChatColor.WHITE + "/" + correctLabels.get(0) + ChatColor.YELLOW; + for (int i = 1; i < correctLabels.size(); ++i) { + commandSyntax += " " + correctLabels.get(i); + } + for (CommandArgumentDescription argument : command.getArguments()) { + commandSyntax += " " + formatArgument(argument); + } + return commandSyntax; + } + + /** Format a command argument with the proper type of brackets. */ + private static String formatArgument(CommandArgumentDescription argument) { + if (argument.isOptional()) { + return "[" + argument.getName() + "]"; + } + return "<" + argument.getName() + ">"; + } + +} diff --git a/src/main/java/fr/xephi/authme/command/help/HelpProvider.java b/src/main/java/fr/xephi/authme/command/help/HelpProvider.java index 73fd957a..37bbb9e5 100644 --- a/src/main/java/fr/xephi/authme/command/help/HelpProvider.java +++ b/src/main/java/fr/xephi/authme/command/help/HelpProvider.java @@ -12,15 +12,13 @@ import fr.xephi.authme.permission.PermissionNode; import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.util.CollectionUtils; -import fr.xephi.authme.util.StringUtils; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; import java.util.List; +import static java.util.Arrays.asList; import static java.util.Collections.singletonList; /** @@ -67,7 +65,7 @@ public final class HelpProvider { List correctLabels = ImmutableList.copyOf(filterCorrectLabels(command, labels)); if (!hasFlag(HIDE_COMMAND, options)) { - printCommand(command, correctLabels, lines); + lines.add(ChatColor.GOLD + "Command: " + CommandSyntaxHelper.getSyntax(command, correctLabels)); } if (hasFlag(SHOW_LONG_DESCRIPTION, options)) { printDetailedDescription(command, lines); @@ -88,15 +86,6 @@ public final class HelpProvider { return lines; } - private static void printCommand(CommandDescription command, List correctLabels, List lines) { - // FIXME: Create highlight logic to mark arguments and the 2nd label as yellow - String syntaxLine = "/" + CommandUtils.labelsToString(correctLabels); - for (CommandArgumentDescription argument : command.getArguments()) { - syntaxLine += " " + formatArgument(argument); - } - lines.add(syntaxLine); - } - private static void printDetailedDescription(CommandDescription command, List lines) { lines.add(ChatColor.GOLD + "Short Description: " + ChatColor.WHITE + command.getDescription()); lines.add(ChatColor.GOLD + "Detailed Description:"); @@ -104,7 +93,7 @@ public final class HelpProvider { } private static void printArguments(CommandDescription command, List lines) { - if (!command.getArguments().isEmpty()) { + if (command.getArguments().isEmpty()) { return; } @@ -122,39 +111,22 @@ public final class HelpProvider { } private static void printAlternatives(CommandDescription command, List correctLabels, List lines) { + // TODO ljacqu 20151219: Need to show alternatives for base labels too? E.g. /r for /register if (command.getLabels().size() <= 1) { return; } lines.add(ChatColor.GOLD + "Alternatives:"); // Get the label used - final String usedLabel = correctLabels.get(correctLabels.size() - 1); + final String parentLabel = correctLabels.get(0); + final String childLabel = correctLabels.get(1); // Create a list of alternatives - List alternatives = new ArrayList<>(); for (String entry : command.getLabels()) { - if (!entry.equalsIgnoreCase(usedLabel)) { - alternatives.add(entry); + if (!entry.equalsIgnoreCase(childLabel)) { + lines.add(" " + CommandSyntaxHelper.getSyntax(command, asList(parentLabel, entry))); } } - - // Sort the alternatives - Collections.sort(alternatives, new Comparator() { - // TODO ljacqu 20151212: This computes the difference each time anew. It might make sense to compute the - // difference once and to store it in some map-like structure (Guava has some interesting ones) - @Override - public int compare(String o1, String o2) { - return Double.compare(StringUtils.getDifference(usedLabel, o1), - StringUtils.getDifference(usedLabel, o2)); - } - }); - - // Print each alternative with proper syntax - for (String alternative : alternatives) { - // fixme add highlight functionality (see commented old line) - // sender.sendMessage(" " + _HelpSyntaxHelper.getCommandSyntax(command, commandReference, alternative, true)); - lines.add(" " + CommandUtils.labelsToString(correctLabels) + " " + alternative); - } } private static void printPermissions(CommandDescription command, CommandSender sender, @@ -199,19 +171,11 @@ public final class HelpProvider { lines.add(ChatColor.GOLD + "Commands:"); String parentCommandPath = CommandUtils.labelsToString(parentLabels); for (CommandDescription child : command.getChildren()) { - lines.add(" " + parentCommandPath + child.getLabels().get(0) + lines.add(" /" + parentCommandPath + " " + child.getLabels().get(0) + ChatColor.GRAY + ChatColor.ITALIC + ": " + child.getDescription()); } } - /** Format a command argument with the proper type of brackets. */ - private static String formatArgument(CommandArgumentDescription argument) { - if (argument.isOptional()) { - return "[" + argument.getName() + "]"; - } - return "<" + argument.getName() + ">"; - } - private static boolean hasFlag(int flag, int options) { return (flag & options) != 0; } From a928a4092dfca78bfef95d4007adce253e6ee20a Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sat, 19 Dec 2015 16:27:00 +0100 Subject: [PATCH 16/18] #305 Fix label handling, add extensive tests for command handler --- .../xephi/authme/command/CommandHandler.java | 18 +- .../authme/command/FoundCommandResult.java | 17 +- .../authme/command/CommandHandlerTest.java | 213 +++++++++++++++++- 3 files changed, 231 insertions(+), 17 deletions(-) diff --git a/src/main/java/fr/xephi/authme/command/CommandHandler.java b/src/main/java/fr/xephi/authme/command/CommandHandler.java index 78a8e78b..fcc65aa0 100644 --- a/src/main/java/fr/xephi/authme/command/CommandHandler.java +++ b/src/main/java/fr/xephi/authme/command/CommandHandler.java @@ -29,6 +29,9 @@ public class CommandHandler { */ private static final double SUGGEST_COMMAND_THRESHOLD = 0.75; + /** + * The class of the help command, to which the base label should also be passed in the arguments. + */ private static final Class HELP_COMMAND_CLASS = HelpCommand.class; private final Set baseCommands; @@ -58,9 +61,8 @@ public class CommandHandler { // Add the Bukkit command label to the front so we get a list like [authme, register, bobby, mysecret] List parts = skipEmptyArguments(bukkitArgs); parts.add(0, bukkitCommandLabel); - - // Get the base command of the result, e.g. authme for [authme, register, bobby, mysecret] FoundCommandResult result = mapPartsToCommand(parts); + switch (result.getResultStatus()) { case SUCCESS: executeCommandIfAllowed(sender, result.getCommandDescription(), result.getArguments()); @@ -75,7 +77,7 @@ public class CommandHandler { sendUnknownCommandMessage(sender, result); break; default: - throw new RuntimeException("Unknown result '" + result.getResultStatus() + "'"); + throw new IllegalStateException("Unknown result '" + result.getResultStatus() + "'"); } return true; @@ -191,8 +193,7 @@ public class CommandHandler { private FoundCommandResult getCommandWithSmallestDifference(CommandDescription base, List parts) { // Return the base command with incorrect arg count error if we only have one part if (parts.size() <= 1) { - return new FoundCommandResult( - base, parts, new ArrayList(), 0.0, FoundResultStatus.INCORRECT_ARGUMENTS); + return new FoundCommandResult(base, parts, new ArrayList(), 0.0, INCORRECT_ARGUMENTS); } final String childLabel = parts.get(1); @@ -207,9 +208,10 @@ public class CommandHandler { } } - // base command may have no children or no child label was present + // base command may have no children, in which case we return the base command with incorrect arguments error if (closestCommand == null) { - return new FoundCommandResult(null, parts, null, minDifference, UNKNOWN_LABEL); + return new FoundCommandResult( + base, parts.subList(0, 1), parts.subList(1, parts.size()), 0.0, INCORRECT_ARGUMENTS); } FoundResultStatus status = (minDifference == 0.0) ? INCORRECT_ARGUMENTS : UNKNOWN_LABEL; @@ -260,7 +262,7 @@ public class CommandHandler { private static void transformResultForHelp(FoundCommandResult result) { if (result.getCommandDescription() != null - && HELP_COMMAND_CLASS.equals(result.getCommandDescription().getExecutableCommand().getClass())) { + && HELP_COMMAND_CLASS.isAssignableFrom(result.getCommandDescription().getExecutableCommand().getClass())) { // For "/authme help register" we have labels = [authme, help] and arguments = [register] // But for the help command we want labels = [authme, help] and arguments = [authme, register], // so we can use the arguments as the labels to the command to show help for diff --git a/src/main/java/fr/xephi/authme/command/FoundCommandResult.java b/src/main/java/fr/xephi/authme/command/FoundCommandResult.java index 76f63633..f9fcce7b 100644 --- a/src/main/java/fr/xephi/authme/command/FoundCommandResult.java +++ b/src/main/java/fr/xephi/authme/command/FoundCommandResult.java @@ -29,13 +29,11 @@ public class FoundCommandResult { * if multiple labels have been defined, e.g. "/authme register" and "/authme reg". */ private final List labels; - /** - * The command arguments. - */ + /** The command arguments. */ private final List arguments; - + /** The difference between the matched command and the supplied labels. */ private final double difference; - + /** The status of the result (see class description). */ private final FoundResultStatus resultStatus; /** @@ -44,6 +42,8 @@ public class FoundCommandResult { * @param commandDescription The command description. * @param labels The labels used to access the command. * @param arguments The command arguments. + * @param difference The difference between the supplied labels and the matched command. + * @param resultStatus The status of the result. */ public FoundCommandResult(CommandDescription commandDescription, List labels, List arguments, double difference, FoundResultStatus resultStatus) { @@ -54,6 +54,13 @@ public class FoundCommandResult { this.resultStatus = resultStatus; } + /** + * Constructor for a fully successfully matched command. + * + * @param commandDescription The matched command description. + * @param labels The labels used to access the command. + * @param arguments The command arguments. + */ public FoundCommandResult(CommandDescription commandDescription, List labels, List arguments) { this(commandDescription, labels, arguments, 0.0, FoundResultStatus.SUCCESS); } diff --git a/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java b/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java index 2e46a30a..b333b164 100644 --- a/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java +++ b/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java @@ -1,25 +1,38 @@ package fr.xephi.authme.command; +import fr.xephi.authme.command.executable.HelpCommand; import fr.xephi.authme.permission.DefaultPermission; import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.permission.PlayerPermission; +import org.bukkit.command.CommandSender; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.mockito.ArgumentCaptor; import java.util.Arrays; import java.util.Collection; -import java.util.HashSet; import java.util.List; import java.util.Set; +import static com.google.common.collect.Sets.newHashSet; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; +import static org.hamcrest.Matchers.stringContainsInOrder; +import static org.mockito.BDDMockito.given; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyListOf; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; /** * Test for {@link CommandHandler}. @@ -32,17 +45,36 @@ public class CommandHandlerTest { @BeforeClass public static void setUpCommandHandler() { + // Register /authme CommandDescription authMeBase = createCommand(null, null, singletonList("authme")); + // Register /authme login createCommand(PlayerPermission.LOGIN, authMeBase, singletonList("login"), newArgument("password", false)); + // Register /authme register , alias: /authme reg createCommand(PlayerPermission.LOGIN, authMeBase, asList("register", "reg"), newArgument("password", false), newArgument("confirmation", false)); - CommandDescription testBase = createCommand(null, null, singletonList("test"), newArgument("test", true)); - commands = new HashSet<>(asList(authMeBase, testBase)); + // Register /email [player] + CommandDescription emailBase = createCommand(null, null, singletonList("email")); + // Register /email helptest -- use only to test for help command arguments special case + CommandDescription.builder().parent(emailBase).labels("helptest").executableCommand(mock(HelpCommand.class)) + .description("test").detailedDescription("Test.").withArgument("Query", "", false).build(); + + // Register /unregister , alias: /unreg + CommandDescription unregisterBase = createCommand(null, null, asList("unregister", "unreg"), + newArgument("player", false)); + + commands = newHashSet(authMeBase, emailBase, unregisterBase); + } + + @Before + public void setUpMocks() { permissionsManagerMock = mock(PermissionsManager.class); handler = new CommandHandler(commands, permissionsManagerMock); } + // ----------- + // mapPartsToCommand() tests + // ----------- @Test public void shouldMapPartsToLoginChildCommand() { // given @@ -56,6 +88,8 @@ public class CommandHandlerTest { assertThat(result.getResultStatus(), equalTo(FoundResultStatus.SUCCESS)); assertThat(result.getArguments(), contains("test1")); assertThat(result.getDifference(), equalTo(0.0)); + assertThat(result.getLabels(), equalTo(parts.subList(0, 2))); + assertThat(result.getArguments(), contains(parts.get(2))); } @Test @@ -69,6 +103,7 @@ public class CommandHandlerTest { // then assertThat(result.getCommandDescription(), equalTo(getChildWithLabel("register", "authme"))); assertThat(result.getResultStatus(), equalTo(FoundResultStatus.SUCCESS)); + assertThat(result.getLabels(), equalTo(parts.subList(0, 2))); assertThat(result.getArguments(), contains("arg1", "arg2")); assertThat(result.getDifference(), equalTo(0.0)); } @@ -85,6 +120,8 @@ public class CommandHandlerTest { assertThat(result.getCommandDescription(), equalTo(getChildWithLabel("register", "authme"))); assertThat(result.getResultStatus(), equalTo(FoundResultStatus.INCORRECT_ARGUMENTS)); assertThat(result.getDifference(), equalTo(0.0)); + assertThat(result.getLabels(), equalTo(parts.subList(0, 2))); + assertThat(result.getArguments(), equalTo(parts.subList(2, 5))); } @Test @@ -99,6 +136,8 @@ public class CommandHandlerTest { assertThat(result.getCommandDescription(), equalTo(getChildWithLabel("register", "authme"))); assertThat(result.getResultStatus(), equalTo(FoundResultStatus.INCORRECT_ARGUMENTS)); assertThat(result.getDifference(), equalTo(0.0)); + assertThat(result.getLabels(), equalTo(parts)); + assertThat(result.getArguments(), empty()); } @Test @@ -113,6 +152,8 @@ public class CommandHandlerTest { assertThat(result.getCommandDescription(), equalTo(getChildWithLabel("register", "authme"))); assertThat(result.getResultStatus(), equalTo(FoundResultStatus.UNKNOWN_LABEL)); assertThat(result.getDifference() < 0.75, equalTo(true)); + assertThat(result.getLabels(), equalTo(parts.subList(0, 2))); + assertThat(result.getArguments(), contains("pass123", "pass123")); } /** In contrast to the previous test, we test a command request with a very apart label. */ @@ -128,8 +169,172 @@ public class CommandHandlerTest { assertThat(result.getCommandDescription(), not(nullValue())); assertThat(result.getResultStatus(), equalTo(FoundResultStatus.UNKNOWN_LABEL)); assertThat(result.getDifference() > 0.75, equalTo(true)); + assertThat(result.getLabels(), equalTo(parts)); + assertThat(result.getArguments(), empty()); } + @Test + public void shouldHandleBaseWithWrongArguments() { + // given + List parts = singletonList("unregister"); + + // when + FoundCommandResult result = handler.mapPartsToCommand(parts); + + // then + assertThat(result.getResultStatus(), equalTo(FoundResultStatus.INCORRECT_ARGUMENTS)); + assertThat(result.getCommandDescription(), equalTo(getCommandWithLabel("unregister", commands))); + assertThat(result.getDifference(), equalTo(0.0)); + assertThat(result.getArguments(), empty()); + assertThat(result.getLabels(), equalTo(parts)); + } + + @Test + public void shouldHandleUnknownBase() { + // given + List parts = asList("bogus", "label1", "arg1"); + + // when + FoundCommandResult result = handler.mapPartsToCommand(parts); + + // then + assertThat(result.getResultStatus(), equalTo(FoundResultStatus.MISSING_BASE_COMMAND)); + assertThat(result.getCommandDescription(), nullValue()); + } + + @Test + public void shouldHandleNullInput() { + // given / when + FoundCommandResult result = handler.mapPartsToCommand(null); + + // then + assertThat(result.getResultStatus(), equalTo(FoundResultStatus.MISSING_BASE_COMMAND)); + assertThat(result.getCommandDescription(), nullValue()); + } + + @Test + public void shouldMapToBaseWithProperArguments() { + // given + List parts = asList("Unreg", "player1"); + + // when + FoundCommandResult result = handler.mapPartsToCommand(parts); + + // then + assertThat(result.getResultStatus(), equalTo(FoundResultStatus.SUCCESS)); + assertThat(result.getCommandDescription(), equalTo(getCommandWithLabel("unregister", commands))); + assertThat(result.getDifference(), equalTo(0.0)); + assertThat(result.getArguments(), contains("player1")); + assertThat(result.getLabels(), contains("Unreg")); + } + + @Test + public void shouldReturnChildlessBaseCommandWithArgCountError() { + // given + List parts = asList("unregistER", "player1", "wrongArg"); + + // when + FoundCommandResult result = handler.mapPartsToCommand(parts); + + // then + assertThat(result.getResultStatus(), equalTo(FoundResultStatus.INCORRECT_ARGUMENTS)); + assertThat(result.getCommandDescription(), equalTo(getCommandWithLabel("unregister", commands))); + assertThat(result.getDifference(), equalTo(0.0)); + assertThat(result.getArguments(), contains("player1", "wrongArg")); + assertThat(result.getLabels(), contains("unregistER")); + } + + // ---------- + // processCommand() tests + // ---------- + @Test + public void shouldCallMappedCommandWithArgs() { + // given + String bukkitLabel = "Authme"; + String[] bukkitArgs = {"Login", "myPass"}; + CommandSender sender = mock(CommandSender.class); + + CommandDescription command = getChildWithLabel("login", "authme"); + given(permissionsManagerMock.hasPermission(sender, command)).willReturn(true); + + // when + handler.processCommand(sender, bukkitLabel, bukkitArgs); + + // then + ArgumentCaptor argsCaptor = ArgumentCaptor.forClass(List.class); + verify(command.getExecutableCommand()).executeCommand(eq(sender), argsCaptor.capture()); + List argument = argsCaptor.getValue(); + assertThat(argument, contains("myPass")); + // Ensure that no error message was issued to the command sender + verify(sender, never()).sendMessage(anyString()); + } + + @Test + public void shouldNotCallExecutableCommandIfNoPermission() { + // given + String bukkitLabel = "unreg"; + String[] bukkitArgs = {"testPlayer"}; + CommandSender sender = mock(CommandSender.class); + given(permissionsManagerMock.hasPermission(any(CommandSender.class), any(CommandDescription.class))) + .willReturn(false); + + // when + handler.processCommand(sender, bukkitLabel, bukkitArgs); + + // then + CommandDescription command = getCommandWithLabel("unregister", commands); + verify(permissionsManagerMock).hasPermission(sender, command); + verify(command.getExecutableCommand(), never()) + .executeCommand(any(CommandSender.class), anyListOf(String.class)); + + ArgumentCaptor messageCaptor = ArgumentCaptor.forClass(String.class); + verify(sender).sendMessage(messageCaptor.capture()); + String message = messageCaptor.getValue(); + assertThat(message, stringContainsInOrder("You don't have permission")); + } + + @Test + public void shouldStripWhitespace() { + // given + String bukkitLabel = "AuthMe"; + String[] bukkitArgs = {" ", "", "LOGIN", " ", "testArg", " "}; + CommandSender sender = mock(CommandSender.class); + + CommandDescription command = getChildWithLabel("login", "authme"); + given(permissionsManagerMock.hasPermission(sender, command)).willReturn(true); + + // when + handler.processCommand(sender, bukkitLabel, bukkitArgs); + + // then + ArgumentCaptor argsCaptor = ArgumentCaptor.forClass(List.class); + verify(command.getExecutableCommand()).executeCommand(eq(sender), argsCaptor.capture()); + List arguments = argsCaptor.getValue(); + assertThat(arguments, contains("testArg")); + verify(sender, never()).sendMessage(anyString()); + } + + @Test + public void shouldPassCommandPathAsArgumentsToHelpCommand() { + // given + String bukkitLabel = "email"; + String[] bukkitArgs = {"helptest", "arg1"}; + CommandSender sender = mock(CommandSender.class); + + CommandDescription command = getChildWithLabel("helptest", "email"); + given(permissionsManagerMock.hasPermission(sender, command)).willReturn(true); + + // when + handler.processCommand(sender, bukkitLabel, bukkitArgs); + + // then + ArgumentCaptor argsCaptor = ArgumentCaptor.forClass(List.class); + verify(command.getExecutableCommand()).executeCommand(eq(sender), argsCaptor.capture()); + List arguments = argsCaptor.getValue(); + assertThat(arguments, contains("email", "arg1")); + } + + // ---------- // Helper methods // ---------- @@ -163,7 +368,7 @@ public class CommandHandlerTest { private static CommandDescription getCommandWithLabel(String label, Collection commands) { for (CommandDescription child : commands) { - if (child.getLabels().contains(label)) { + if (child.hasLabel(label)) { return child; } } From b64b6177fae21ad814d7b7f25c8a5e7d75da163b Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sat, 19 Dec 2015 17:45:58 +0100 Subject: [PATCH 17/18] Fix invoking help command throwing exception - ConcurrentModificationException was being thrown because labels was being modified again in transformForHelpCommand --- .../java/fr/xephi/authme/command/CommandHandler.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/fr/xephi/authme/command/CommandHandler.java b/src/main/java/fr/xephi/authme/command/CommandHandler.java index fcc65aa0..a6f7f4b6 100644 --- a/src/main/java/fr/xephi/authme/command/CommandHandler.java +++ b/src/main/java/fr/xephi/authme/command/CommandHandler.java @@ -181,8 +181,7 @@ public class CommandHandler { if (childCommand != null) { FoundCommandResult result = new FoundCommandResult( childCommand, parts.subList(0, 2), parts.subList(2, parts.size())); - transformResultForHelp(result); - return result; + return transformResultForHelp(result); } else if (hasSuitableArgumentCount(base, remainingParts.size())) { return new FoundCommandResult(base, parts.subList(0, 1), parts.subList(1, parts.size())); } @@ -260,15 +259,18 @@ public class CommandHandler { return null; } - private static void transformResultForHelp(FoundCommandResult result) { + private static FoundCommandResult transformResultForHelp(FoundCommandResult result) { if (result.getCommandDescription() != null && HELP_COMMAND_CLASS.isAssignableFrom(result.getCommandDescription().getExecutableCommand().getClass())) { // For "/authme help register" we have labels = [authme, help] and arguments = [register] // But for the help command we want labels = [authme, help] and arguments = [authme, register], // so we can use the arguments as the labels to the command to show help for - final String baseLabel = result.getLabels().get(0); - result.getArguments().add(0, baseLabel); + List arguments = new ArrayList<>(result.getArguments()); + arguments.add(0, result.getLabels().get(0)); + return new FoundCommandResult(result.getCommandDescription(), result.getLabels(), + arguments, result.getDifference(), result.getResultStatus()); } + return result; } private static boolean hasSuitableArgumentCount(CommandDescription command, int argumentCount) { From efa458cae1954e7efc2907fd87ed9e98d4aa9c38 Mon Sep 17 00:00:00 2001 From: ljacqu Date: Sat, 19 Dec 2015 20:25:12 +0100 Subject: [PATCH 18/18] Finalization for #305 - command refactor --- .../fr/xephi/authme/command/CommandDescription.java | 11 +++++------ .../java/fr/xephi/authme/command/CommandHandler.java | 4 ++-- .../fr/xephi/authme/command/CommandInitializer.java | 6 ++---- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/main/java/fr/xephi/authme/command/CommandDescription.java b/src/main/java/fr/xephi/authme/command/CommandDescription.java index 6e69c765..d398af67 100644 --- a/src/main/java/fr/xephi/authme/command/CommandDescription.java +++ b/src/main/java/fr/xephi/authme/command/CommandDescription.java @@ -146,16 +146,15 @@ public class CommandDescription { } /** - * Return the number of parents that precede the command description. + * Return the number of labels necessary to get to this command. This corresponds to the number of parents + 1. * - * @return The number of parents, e.g. for "/authme abc def" the parent count is 2 ("/authme abc", "/authme") + * @return The number of labels, e.g. for "/authme abc def" the label count is 3 */ - // TODO ljacqu 20151217: If we always use `getParentCount() + 1` rewrite this method to a `getLabelCount()` - public int getParentCount() { + public int getLabelCount() { if (parent == null) { - return 0; + return 1; } - return parent.getParentCount() + 1; + return parent.getLabelCount() + 1; } /** diff --git a/src/main/java/fr/xephi/authme/command/CommandHandler.java b/src/main/java/fr/xephi/authme/command/CommandHandler.java index a6f7f4b6..fad9a269 100644 --- a/src/main/java/fr/xephi/authme/command/CommandHandler.java +++ b/src/main/java/fr/xephi/authme/command/CommandHandler.java @@ -125,7 +125,7 @@ public class CommandHandler { sender.sendMessage(ChatColor.DARK_RED + "Unknown command!"); // Show a command suggestion if available and the difference isn't too big - if (result.getDifference() < SUGGEST_COMMAND_THRESHOLD && result.getCommandDescription() != null) { + if (result.getDifference() <= SUGGEST_COMMAND_THRESHOLD && result.getCommandDescription() != null) { sender.sendMessage(ChatColor.YELLOW + "Did you mean " + ChatColor.GOLD + CommandUtils.constructCommandPath(result.getCommandDescription()) + ChatColor.YELLOW + "?"); } @@ -215,7 +215,7 @@ public class CommandHandler { FoundResultStatus status = (minDifference == 0.0) ? INCORRECT_ARGUMENTS : UNKNOWN_LABEL; final int partsSize = parts.size(); - List labels = parts.subList(0, Math.min(closestCommand.getParentCount() + 1, partsSize)); + List labels = parts.subList(0, Math.min(closestCommand.getLabelCount(), partsSize)); List arguments = (labels.size() == partsSize) ? new ArrayList() : parts.subList(labels.size(), partsSize); diff --git a/src/main/java/fr/xephi/authme/command/CommandInitializer.java b/src/main/java/fr/xephi/authme/command/CommandInitializer.java index 2866669e..82f45fc2 100644 --- a/src/main/java/fr/xephi/authme/command/CommandInitializer.java +++ b/src/main/java/fr/xephi/authme/command/CommandInitializer.java @@ -34,7 +34,6 @@ import fr.xephi.authme.command.executable.register.RegisterCommand; import fr.xephi.authme.command.executable.unregister.UnregisterCommand; import fr.xephi.authme.permission.AdminPermission; import fr.xephi.authme.permission.PlayerPermission; -import fr.xephi.authme.util.Wrapper; import java.util.Arrays; import java.util.List; @@ -56,7 +55,6 @@ public final class CommandInitializer { public static Set getBaseCommands() { if (baseCommands == null) { - Wrapper.getInstance().getLogger().info("Initializing AuthMe commands"); initializeCommands(); } return baseCommands; @@ -287,8 +285,8 @@ public final class CommandInitializer { .parent(AUTHME_BASE) .labels("version", "ver", "v", "about", "info") .description("Version info") - .detailedDescription("Show detailed information about the installed AuthMeReloaded version, and shows the " - + "developers, contributors, license and other information.") + .detailedDescription("Show detailed information about the installed AuthMeReloaded version, the " + + "developers, contributors, and license.") .executableCommand(new VersionCommand()) .build();