From 059f28fbb3a90748968401317f81255b2805b0fd Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 28 Jul 2022 08:46:31 +0200 Subject: [PATCH 01/15] Add api to enable caching for TypeMapper --- src/de/steamwar/command/TabCompletionCache.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/de/steamwar/command/TabCompletionCache.java b/src/de/steamwar/command/TabCompletionCache.java index 5cf555c..6f2d0ff 100644 --- a/src/de/steamwar/command/TabCompletionCache.java +++ b/src/de/steamwar/command/TabCompletionCache.java @@ -24,6 +24,7 @@ import lombok.EqualsAndHashCode; import lombok.experimental.UtilityClass; import java.util.*; +import java.util.concurrent.TimeUnit; import java.util.function.Supplier; @UtilityClass @@ -36,12 +37,16 @@ public class TabCompletionCache { void add(AbstractTypeMapper typeMapper, AbstractSWCommand.Cached cached) { if (cached != null) { - TabCompletionCache.cached.add(typeMapper); - if (cached.global()) TabCompletionCache.global.add(typeMapper); - TabCompletionCache.cacheDuration.put(typeMapper, cached.timeUnit().toMillis(cached.cacheDuration())); + add(typeMapper, cached.global(), cached.cacheDuration(), cached.timeUnit()); } } + public void add(AbstractTypeMapper typeMapper, boolean global, long cacheDuration, TimeUnit timeUnit) { + TabCompletionCache.cached.add(typeMapper); + if (global) TabCompletionCache.global.add(typeMapper); + TabCompletionCache.cacheDuration.put(typeMapper, timeUnit.toMillis(cacheDuration)); + } + @EqualsAndHashCode @AllArgsConstructor private static class Key { From 5050580774202bbed2a9d2618f1010b39d5b5c69 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 16 Aug 2022 17:11:16 +0200 Subject: [PATCH 02/15] Add better boolean handling for StaticValue annotation --- src/de/steamwar/command/AbstractSWCommand.java | 6 ++++-- src/de/steamwar/command/SWCommandUtils.java | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/de/steamwar/command/AbstractSWCommand.java b/src/de/steamwar/command/AbstractSWCommand.java index 1de5785..aa33a64 100644 --- a/src/de/steamwar/command/AbstractSWCommand.java +++ b/src/de/steamwar/command/AbstractSWCommand.java @@ -371,10 +371,12 @@ public abstract class AbstractSWCommand { * and can be set to true if you want to allow int as well as boolean as annotated parameter types. * The value array needs to be at least 2 long for this flag to be considered. * While using an int, the value will represent the index into the value array. - * While using a boolean, the value array must only be 2 long and the value will be {@code false} - * for the first index and {@code true} for the second index. + * While using a boolean, the {@link #falseValues()} defines which indices are + * considered {@code false} or {@code true}. */ boolean allowISE() default false; + + int[] falseValues() default { 0 }; } @Retention(RetentionPolicy.RUNTIME) diff --git a/src/de/steamwar/command/SWCommandUtils.java b/src/de/steamwar/command/SWCommandUtils.java index 9620631..3cac23c 100644 --- a/src/de/steamwar/command/SWCommandUtils.java +++ b/src/de/steamwar/command/SWCommandUtils.java @@ -136,11 +136,13 @@ public class SWCommandUtils { return createMapper(staticValue.value()); } if (staticValue.allowISE()) { - if ((parameter.getType() == boolean.class || parameter.getType() == Boolean.class) && staticValue.value().length == 2) { + if ((parameter.getType() == boolean.class || parameter.getType() == Boolean.class)) { List tabCompletes = new ArrayList<>(Arrays.asList(staticValue.value())); + Set trueValues = new HashSet<>(); + for (int i : staticValue.falseValues()) trueValues.add(i); return createMapper(s -> { int index = tabCompletes.indexOf(s); - return index == -1 ? null : index != 0; + return index == -1 ? null : !trueValues.contains(index); }, (commandSender, s) -> tabCompletes); } if ((parameter.getType() == int.class || parameter.getType() == Integer.class) && staticValue.value().length >= 2) { From b28178b9155734fdd38b0f059bfdafd81d0289c0 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 16 Aug 2022 17:12:27 +0200 Subject: [PATCH 03/15] Add better boolean handling for StaticValue annotation --- src/de/steamwar/command/SWCommandUtils.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/de/steamwar/command/SWCommandUtils.java b/src/de/steamwar/command/SWCommandUtils.java index 3cac23c..94a9c93 100644 --- a/src/de/steamwar/command/SWCommandUtils.java +++ b/src/de/steamwar/command/SWCommandUtils.java @@ -138,11 +138,11 @@ public class SWCommandUtils { if (staticValue.allowISE()) { if ((parameter.getType() == boolean.class || parameter.getType() == Boolean.class)) { List tabCompletes = new ArrayList<>(Arrays.asList(staticValue.value())); - Set trueValues = new HashSet<>(); - for (int i : staticValue.falseValues()) trueValues.add(i); + Set falseValues = new HashSet<>(); + for (int i : staticValue.falseValues()) falseValues.add(i); return createMapper(s -> { int index = tabCompletes.indexOf(s); - return index == -1 ? null : !trueValues.contains(index); + return index == -1 ? null : !falseValues.contains(index); }, (commandSender, s) -> tabCompletes); } if ((parameter.getType() == int.class || parameter.getType() == Integer.class) && staticValue.value().length >= 2) { From 696c03b8512ef185218bf49da298387d6c63797a Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 16 Aug 2022 17:53:59 +0200 Subject: [PATCH 04/15] Add better int and long handling for StaticValue annotation --- src/de/steamwar/command/SWCommandUtils.java | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/de/steamwar/command/SWCommandUtils.java b/src/de/steamwar/command/SWCommandUtils.java index 94a9c93..69e0b8c 100644 --- a/src/de/steamwar/command/SWCommandUtils.java +++ b/src/de/steamwar/command/SWCommandUtils.java @@ -145,18 +145,11 @@ public class SWCommandUtils { return index == -1 ? null : !falseValues.contains(index); }, (commandSender, s) -> tabCompletes); } - if ((parameter.getType() == int.class || parameter.getType() == Integer.class) && staticValue.value().length >= 2) { + if ((parameter.getType() == int.class || parameter.getType() == Integer.class || parameter.getType() == long.class || parameter.getType() == Long.class) && staticValue.value().length >= 2) { List tabCompletes = new ArrayList<>(Arrays.asList(staticValue.value())); return createMapper(s -> { - int index = tabCompletes.indexOf(s); - return index == -1 ? null : index; - }, (commandSender, s) -> tabCompletes); - } - if ((parameter.getType() == long.class || parameter.getType() == Long.class) && staticValue.value().length >= 2) { - List tabCompletes = new ArrayList<>(Arrays.asList(staticValue.value())); - return createMapper(s -> { - long index = tabCompletes.indexOf(s); - return index == -1 ? null : index; + Number index = tabCompletes.indexOf(s); + return index.longValue() == -1 ? null : index; }, (commandSender, s) -> tabCompletes); } } From c2795f0f34a8050f77276b980a33d4032a412b05 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 16 Aug 2022 18:04:55 +0200 Subject: [PATCH 05/15] Add StaticValueCommand and StaticValueCommandTest --- .../steamwar/command/StaticValueCommand.java | 55 ++++++++ .../command/StaticValueCommandTest.java | 123 ++++++++++++++++++ 2 files changed, 178 insertions(+) create mode 100644 testsrc/de/steamwar/command/StaticValueCommand.java create mode 100644 testsrc/de/steamwar/command/StaticValueCommandTest.java diff --git a/testsrc/de/steamwar/command/StaticValueCommand.java b/testsrc/de/steamwar/command/StaticValueCommand.java new file mode 100644 index 0000000..0eca60d --- /dev/null +++ b/testsrc/de/steamwar/command/StaticValueCommand.java @@ -0,0 +1,55 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.command; + +import de.steamwar.command.dto.ExecutionIdentifier; +import de.steamwar.command.dto.TestSWCommand; + +public class StaticValueCommand extends TestSWCommand { + + public StaticValueCommand() { + super("staticvalue"); + } + + @Register + public void defaultStaticValue(String s, @StaticValue({"hello", "world"}) String staticValue) { + throw new ExecutionIdentifier("RunStaticValue with " + staticValue); + } + + @Register + public void booleanStaticValue(String s, @StaticValue(value = {"-a", "-b", "-c"}, allowISE = true) boolean staticValue) { + throw new ExecutionIdentifier("RunStaticValue with " + staticValue); + } + + @Register + public void booleanStaticValueOtherFalseValue(String s, @StaticValue(value = {"-d", "-e", "-f"}, allowISE = true, falseValues = { 1 }) boolean staticValue) { + throw new ExecutionIdentifier("RunStaticValue with " + staticValue); + } + + @Register + public void intStaticValue(String s, @StaticValue(value = {"-g", "-h", "-i"}, allowISE = true) int staticValue) { + throw new ExecutionIdentifier("RunStaticValue with int " + staticValue); + } + + @Register + public void longStaticValue(String s, @StaticValue(value = {"-j", "-k", "-l"}, allowISE = true) long staticValue) { + throw new ExecutionIdentifier("RunStaticValue with long " + staticValue); + } +} diff --git a/testsrc/de/steamwar/command/StaticValueCommandTest.java b/testsrc/de/steamwar/command/StaticValueCommandTest.java new file mode 100644 index 0000000..055b8e2 --- /dev/null +++ b/testsrc/de/steamwar/command/StaticValueCommandTest.java @@ -0,0 +1,123 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.command; + +import de.steamwar.command.dto.ExecutionIdentifier; +import org.junit.Test; + +import static de.steamwar.AssertionUtils.assertCMDFramework; + +public class StaticValueCommandTest { + + @Test + public void defaultTest() { + StaticValueCommand cmd = new StaticValueCommand(); + try { + cmd.execute("", "", new String[] {"hello"}); + } catch (Exception e) { + assertCMDFramework(e, ExecutionIdentifier.class, "RunStaticValue with hello"); + } + try { + cmd.execute("", "", new String[] {"world"}); + } catch (Exception e) { + assertCMDFramework(e, ExecutionIdentifier.class, "RunStaticValue with world"); + } + } + + @Test + public void booleanTest() { + StaticValueCommand cmd = new StaticValueCommand(); + try { + cmd.execute("", "", new String[] {"-a"}); + } catch (Exception e) { + assertCMDFramework(e, ExecutionIdentifier.class, "RunStaticValue with false"); + } + try { + cmd.execute("", "", new String[] {"-b"}); + } catch (Exception e) { + assertCMDFramework(e, ExecutionIdentifier.class, "RunStaticValue with true"); + } + try { + cmd.execute("", "", new String[] {"-c"}); + } catch (Exception e) { + assertCMDFramework(e, ExecutionIdentifier.class, "RunStaticValue with true"); + } + } + + @Test + public void booleanOtherFalseTest() { + StaticValueCommand cmd = new StaticValueCommand(); + try { + cmd.execute("", "", new String[] {"-d"}); + } catch (Exception e) { + assertCMDFramework(e, ExecutionIdentifier.class, "RunStaticValue with true"); + } + try { + cmd.execute("", "", new String[] {"-e"}); + } catch (Exception e) { + assertCMDFramework(e, ExecutionIdentifier.class, "RunStaticValue with false"); + } + try { + cmd.execute("", "", new String[] {"-f"}); + } catch (Exception e) { + assertCMDFramework(e, ExecutionIdentifier.class, "RunStaticValue with true"); + } + } + + @Test + public void intTest() { + StaticValueCommand cmd = new StaticValueCommand(); + try { + cmd.execute("", "", new String[] {"-g"}); + } catch (Exception e) { + assertCMDFramework(e, ExecutionIdentifier.class, "RunStaticValue with int 0"); + } + try { + cmd.execute("", "", new String[] {"-h"}); + } catch (Exception e) { + assertCMDFramework(e, ExecutionIdentifier.class, "RunStaticValue with int 1"); + } + try { + cmd.execute("", "", new String[] {"-i"}); + } catch (Exception e) { + assertCMDFramework(e, ExecutionIdentifier.class, "RunStaticValue with int 2"); + } + } + + @Test + public void longTest() { + StaticValueCommand cmd = new StaticValueCommand(); + try { + cmd.execute("", "", new String[] {"-j"}); + } catch (Exception e) { + assertCMDFramework(e, ExecutionIdentifier.class, "RunStaticValue with long 0"); + } + try { + cmd.execute("", "", new String[] {"-k"}); + } catch (Exception e) { + assertCMDFramework(e, ExecutionIdentifier.class, "RunStaticValue with long 1"); + } + try { + cmd.execute("", "", new String[] {"-l"}); + } catch (Exception e) { + assertCMDFramework(e, ExecutionIdentifier.class, "RunStaticValue with long 2"); + } + } +} \ No newline at end of file From 498a638790ba61d9567d0ac76a5b00c71eba7736 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 16 Aug 2022 18:11:10 +0200 Subject: [PATCH 06/15] Add one last test --- .../de/steamwar/command/StaticValueCommandTest.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/testsrc/de/steamwar/command/StaticValueCommandTest.java b/testsrc/de/steamwar/command/StaticValueCommandTest.java index 055b8e2..665250a 100644 --- a/testsrc/de/steamwar/command/StaticValueCommandTest.java +++ b/testsrc/de/steamwar/command/StaticValueCommandTest.java @@ -22,10 +22,20 @@ package de.steamwar.command; import de.steamwar.command.dto.ExecutionIdentifier; import org.junit.Test; +import java.util.List; + import static de.steamwar.AssertionUtils.assertCMDFramework; +import static de.steamwar.AssertionUtils.assertTabCompletes; public class StaticValueCommandTest { + @Test + public void tabCompletionTest() { + StaticValueCommand cmd = new StaticValueCommand(); + List strings = cmd.tabComplete("", "", new String[]{""}); + assertTabCompletes(strings, "hello", "world", "-a", "-b", "-c", "-d", "-e", "-f", "-g", "-h", "-i", "-j", "-k", "-l"); + } + @Test public void defaultTest() { StaticValueCommand cmd = new StaticValueCommand(); From f3387424387d06ca5dfd7883a0d83f821c8d083b Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 16 Aug 2022 18:14:59 +0200 Subject: [PATCH 07/15] Update list usage to collection in SWTypeMapperCreator --- src/de/steamwar/command/SWTypeMapperCreator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/de/steamwar/command/SWTypeMapperCreator.java b/src/de/steamwar/command/SWTypeMapperCreator.java index 33c5dcb..f21b0a8 100644 --- a/src/de/steamwar/command/SWTypeMapperCreator.java +++ b/src/de/steamwar/command/SWTypeMapperCreator.java @@ -19,10 +19,10 @@ package de.steamwar.command; -import java.util.List; +import java.util.Collection; import java.util.function.BiFunction; import java.util.function.Function; public interface SWTypeMapperCreator, K, V> { - T createTypeMapper(Function mapper, BiFunction> tabCompleter); + T createTypeMapper(Function mapper, BiFunction> tabCompleter); } From 3fa992b5c9fa73e0c31525b814cd020e91d9e0fe Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 16 Aug 2022 22:20:17 +0200 Subject: [PATCH 08/15] Remove guard system --- .../command/AbstractGuardChecker.java | 29 ------- .../steamwar/command/AbstractSWCommand.java | 49 +----------- src/de/steamwar/command/CommandPart.java | 75 ++----------------- src/de/steamwar/command/GuardCheckType.java | 27 ------- src/de/steamwar/command/GuardResult.java | 27 ------- src/de/steamwar/command/SWCommandUtils.java | 55 +------------- src/de/steamwar/command/SubCommand.java | 31 +------- testsrc/de/steamwar/command/GuardCommand.java | 43 ----------- .../de/steamwar/command/GuardCommandTest.java | 52 ------------- .../command/dto/TestGuardChecker.java | 25 ------- 10 files changed, 14 insertions(+), 399 deletions(-) delete mode 100644 src/de/steamwar/command/AbstractGuardChecker.java delete mode 100644 src/de/steamwar/command/GuardCheckType.java delete mode 100644 src/de/steamwar/command/GuardResult.java delete mode 100644 testsrc/de/steamwar/command/GuardCommand.java delete mode 100644 testsrc/de/steamwar/command/GuardCommandTest.java delete mode 100644 testsrc/de/steamwar/command/dto/TestGuardChecker.java diff --git a/src/de/steamwar/command/AbstractGuardChecker.java b/src/de/steamwar/command/AbstractGuardChecker.java deleted file mode 100644 index dd4c555..0000000 --- a/src/de/steamwar/command/AbstractGuardChecker.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2020 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.command; - -@Deprecated -@FunctionalInterface -public interface AbstractGuardChecker { - /** - * While guarding the first parameter of the command the parameter s of this method is {@code null} - */ - GuardResult guard(T t, GuardCheckType guardCheckType, String[] previousArguments, String s); -} diff --git a/src/de/steamwar/command/AbstractSWCommand.java b/src/de/steamwar/command/AbstractSWCommand.java index aa33a64..758be84 100644 --- a/src/de/steamwar/command/AbstractSWCommand.java +++ b/src/de/steamwar/command/AbstractSWCommand.java @@ -38,7 +38,6 @@ public abstract class AbstractSWCommand { protected final List> commandHelpList = new ArrayList<>(); private final Map> localTypeMapper = new HashMap<>(); - private final Map> localGuardChecker = new HashMap<>(); private final Map> localValidators = new HashMap<>(); protected AbstractSWCommand(Class clazz, String command) { @@ -126,20 +125,6 @@ public abstract class AbstractSWCommand { SWCommandUtils.getMAPPER_FUNCTIONS().putIfAbsent(anno.value().getTypeName(), typeMapper); } }); - addGuard(Guard.class, method, i -> i == 0, false, AbstractGuardChecker.class, (anno, guardChecker) -> { - if (anno.local()) { - localGuardChecker.putIfAbsent(anno.value(), (AbstractGuardChecker) guardChecker); - } else { - SWCommandUtils.getGUARD_FUNCTIONS().putIfAbsent(anno.value(), guardChecker); - } - }); - addGuard(ClassGuard.class, method, i -> i == 0, false, AbstractGuardChecker.class, (anno, guardChecker) -> { - if (anno.local()) { - localGuardChecker.putIfAbsent(anno.value().getTypeName(), (AbstractGuardChecker) guardChecker); - } else { - SWCommandUtils.getGUARD_FUNCTIONS().putIfAbsent(anno.value().getTypeName(), guardChecker); - } - }); addValidator(Validator.class, method, i -> i == 0, false, AbstractValidator.class, (anno, validator) -> { if (anno.local()) { localValidators.putIfAbsent(anno.value(), (AbstractValidator) validator); @@ -168,7 +153,7 @@ public abstract class AbstractSWCommand { commandSystemWarning(() -> "The method '" + method.toString() + "' is lacking the varArgs parameters of type '" + String.class.getTypeName() + "' as last Argument"); return; } - commandHelpList.add(new SubCommand<>(this, method, anno.value(), new HashMap<>(), new HashMap<>(), localGuardChecker, true, null, anno.noTabComplete())); + commandHelpList.add(new SubCommand<>(this, method, anno.value(), new HashMap<>(), new HashMap<>(), true, null, anno.noTabComplete())); }); add(Register.class, method, i -> i > 0, true, null, (anno, parameters) -> { @@ -189,7 +174,7 @@ public abstract class AbstractSWCommand { return; } } - commandList.add(new SubCommand<>(this, method, anno.value(), localTypeMapper, localValidators, localGuardChecker, false, anno.description(), anno.noTabComplete())); + commandList.add(new SubCommand<>(this, method, anno.value(), localTypeMapper, localValidators, false, anno.description(), anno.noTabComplete())); }); } @@ -255,18 +240,6 @@ public abstract class AbstractSWCommand { }); } - @Deprecated - private void addGuard(Class annotation, Method method, IntPredicate parameterTester, boolean firstParameter, Class returnType, BiConsumer> consumer) { - add(annotation, method, parameterTester, firstParameter, returnType, (anno, parameters) -> { - try { - method.setAccessible(true); - consumer.accept(anno, (AbstractGuardChecker) method.invoke(this)); - } catch (Exception e) { - throw new SecurityException(e.getMessage(), e); - } - }); - } - // TODO: Implement this when Message System is ready /* public void addDefaultHelpMessage(String message) { @@ -327,24 +300,6 @@ public abstract class AbstractSWCommand { boolean global() default false; } - @Deprecated - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.PARAMETER, ElementType.METHOD}) - protected @interface Guard { - String value() default ""; - - boolean local() default false; - } - - @Deprecated - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.METHOD}) - protected @interface ClassGuard { - Class value(); - - boolean local() default false; - } - @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.PARAMETER, ElementType.METHOD}) protected @interface Validator { diff --git a/src/de/steamwar/command/CommandPart.java b/src/de/steamwar/command/CommandPart.java index d5a5220..f402abe 100644 --- a/src/de/steamwar/command/CommandPart.java +++ b/src/de/steamwar/command/CommandPart.java @@ -42,24 +42,20 @@ class CommandPart { private AbstractSWCommand command; private AbstractTypeMapper typeMapper; private AbstractValidator validator; - private AbstractGuardChecker guardChecker; private Class varArgType; private String optional; - private GuardCheckType guardCheckType; private CommandPart next = null; @Setter private boolean ignoreAsArgument = false; - public CommandPart(AbstractSWCommand command, AbstractTypeMapper typeMapper, AbstractValidator validator, AbstractGuardChecker guardChecker, Class varArgType, String optional, GuardCheckType guardCheckType) { + public CommandPart(AbstractSWCommand command, AbstractTypeMapper typeMapper, AbstractValidator validator, Class varArgType, String optional) { this.command = command; this.typeMapper = typeMapper; this.validator = validator; - this.guardChecker = guardChecker; this.varArgType = varArgType; this.optional = optional; - this.guardCheckType = guardCheckType; validatePart(); } @@ -72,9 +68,6 @@ class CommandPart { } private void validatePart() { - if (guardCheckType == GuardCheckType.TAB_COMPLETE) { - throw new IllegalArgumentException("Tab complete is not allowed as a guard check type!"); - } if (optional != null && varArgType != null) { throw new IllegalArgumentException("A vararg part can't have an optional part!"); } @@ -92,7 +85,7 @@ class CommandPart { if (varArgType != null) { Object array = Array.newInstance(varArgType, args.length - startIndex); for (int i = startIndex; i < args.length; i++) { - CheckArgumentResult validArgument = checkArgument(null, null, sender, args, i); + CheckArgumentResult validArgument = checkArgument(null, sender, args, i); if (!validArgument.success) { throw new CommandParseException(); } @@ -107,7 +100,7 @@ class CommandPart { return; } - CheckArgumentResult validArgument = checkArgument(errors, null, sender, args, startIndex); + CheckArgumentResult validArgument = checkArgument(errors, sender, args, startIndex); if (!validArgument.success && optional == null) { throw new CommandParseException(); } @@ -128,43 +121,10 @@ class CommandPart { } } - public boolean guardCheck(T sender, String[] args, int startIndex) { - if (varArgType != null) { - for (int i = startIndex; i < args.length; i++) { - GuardResult guardResult = checkGuard(guardCheckType, sender, args, i); - if (guardResult == GuardResult.DENIED) { - throw new CommandNoHelpException(); - } - if (guardResult == GuardResult.DENIED_WITH_HELP) { - return false; - } - } - return true; - } - - GuardResult guardResult = checkGuard(guardCheckType, sender, args, startIndex); - if (guardResult == GuardResult.DENIED) { - if (optional != null && next != null) { - return next.guardCheck(sender, args, startIndex); - } - throw new CommandNoHelpException(); - } - if (guardResult == GuardResult.DENIED_WITH_HELP) { - if (optional != null && next != null) { - return next.guardCheck(sender, args, startIndex); - } - return false; - } - if (next != null) { - return next.guardCheck(sender, args, startIndex + 1); - } - return true; - } - public void generateTabComplete(List current, T sender, String[] args, int startIndex) { if (varArgType != null) { for (int i = startIndex; i < args.length - 1; i++) { - CheckArgumentResult validArgument = checkArgument((ignore) -> {}, GuardCheckType.TAB_COMPLETE, sender, args, i); + CheckArgumentResult validArgument = checkArgument((ignore) -> {}, sender, args, i); if (!validArgument.success) { return; } @@ -177,7 +137,7 @@ class CommandPart { } if (args.length - 1 > startIndex) { - CheckArgumentResult checkArgumentResult = checkArgument((ignore) -> {}, GuardCheckType.TAB_COMPLETE, sender, args, startIndex); + CheckArgumentResult checkArgumentResult = checkArgument((ignore) -> {}, sender, args, startIndex); if (checkArgumentResult.success && next != null) { next.generateTabComplete(current, sender, args, startIndex + 1); return; @@ -203,7 +163,7 @@ class CommandPart { }); } - private CheckArgumentResult checkArgument(Consumer errors, GuardCheckType guardCheckType, T sender, String[] args, int index) { + private CheckArgumentResult checkArgument(Consumer errors, T sender, String[] args, int index) { try { Object value = typeMapper.map(sender, Arrays.copyOf(args, index), args[index]); if (validator != null && errors != null) { @@ -216,29 +176,8 @@ class CommandPart { } return new CheckArgumentResult(value != null, value); } - if (value == null) { - return new CheckArgumentResult(false, null); - } - - GuardResult guardResult = checkGuard(guardCheckType, sender, args, index); - switch (guardResult) { - case ALLOWED: - return new CheckArgumentResult(true, value); - case DENIED: - throw new CommandNoHelpException(); - case DENIED_WITH_HELP: - default: - return new CheckArgumentResult(false, null); - } } catch (Exception e) { - return new CheckArgumentResult(false, null); } - } - - private GuardResult checkGuard(GuardCheckType guardCheckType, T sender, String[] args, int index) { - if (guardChecker != null && guardCheckType != null) { - return guardChecker.guard(sender, guardCheckType, Arrays.copyOf(args, index), args[index]); - } - return GuardResult.ALLOWED; + return new CheckArgumentResult(false, null); } } diff --git a/src/de/steamwar/command/GuardCheckType.java b/src/de/steamwar/command/GuardCheckType.java deleted file mode 100644 index d2e6ed0..0000000 --- a/src/de/steamwar/command/GuardCheckType.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2020 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.command; - -@Deprecated -public enum GuardCheckType { - COMMAND, - HELP_COMMAND, - TAB_COMPLETE -} diff --git a/src/de/steamwar/command/GuardResult.java b/src/de/steamwar/command/GuardResult.java deleted file mode 100644 index 3e6aafc..0000000 --- a/src/de/steamwar/command/GuardResult.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2020 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.command; - -@Deprecated -public enum GuardResult { - ALLOWED, - DENIED_WITH_HELP, - DENIED -} diff --git a/src/de/steamwar/command/SWCommandUtils.java b/src/de/steamwar/command/SWCommandUtils.java index 69e0b8c..61845dc 100644 --- a/src/de/steamwar/command/SWCommandUtils.java +++ b/src/de/steamwar/command/SWCommandUtils.java @@ -37,10 +37,6 @@ public class SWCommandUtils { @Getter private final Map> MAPPER_FUNCTIONS = new HashMap<>(); - @Getter - @Deprecated - private final Map> GUARD_FUNCTIONS = new HashMap<>(); - @Getter private final Map> VALIDATOR_FUNCTIONS = new HashMap<>(); @@ -78,11 +74,11 @@ public class SWCommandUtils { MAPPER_FUNCTIONS.put(alternativeClazz.getTypeName(), mapper); } - static CommandPart generateCommandPart(AbstractSWCommand command, boolean help, String[] subCommand, Parameter[] parameters, Map> localTypeMapper, Map> localValidator, Map> localGuardChecker) { + static CommandPart generateCommandPart(AbstractSWCommand command, boolean help, String[] subCommand, Parameter[] parameters, Map> localTypeMapper, Map> localValidator) { CommandPart first = null; CommandPart current = null; for (String s : subCommand) { - CommandPart commandPart = new CommandPart(command, createMapper(s), null, null, null, null, help ? GuardCheckType.HELP_COMMAND : GuardCheckType.COMMAND); + CommandPart commandPart = new CommandPart(command, createMapper(s), null, null, null); commandPart.setIgnoreAsArgument(true); if (current != null) { current.setNext(commandPart); @@ -96,11 +92,10 @@ public class SWCommandUtils { Parameter parameter = parameters[i]; AbstractTypeMapper typeMapper = getTypeMapper(parameter, localTypeMapper); AbstractValidator validator = (AbstractValidator) getValidator(parameter, localValidator); - AbstractGuardChecker guardChecker = getGuardChecker(parameter, localGuardChecker); Class varArgType = parameter.isVarArgs() ? parameter.getType().getComponentType() : null; AbstractSWCommand.OptionalValue optionalValue = parameter.getAnnotation(AbstractSWCommand.OptionalValue.class); - CommandPart commandPart = new CommandPart<>(command, typeMapper, validator, guardChecker, varArgType, optionalValue != null ? optionalValue.value() : null, help ? GuardCheckType.HELP_COMMAND : GuardCheckType.COMMAND); + CommandPart commandPart = new CommandPart<>(command, typeMapper, validator, varArgType, optionalValue != null ? optionalValue.value() : null); if (current != null) { current.setNext(commandPart); } @@ -203,40 +198,6 @@ public class SWCommandUtils { return validator; } - @Deprecated - public static AbstractGuardChecker getGuardChecker(Parameter parameter, Map> localGuardChecker) { - Class clazz = parameter.getType(); - if (parameter.isVarArgs()) { - clazz = clazz.getComponentType(); - } - - AbstractSWCommand.ClassGuard classGuard = parameter.getAnnotation(AbstractSWCommand.ClassGuard.class); - if (classGuard != null) { - if (classGuard.value() != null) { - return getGuardChecker(classGuard.value().getTypeName(), localGuardChecker); - } - return getGuardChecker(clazz.getTypeName(), localGuardChecker); - } - - AbstractSWCommand.Guard guard = parameter.getAnnotation(AbstractSWCommand.Guard.class); - if (guard != null) { - if (guard.value() != null && !guard.value().isEmpty()) { - return getGuardChecker(guard.value(), localGuardChecker); - } - return getGuardChecker(clazz.getTypeName(), localGuardChecker); - } - return null; - } - - @Deprecated - private static AbstractGuardChecker getGuardChecker(String s, Map> localGuardChecker) { - AbstractGuardChecker guardChecker = localGuardChecker.getOrDefault(s, (AbstractGuardChecker) GUARD_FUNCTIONS.getOrDefault(s, null)); - if (guardChecker == null) { - throw new IllegalArgumentException("No guard found for " + s); - } - return guardChecker; - } - public static void addMapper(Class clazz, AbstractTypeMapper mapper) { addMapper(clazz.getTypeName(), mapper); } @@ -253,16 +214,6 @@ public class SWCommandUtils { VALIDATOR_FUNCTIONS.putIfAbsent(name, validator); } - @Deprecated - public static void addGuard(Class clazz, AbstractGuardChecker guardChecker) { - addGuard(clazz.getTypeName(), guardChecker); - } - - @Deprecated - public static void addGuard(String name, AbstractGuardChecker guardChecker) { - GUARD_FUNCTIONS.putIfAbsent(name, guardChecker); - } - public static , K> T createMapper(String... values) { List strings = Arrays.stream(values).map(String::toLowerCase).collect(Collectors.toList()); List tabCompletes = Arrays.asList(values); diff --git a/src/de/steamwar/command/SubCommand.java b/src/de/steamwar/command/SubCommand.java index d3a266c..8626f1d 100644 --- a/src/de/steamwar/command/SubCommand.java +++ b/src/de/steamwar/command/SubCommand.java @@ -38,13 +38,12 @@ public class SubCommand { private Predicate senderPredicate; private Function senderFunction; AbstractValidator validator; - AbstractGuardChecker guardChecker; boolean noTabComplete; int comparableValue; private CommandPart commandPart; - SubCommand(AbstractSWCommand abstractSWCommand, Method method, String[] subCommand, Map> localTypeMapper, Map> localValidator, Map> localGuardChecker, boolean help, String[] description, boolean noTabComplete) { + SubCommand(AbstractSWCommand abstractSWCommand, Method method, String[] subCommand, Map> localTypeMapper, Map> localValidator, boolean help, String[] description, boolean noTabComplete) { this.abstractSWCommand = abstractSWCommand; this.method = method; this.subCommand = subCommand; @@ -55,9 +54,8 @@ public class SubCommand { comparableValue = parameters[parameters.length - 1].isVarArgs() ? Integer.MAX_VALUE : -parameters.length; validator = (AbstractValidator) SWCommandUtils.getValidator(parameters[0], localValidator); - guardChecker = SWCommandUtils.getGuardChecker(parameters[0], localGuardChecker); - commandPart = SWCommandUtils.generateCommandPart(abstractSWCommand, help, subCommand, parameters, localTypeMapper, localValidator, localGuardChecker); + commandPart = SWCommandUtils.generateCommandPart(abstractSWCommand, help, subCommand, parameters, localTypeMapper, localValidator); senderPredicate = t -> parameters[0].getType().isAssignableFrom(t.getClass()); senderFunction = t -> parameters[0].getType().cast(t); @@ -79,17 +77,6 @@ public class SubCommand { })) { throw new CommandNoHelpException(); } - } else if (guardChecker != null) { - GuardResult guardResult = guardChecker.guard(sender, GuardCheckType.COMMAND, new String[0], null); - switch (guardResult) { - case ALLOWED: - break; - case DENIED: - throw new CommandNoHelpException(); - case DENIED_WITH_HELP: - default: - return true; - } } method.setAccessible(true); method.invoke(abstractSWCommand, senderFunction.apply(sender)); @@ -102,19 +89,7 @@ public class SubCommand { })) { throw new CommandNoHelpException(); } - } else if (guardChecker != null) { - GuardResult guardResult = guardChecker.guard(sender, GuardCheckType.COMMAND, new String[0], null); - switch (guardResult) { - case ALLOWED: - break; - case DENIED: - throw new CommandNoHelpException(); - case DENIED_WITH_HELP: - default: - return true; - } } - commandPart.guardCheck(sender, args, 0); objects.add(0, senderFunction.apply(sender)); method.setAccessible(true); method.invoke(abstractSWCommand, objects.toArray()); @@ -138,8 +113,6 @@ public class SubCommand { })) { return null; } - } else if (guardChecker != null && guardChecker.guard(sender, GuardCheckType.TAB_COMPLETE, new String[0], null) != GuardResult.ALLOWED) { - return null; } if (commandPart == null) { return null; diff --git a/testsrc/de/steamwar/command/GuardCommand.java b/testsrc/de/steamwar/command/GuardCommand.java deleted file mode 100644 index 7ee1854..0000000 --- a/testsrc/de/steamwar/command/GuardCommand.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2020 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.command; - -import de.steamwar.command.dto.ExecutionIdentifier; -import de.steamwar.command.dto.TestGuardChecker; -import de.steamwar.command.dto.TestSWCommand; - -public class GuardCommand extends TestSWCommand { - - public GuardCommand() { - super("typemapper"); - } - - @Register - public void test(@Guard String sender) { - throw new ExecutionIdentifier("RunTypeMapper"); - } - - @ClassGuard(value = String.class, local = true) - public AbstractGuardChecker getGuardChecker() { - return (TestGuardChecker) (s, guardCheckType, previousArguments, s2) -> { - throw new ExecutionIdentifier("GuardChecker " + guardCheckType); - }; - } -} diff --git a/testsrc/de/steamwar/command/GuardCommandTest.java b/testsrc/de/steamwar/command/GuardCommandTest.java deleted file mode 100644 index 51eae0e..0000000 --- a/testsrc/de/steamwar/command/GuardCommandTest.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2020 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.command; - -import de.steamwar.command.dto.ExecutionIdentifier; -import org.junit.Test; - -import static de.steamwar.AssertionUtils.assertCMDFramework; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.is; - -public class GuardCommandTest { - - @Test - public void test() { - GuardCommand cmd = new GuardCommand(); - try { - cmd.execute("test", "", new String[0]); - } catch (Exception e) { - assertThat(e.getMessage(), is("GuardChecker COMMAND")); - } - } - - @Test - public void testTabComplete() { - GuardCommand cmd = new GuardCommand(); - try { - cmd.tabComplete("test", "", new String[]{""}); - } catch (Exception e) { - assertThat(e, is(instanceOf(ExecutionIdentifier.class))); - assertThat(e.getMessage(), is("GuardChecker TAB_COMPLETE")); - } - } -} diff --git a/testsrc/de/steamwar/command/dto/TestGuardChecker.java b/testsrc/de/steamwar/command/dto/TestGuardChecker.java deleted file mode 100644 index b85fa17..0000000 --- a/testsrc/de/steamwar/command/dto/TestGuardChecker.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2020 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.command.dto; - -import de.steamwar.command.AbstractGuardChecker; - -public interface TestGuardChecker extends AbstractGuardChecker { -} From 10893388c7755e7d43d7ff35753fedadc2849588 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Wed, 17 Aug 2022 18:11:34 +0200 Subject: [PATCH 09/15] Update AbstractValidator --- .../steamwar/command/AbstractValidator.java | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/de/steamwar/command/AbstractValidator.java b/src/de/steamwar/command/AbstractValidator.java index 60efd19..4614681 100644 --- a/src/de/steamwar/command/AbstractValidator.java +++ b/src/de/steamwar/command/AbstractValidator.java @@ -19,6 +19,12 @@ package de.steamwar.command; +import lombok.AllArgsConstructor; +import lombok.RequiredArgsConstructor; + +import java.security.Provider; +import java.util.function.*; + @FunctionalInterface public interface AbstractValidator { @@ -32,8 +38,52 @@ public interface AbstractValidator { */ boolean validate(K sender, T value, MessageSender messageSender); + default Validator validate(C value, MessageSender messageSender) { + return new Validator<>(value, messageSender); + } + + @RequiredArgsConstructor + class Validator { + private final C value; + private final MessageSender messageSender; + + private boolean valid = true; + + public Validator map(Function mapper) { + return new Validator<>(mapper.apply(value), messageSender).and(ignore -> valid); + } + + public Validator and(Predicate predicate) { + valid &= predicate.test(value); + return this; + } + + public Validator or(Predicate predicate) { + valid |= predicate.test(value); + return this; + } + + public Validator errorMessage(String s, Object... args) { + if (!valid) messageSender.send(s, args); + return this; + } + + public boolean result() { + return valid; + } + } + @FunctionalInterface interface MessageSender { void send(String s, Object... args); + + default boolean send(boolean condition, String s, Object... args) { + if (condition) send(s, args); + return condition; + } + + default boolean send(BooleanSupplier condition, String s, Object... args) { + return send(condition.getAsBoolean(), s, args); + } } } From a4ac3fa8f011c2d683b84099d5aa7efd3da86c54 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Wed, 17 Aug 2022 18:25:08 +0200 Subject: [PATCH 10/15] Remove unused imports --- src/de/steamwar/command/AbstractValidator.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/de/steamwar/command/AbstractValidator.java b/src/de/steamwar/command/AbstractValidator.java index 4614681..b0340e3 100644 --- a/src/de/steamwar/command/AbstractValidator.java +++ b/src/de/steamwar/command/AbstractValidator.java @@ -19,11 +19,11 @@ package de.steamwar.command; -import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor; -import java.security.Provider; -import java.util.function.*; +import java.util.function.BooleanSupplier; +import java.util.function.Function; +import java.util.function.Predicate; @FunctionalInterface public interface AbstractValidator { From 21cb3b266a67f8f14f6d68e260a793de2f2f9141 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Wed, 17 Aug 2022 18:35:59 +0200 Subject: [PATCH 11/15] Add AbstractValidator.Validator.set --- src/de/steamwar/command/AbstractValidator.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/de/steamwar/command/AbstractValidator.java b/src/de/steamwar/command/AbstractValidator.java index b0340e3..aab4876 100644 --- a/src/de/steamwar/command/AbstractValidator.java +++ b/src/de/steamwar/command/AbstractValidator.java @@ -50,7 +50,12 @@ public interface AbstractValidator { private boolean valid = true; public Validator map(Function mapper) { - return new Validator<>(mapper.apply(value), messageSender).and(ignore -> valid); + return new Validator<>(mapper.apply(value), messageSender).set(valid); + } + + public Validator set(boolean value) { + this.valid = value; + return this; } public Validator and(Predicate predicate) { From 3829cd6706ab6ee9d22f4684b135b5e7eca1d6b6 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Mon, 22 Aug 2022 18:07:35 +0200 Subject: [PATCH 12/15] Add AbstractSWCommand.OptionalValue.onlyUINIG --- src/de/steamwar/command/AbstractSWCommand.java | 5 +++++ src/de/steamwar/command/CommandPart.java | 10 ++++++++-- src/de/steamwar/command/SWCommandUtils.java | 1 + 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/de/steamwar/command/AbstractSWCommand.java b/src/de/steamwar/command/AbstractSWCommand.java index aa33a64..5a4a10a 100644 --- a/src/de/steamwar/command/AbstractSWCommand.java +++ b/src/de/steamwar/command/AbstractSWCommand.java @@ -386,6 +386,11 @@ public abstract class AbstractSWCommand { * Will pe parsed against the TypeMapper specified by the parameter or annotation. */ String value(); + + /** + * The method name stands for 'onlyUseIfNoneIsGiven'. + */ + boolean onlyUINIG() default false; } @Retention(RetentionPolicy.RUNTIME) diff --git a/src/de/steamwar/command/CommandPart.java b/src/de/steamwar/command/CommandPart.java index d5a5220..14b4079 100644 --- a/src/de/steamwar/command/CommandPart.java +++ b/src/de/steamwar/command/CommandPart.java @@ -23,7 +23,6 @@ import lombok.AllArgsConstructor; import lombok.Setter; import java.lang.reflect.Array; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -52,6 +51,9 @@ class CommandPart { @Setter private boolean ignoreAsArgument = false; + @Setter + private boolean onlyUseIfNoneIsGiven = false; + public CommandPart(AbstractSWCommand command, AbstractTypeMapper typeMapper, AbstractValidator validator, AbstractGuardChecker guardChecker, Class varArgType, String optional, GuardCheckType guardCheckType) { this.command = command; this.typeMapper = typeMapper; @@ -113,7 +115,11 @@ class CommandPart { } if (!validArgument.success) { if (!ignoreAsArgument) { - current.add(typeMapper.map(sender, EMPTY_ARRAY, optional)); + if (!onlyUseIfNoneIsGiven) { + current.add(typeMapper.map(sender, EMPTY_ARRAY, optional)); + } else if(startIndex >= args.length) { + current.add(typeMapper.map(sender, EMPTY_ARRAY, optional)); + } } if (next != null) { next.generateArgumentArray(errors, current, sender, args, startIndex); diff --git a/src/de/steamwar/command/SWCommandUtils.java b/src/de/steamwar/command/SWCommandUtils.java index 69e0b8c..e1266bd 100644 --- a/src/de/steamwar/command/SWCommandUtils.java +++ b/src/de/steamwar/command/SWCommandUtils.java @@ -101,6 +101,7 @@ public class SWCommandUtils { AbstractSWCommand.OptionalValue optionalValue = parameter.getAnnotation(AbstractSWCommand.OptionalValue.class); CommandPart commandPart = new CommandPart<>(command, typeMapper, validator, guardChecker, varArgType, optionalValue != null ? optionalValue.value() : null, help ? GuardCheckType.HELP_COMMAND : GuardCheckType.COMMAND); + commandPart.setOnlyUseIfNoneIsGiven(optionalValue != null && optionalValue.onlyUINIG()); if (current != null) { current.setNext(commandPart); } From 2c6ebc82f3d8177191bcd7444dfe9607c35c952b Mon Sep 17 00:00:00 2001 From: yoyosource Date: Mon, 22 Aug 2022 18:30:23 +0200 Subject: [PATCH 13/15] Fix internal error --- src/de/steamwar/command/CommandPart.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/de/steamwar/command/CommandPart.java b/src/de/steamwar/command/CommandPart.java index 14b4079..09b8303 100644 --- a/src/de/steamwar/command/CommandPart.java +++ b/src/de/steamwar/command/CommandPart.java @@ -119,6 +119,8 @@ class CommandPart { current.add(typeMapper.map(sender, EMPTY_ARRAY, optional)); } else if(startIndex >= args.length) { current.add(typeMapper.map(sender, EMPTY_ARRAY, optional)); + } else { + throw new CommandParseException(); } } if (next != null) { From 3701f6f5ff10fa97d6816d5f57c85f7213f7fb3e Mon Sep 17 00:00:00 2001 From: yoyosource Date: Mon, 22 Aug 2022 21:06:10 +0200 Subject: [PATCH 14/15] Fix validators --- src/de/steamwar/command/CommandPart.java | 4 ++-- src/de/steamwar/command/SubCommand.java | 4 ++-- testsrc/de/steamwar/command/ValidatorCommand.java | 2 ++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/de/steamwar/command/CommandPart.java b/src/de/steamwar/command/CommandPart.java index 7ecdb58..4931ef0 100644 --- a/src/de/steamwar/command/CommandPart.java +++ b/src/de/steamwar/command/CommandPart.java @@ -182,10 +182,10 @@ class CommandPart { })) { return new CheckArgumentResult(false, null); } - return new CheckArgumentResult(value != null, value); } + return new CheckArgumentResult(value != null, value); } catch (Exception e) { + return new CheckArgumentResult(false, null); } - return new CheckArgumentResult(false, null); } } diff --git a/src/de/steamwar/command/SubCommand.java b/src/de/steamwar/command/SubCommand.java index 8626f1d..9a497e5 100644 --- a/src/de/steamwar/command/SubCommand.java +++ b/src/de/steamwar/command/SubCommand.java @@ -75,7 +75,7 @@ public class SubCommand { if (!validator.validate(sender, sender, (s, objectArgs) -> { abstractSWCommand.sendMessage(sender, s, objectArgs); })) { - throw new CommandNoHelpException(); + return false; } } method.setAccessible(true); @@ -87,7 +87,7 @@ public class SubCommand { if (!validator.validate(sender, sender, (s, objectArgs) -> { abstractSWCommand.sendMessage(sender, s, objectArgs); })) { - throw new CommandNoHelpException(); + return false; } } objects.add(0, senderFunction.apply(sender)); diff --git a/testsrc/de/steamwar/command/ValidatorCommand.java b/testsrc/de/steamwar/command/ValidatorCommand.java index ea95a5e..b0e4a36 100644 --- a/testsrc/de/steamwar/command/ValidatorCommand.java +++ b/testsrc/de/steamwar/command/ValidatorCommand.java @@ -43,11 +43,13 @@ public class ValidatorCommand extends TestSWCommand { @Register public void onError(String sender, @ErrorMessage("Hello World") int error) { + System.out.println("onError: " + sender + " " + error); throw new ExecutionIdentifier("RunOnError"); } @Register public void onError(String sender, double error) { + System.out.println("onError: " + sender + " " + error); throw new ExecutionIdentifier("RunOnErrorDouble"); } From 59361e14c0637599231760d4392782e6a9c91c28 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Sat, 27 Aug 2022 18:03:16 +0200 Subject: [PATCH 15/15] Add AbstractSWCommand.AllowNull --- .../steamwar/command/AbstractSWCommand.java | 8 ++- src/de/steamwar/command/CommandPart.java | 5 +- src/de/steamwar/command/SWCommandUtils.java | 2 + .../steamwar/command/NullMapperCommand.java | 59 +++++++++++++++++++ .../command/NullMapperCommandTest.java | 52 ++++++++++++++++ 5 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 testsrc/de/steamwar/command/NullMapperCommand.java create mode 100644 testsrc/de/steamwar/command/NullMapperCommandTest.java diff --git a/src/de/steamwar/command/AbstractSWCommand.java b/src/de/steamwar/command/AbstractSWCommand.java index def1527..e30ac7b 100644 --- a/src/de/steamwar/command/AbstractSWCommand.java +++ b/src/de/steamwar/command/AbstractSWCommand.java @@ -76,7 +76,8 @@ public abstract class AbstractSWCommand { errors.forEach(Runnable::run); return; } - commandHelpList.stream().anyMatch(s -> s.invoke((ignore) -> {}, sender, alias, args)); + commandHelpList.stream().anyMatch(s -> s.invoke((ignore) -> { + }, sender, alias, args)); } } catch (CommandNoHelpException e) { // Ignored @@ -361,4 +362,9 @@ public abstract class AbstractSWCommand { */ boolean allowEAs() default true; } + + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.PARAMETER}) + protected @interface AllowNull { + } } diff --git a/src/de/steamwar/command/CommandPart.java b/src/de/steamwar/command/CommandPart.java index 4931ef0..80f0048 100644 --- a/src/de/steamwar/command/CommandPart.java +++ b/src/de/steamwar/command/CommandPart.java @@ -52,6 +52,9 @@ class CommandPart { @Setter private boolean onlyUseIfNoneIsGiven = false; + @Setter + private boolean allowNullValues = false; + public CommandPart(AbstractSWCommand command, AbstractTypeMapper typeMapper, AbstractValidator validator, Class varArgType, String optional) { this.command = command; this.typeMapper = typeMapper; @@ -183,7 +186,7 @@ class CommandPart { return new CheckArgumentResult(false, null); } } - return new CheckArgumentResult(value != null, value); + return new CheckArgumentResult(allowNullValues || value != null, value); } catch (Exception e) { return new CheckArgumentResult(false, null); } diff --git a/src/de/steamwar/command/SWCommandUtils.java b/src/de/steamwar/command/SWCommandUtils.java index 0005949..f6aa8f3 100644 --- a/src/de/steamwar/command/SWCommandUtils.java +++ b/src/de/steamwar/command/SWCommandUtils.java @@ -94,9 +94,11 @@ public class SWCommandUtils { AbstractValidator validator = (AbstractValidator) getValidator(parameter, localValidator); Class varArgType = parameter.isVarArgs() ? parameter.getType().getComponentType() : null; AbstractSWCommand.OptionalValue optionalValue = parameter.getAnnotation(AbstractSWCommand.OptionalValue.class); + AbstractSWCommand.AllowNull allowNull = parameter.getAnnotation(AbstractSWCommand.AllowNull.class); CommandPart commandPart = new CommandPart<>(command, typeMapper, validator, varArgType, optionalValue != null ? optionalValue.value() : null); commandPart.setOnlyUseIfNoneIsGiven(optionalValue != null && optionalValue.onlyUINIG()); + commandPart.setAllowNullValues(allowNull != null); if (current != null) { current.setNext(commandPart); } diff --git a/testsrc/de/steamwar/command/NullMapperCommand.java b/testsrc/de/steamwar/command/NullMapperCommand.java new file mode 100644 index 0000000..e47eab7 --- /dev/null +++ b/testsrc/de/steamwar/command/NullMapperCommand.java @@ -0,0 +1,59 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.command; + +import de.steamwar.command.dto.ExecutionIdentifier; +import de.steamwar.command.dto.TestSWCommand; +import de.steamwar.command.dto.TestTypeMapper; + +import java.util.Collection; + +public class NullMapperCommand extends TestSWCommand { + + public NullMapperCommand() { + super("nullmapper"); + } + + @Register + public void test(String sender, @AllowNull String arg) { + if (arg == null) { + throw new ExecutionIdentifier("null"); + } + throw new ExecutionIdentifier("notnull"); + } + + @ClassMapper(value = String.class, local = true) + public TestTypeMapper typeMapper() { + return new TestTypeMapper() { + @Override + public String map(String sender, String[] previousArguments, String s) { + if (s.equals("Hello World")) { + return null; + } + return s; + } + + @Override + public Collection tabCompletes(String sender, String[] previousArguments, String s) { + return null; + } + }; + } +} diff --git a/testsrc/de/steamwar/command/NullMapperCommandTest.java b/testsrc/de/steamwar/command/NullMapperCommandTest.java new file mode 100644 index 0000000..1e19d13 --- /dev/null +++ b/testsrc/de/steamwar/command/NullMapperCommandTest.java @@ -0,0 +1,52 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.command; + +import de.steamwar.command.dto.ExecutionIdentifier; +import org.junit.Test; + +import static de.steamwar.AssertionUtils.assertCMDFramework; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +public class NullMapperCommandTest { + + @Test + public void testNull() { + NullMapperCommand command = new NullMapperCommand(); + try { + command.execute("test", "", new String[] {"Hello World"}); + assertThat(true, is(false)); + } catch (Exception e) { + assertCMDFramework(e, ExecutionIdentifier.class, "null"); + } + } + + @Test + public void testNonNull() { + NullMapperCommand command = new NullMapperCommand(); + try { + command.execute("test", "", new String[] {"Hello"}); + assertThat(true, is(false)); + } catch (Exception e) { + assertCMDFramework(e, ExecutionIdentifier.class, "notnull"); + } + } +}