diff --git a/src/main/java/nova/commands/Args.java b/src/main/java/nova/commands/Args.java index f47773f..1cf6e41 100644 --- a/src/main/java/nova/commands/Args.java +++ b/src/main/java/nova/commands/Args.java @@ -175,8 +175,8 @@ public Stream parallelStream() { public int hashCode() { int hash = 5; hash = 97 * hash + Arrays.deepHashCode(this.requiredArgs); - hash = 97 * hash + this.optionalArgsString.hashCode(); - hash = 97 * hash + this.optionalArgsChar.hashCode(); + hash = 97 * hash + Objects.hashCode(this.optionalArgsString); + hash = 97 * hash + Objects.hashCode(this.optionalArgsChar); return hash; } diff --git a/src/main/java/nova/commands/ArgsParser.java b/src/main/java/nova/commands/ArgsParser.java index 38fb803..d7cdc34 100644 --- a/src/main/java/nova/commands/ArgsParser.java +++ b/src/main/java/nova/commands/ArgsParser.java @@ -19,6 +19,7 @@ */ package nova.commands; +import nova.commands.exception.CommandParseException; import nova.core.retention.Data; import nova.core.util.EnumSelector; @@ -181,10 +182,10 @@ public ArgsParser opt(char shortName) { * After this method is called, no more edits are allowed. * * @return The parsed {@link Args} instance. - * @throws IllegalStateException The {@link #args(java.lang.Class...)} + * @throws CommandParseException The {@link #args(java.lang.Class...)} * hasn't been called and the constructor arguments parameter isn't empty. */ - public Args parse() throws IllegalArgumentException { + public Args parse() throws CommandParseException { if (parsed != null) return parsed; @@ -194,7 +195,7 @@ public Args parse() throws IllegalArgumentException { } if (required.length == 0) - throw new IllegalStateException("Cannot parse ArgParser without specifying required arguments."); + throw new CommandParseException("Cannot parse ArgParser without specifying required arguments.", Errors.UNSPECIFIED_REQUIRED_ARGUMENTS); int requiredPos = 0; boolean continuos = false; @@ -296,7 +297,7 @@ public Args parse() throws IllegalArgumentException { errored.lock(); if (!errored.blocksAll()) - throw new IllegalArgumentException("Errors with command: " + errored.toSet()); + throw new CommandParseException("Errors with command", errored); parsed = new Args(required, optsStr, optsChar); return parsed; @@ -371,7 +372,9 @@ public boolean locked() { return parsed != null; } - private static enum Errors { + public static enum Errors { + PARSER_IS_LOCKED("Parser is locked"), + UNSPECIFIED_REQUIRED_ARGUMENTS("Required arguments unspecified"), TOO_LONG("Arguments too long"), UNENDED_QUOTES("Unended quotes"), UNKNOWN_OPTIONAL("Unknown optional argument"); diff --git a/src/main/java/nova/commands/Command.java b/src/main/java/nova/commands/Command.java index 88701f6..486058a 100644 --- a/src/main/java/nova/commands/Command.java +++ b/src/main/java/nova/commands/Command.java @@ -20,6 +20,7 @@ package nova.commands; +import nova.commands.exception.CommandException; import nova.core.entity.component.Player; import nova.core.event.bus.Event; import nova.core.event.bus.EventBus; @@ -61,8 +62,10 @@ public Command(String command) { * @param player The player who issued this command. * Won't be present if the command was issued from the server command line. * @param args The arguments that were given by the player. + * + * @throws CommandException If something goes wrong during command execution. */ - public abstract void handle(Optional player, String... args); + public abstract void handle(Optional player, String... args) throws CommandException; /** * Get a list of possible ways the command could auto-complete. @@ -74,7 +77,7 @@ public Command(String command) { * @param args The already completed arguments * @return The list. Must not be null. */ - public List getAutocompleteList(Optional player, int pos, String startsWith, String... args) { + public List getAutocompleteList(Optional player, String... args) { return Collections.emptyList(); } diff --git a/src/main/java/nova/commands/event/CommandEvent.java b/src/main/java/nova/commands/event/CommandEvent.java index b73c3e5..ff45c67 100644 --- a/src/main/java/nova/commands/event/CommandEvent.java +++ b/src/main/java/nova/commands/event/CommandEvent.java @@ -64,26 +64,6 @@ public CommandHandleEvent(Optional player, Command command, String... ar } } - /** - * Event is triggered when a command execution fails. - */ - public static class CommandHandleErrorEvent extends CommandHandleEvent { - public final Optional message; - public final Object[] messageParameters; - - public CommandHandleErrorEvent(Optional player, Command command, String... args) { - super(player, command, args); - this.message = Optional.empty(); - this.messageParameters = new Object[0]; - } - - public CommandHandleErrorEvent(Optional player, Command command, String[] args, String message, Object... messageParameters) { - super(player, command, args); - this.message = Optional.ofNullable(message); - this.messageParameters = Arrays.copyOf(messageParameters, messageParameters.length); - } - } - /** * Event is triggered when a Command is registered. * diff --git a/src/main/java/nova/commands/exception/CommandException.java b/src/main/java/nova/commands/exception/CommandException.java new file mode 100644 index 0000000..9a2a6aa --- /dev/null +++ b/src/main/java/nova/commands/exception/CommandException.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2017 NOVA, All rights reserved. + * This library is free software, licensed under GNU Lesser General Public License version 3 + * + * This file is part of NOVA. + * + * NOVA is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * NOVA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NOVA. If not, see . + */ + +package nova.commands.exception; + +import nova.core.util.exception.NovaException; + +import java.util.Arrays; +import java.util.Optional; + +/** + * @author ExE Boss + */ +public class CommandException extends NovaException { + + private static final long serialVersionUID = 1L; + private final Object[] arguments; + + public CommandException() { + this.arguments = null; + } + + public CommandException(String message, Object... parameters) { + super(message, parameters); + this.arguments = Arrays.copyOf(parameters, parameters.length); + } + + public CommandException(String message) { + super(message); + this.arguments = null; + } + + public CommandException(String message, Throwable cause) { + super(message, cause); + this.arguments = null; + } + + public CommandException(String message, Throwable cause, Object... parameters) { + super(message, parameters); + this.initCause(cause); + this.arguments = Arrays.copyOf(parameters, parameters.length); + } + + public CommandException(Throwable cause) { + super(cause); + this.arguments = null; + } + + public Optional getArguments() { + return Optional.ofNullable(Arrays.copyOf(arguments, arguments.length)); + } +} diff --git a/src/main/java/nova/commands/exception/CommandParseException.java b/src/main/java/nova/commands/exception/CommandParseException.java new file mode 100644 index 0000000..a413d7c --- /dev/null +++ b/src/main/java/nova/commands/exception/CommandParseException.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017 NOVA, All rights reserved. + * This library is free software, licensed under GNU Lesser General Public License version 3 + * + * This file is part of NOVA. + * + * NOVA is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * NOVA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with NOVA. If not, see . + */ + +package nova.commands.exception; + +import nova.commands.ArgsParser; +import nova.core.util.EnumSelector; + +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumSet; +import java.util.Optional; +import java.util.Set; + +/** + * @author ExE Boss + */ +public class CommandParseException extends CommandException { + + private static final long serialVersionUID = 1L; + + private final Set errors; + + public CommandParseException(String message) { + super(message); + this.errors = null; + } + + public CommandParseException(String message, Throwable cause) { + super(message, cause); + this.errors = null; + } + + private CommandParseException(String message, Set errors) { + super(message + ": " + errors); + this.errors = errors; + } + + public CommandParseException(String message, ArgsParser.Errors... errors) { + this(message, toEnumSet(errors)); + } + + public CommandParseException(String message, EnumSet errors) { + this(message, Collections.unmodifiableSet(errors)); + } + + public CommandParseException(String message, EnumSelector errors) { + this(message, errors.toSet()); + } + + public Optional> getErrors() { + return Optional.ofNullable(errors); + } + + private static EnumSet toEnumSet(ArgsParser.Errors... errors) { + EnumSet set = EnumSet.noneOf(ArgsParser.Errors.class); + set.addAll(Arrays.asList(errors)); + return set; + } +} diff --git a/src/test/java/nova/commands/CommandTest.java b/src/test/java/nova/commands/CommandTest.java index 3c2f5bf..b33b869 100644 --- a/src/test/java/nova/commands/CommandTest.java +++ b/src/test/java/nova/commands/CommandTest.java @@ -20,6 +20,7 @@ package nova.commands; +import nova.commands.exception.CommandException; import nova.core.event.bus.Event; import nova.core.event.bus.EventBus; import org.junit.Before; @@ -55,6 +56,11 @@ public void testHandle() { command.handle(null, new String[]{"test"}, Optional.of(events)); } + @Test(expected = CommandException.class) + public void testHandleException() { + command.handleError(null, new String[0], "Message"); + } + @Test public void testGetCommandName() { assertThat(command.getCommandName()).isEqualTo("Test_Command"); diff --git a/src/test/java/nova/commands/TestCommand.java b/src/test/java/nova/commands/TestCommand.java index 4623a9d..cf26988 100644 --- a/src/test/java/nova/commands/TestCommand.java +++ b/src/test/java/nova/commands/TestCommand.java @@ -19,7 +19,7 @@ */ package nova.commands; -import nova.commands.event.CommandEvent; +import nova.commands.exception.CommandException; import nova.core.entity.component.Player; import nova.core.event.bus.Event; import nova.core.event.bus.EventBus; @@ -39,22 +39,22 @@ public TestCommand(String command) { super(command); } - public void handle(Optional player, String[] args, Optional> events) { + public void handle(Optional player, String[] args, Optional> events) throws CommandException { Args argsObj = new ArgsParser(args).args(String.class).parse(); events.ifPresent(evt -> evt.publish(new TestCommandHandleEvent(player, this, argsObj))); } - public void handleError(Optional player, String[] args, Optional> events, String message) { - events.ifPresent(evt -> evt.publish(new CommandEvent.CommandHandleErrorEvent(player, this, args, message))); + public void handleError(Optional player, String[] args, String message) throws CommandException { + throw new CommandException(message); } @Override - public void handle(Optional player, String... args) { + public void handle(Optional player, String... args) throws CommandException { this.handle(player, args, Optional.empty()); } @Override - public String getCommandUsage(Optional player) { + public String getCommandUsage(Optional player) throws CommandException { return ""; } } diff --git a/src/test/java/nova/commands/event/CommandEventTest.java b/src/test/java/nova/commands/event/CommandEventTest.java index 9b80ec3..84c8668 100644 --- a/src/test/java/nova/commands/event/CommandEventTest.java +++ b/src/test/java/nova/commands/event/CommandEventTest.java @@ -20,6 +20,7 @@ package nova.commands.event; import nova.commands.TestCommand; +import nova.commands.TestCommandHandleEvent; import nova.core.event.bus.Event; import nova.core.event.bus.EventBus; import org.junit.Before; @@ -44,14 +45,6 @@ public void setUp() { command = new TestCommand(); } - @Test - public void testCommandHandleErrorEvent() { - events.on(CommandEvent.CommandHandleErrorEvent.class).bind(evt -> { - evt.message.ifPresent(msg -> assertThat(msg).isEqualTo("Message")); - }); - command.handleError(null, new String[0], Optional.of(events), "Message"); - } - @Test public void testCommandRegister() { events.on(CommandEvent.Register.class).bind(evt -> {