From cdd703efa44d4b4ad6bc9ce4e475e96a7dc09cf0 Mon Sep 17 00:00:00 2001 From: Janne Valkealahti Date: Thu, 22 Jun 2023 16:00:00 +0100 Subject: [PATCH] Fix alias usage with Command annotation - Fix alias command extraction from existing @Command annotations so that we actually get multiple aliases defined if more than one defined on a method level. - Fix rendering issue in a help stg template when multiple aliases exists. - Fixes #796 --- .../support/CommandAnnotationUtils.java | 23 +++++++++-- .../CommandRegistrationFactoryBean.java | 6 +-- .../support/CommandAnnotationUtilsTests.java | 8 ++-- .../CommandRegistrationFactoryBeanTests.java | 21 +++++++++- .../shell/samples/e2e/AliasCommands.java | 40 +++++++++++++++++++ .../template/help-command-default.stg | 2 +- 6 files changed, 87 insertions(+), 13 deletions(-) diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/support/CommandAnnotationUtils.java b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/support/CommandAnnotationUtils.java index f857ceff..c679c684 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/support/CommandAnnotationUtils.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/support/CommandAnnotationUtils.java @@ -15,6 +15,8 @@ */ package org.springframework.shell.command.annotation.support; +import java.util.List; +import java.util.stream.Collectors; import java.util.stream.Stream; import org.springframework.core.annotation.MergedAnnotation; @@ -85,10 +87,10 @@ class CommandAnnotationUtils { * * @param left the left side annotation * @param right the right side annotation - * @return deduced boolean for alias field + * @return deduced arrays for alias field */ - static String[] deduceAlias(MergedAnnotation left, MergedAnnotation right) { - return deduceStringArray(ALIAS, left, right); + static String[][] deduceAlias(MergedAnnotation left, MergedAnnotation right) { + return deduceStringArrayLeftPrefixes(ALIAS, left, right); } /** @@ -149,6 +151,21 @@ class CommandAnnotationUtils { return mode; } + private static String[][] deduceStringArrayLeftPrefixes(String field, MergedAnnotation left, MergedAnnotation right) { + List prefix = Stream.of(left.getStringArray(field)) + .flatMap(command -> Stream.of(command.split(" "))) + .filter(command -> StringUtils.hasText(command)) + .map(command -> command.strip()) + .collect(Collectors.toList()); + + return Stream.of(right.getStringArray(field)) + .flatMap(command -> Stream.of(command.split(" "))) + .filter(command -> StringUtils.hasText(command)) + .map(command -> command.strip()) + .map(command -> Stream.concat(prefix.stream(), Stream.of(command)).collect(Collectors.toList())) + .map(arr -> arr.toArray(String[]::new)) + .toArray(String[][]::new); + } private static String[] deduceStringArray(String field, MergedAnnotation left, MergedAnnotation right) { return Stream.of(left.getStringArray(field), right.getStringArray(field)) diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/support/CommandRegistrationFactoryBean.java b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/support/CommandRegistrationFactoryBean.java index 741acda6..7cefcdf9 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/support/CommandRegistrationFactoryBean.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/support/CommandRegistrationFactoryBean.java @@ -189,9 +189,9 @@ class CommandRegistrationFactoryBean implements FactoryBean } // alias - String[] deduceAlias = CommandAnnotationUtils.deduceAlias(classAnn, methodAnn); - if (deduceAlias.length > 0) { - builder.withAlias().command(deduceAlias); + String[][] deduceAlias = CommandAnnotationUtils.deduceAlias(classAnn, methodAnn); + for (String[] a : deduceAlias) { + builder.withAlias().command(a); } // target diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/support/CommandAnnotationUtilsTests.java b/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/support/CommandAnnotationUtilsTests.java index 895f7f30..526cace6 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/support/CommandAnnotationUtilsTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/support/CommandAnnotationUtilsTests.java @@ -133,13 +133,13 @@ class CommandAnnotationUtilsTests { void testAlias() { assertThat(CommandAnnotationUtils.deduceAlias(aliasDefault, aliasDefault)).isEmpty(); assertThat(CommandAnnotationUtils.deduceAlias(aliasDefault, aliasValues1)) - .isEqualTo(new String[] { "one", "two" }); + .isEqualTo(new String[][] { { "one" }, { "two" } }); assertThat(CommandAnnotationUtils.deduceAlias(aliasValues1, aliasValues2)) - .isEqualTo(new String[] { "one", "two", "three", "four" }); + .isEqualTo(new String[][] { { "one", "two", "three" }, { "one", "two", "four" } }); assertThat(CommandAnnotationUtils.deduceAlias(aliasDefault, aliasValues3)) - .isEqualTo(new String[] { "five", "six", "seven" }); + .isEqualTo(new String[][] { { "five" }, { "six" }, { "seven" } }); assertThat(CommandAnnotationUtils.deduceAlias(aliasDefault, aliasValues4)) - .isEqualTo(new String[] { "eight", "nine" }); + .isEqualTo(new String[][] { { "eight" }, { "nine" } }); } private static MergedAnnotation groupValue1 = MergedAnnotations.from(GroupValues1.class) diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/support/CommandRegistrationFactoryBeanTests.java b/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/support/CommandRegistrationFactoryBeanTests.java index 5a5a62f9..e4892e4b 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/support/CommandRegistrationFactoryBeanTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/support/CommandRegistrationFactoryBeanTests.java @@ -63,7 +63,7 @@ class CommandRegistrationFactoryBeanTests { @Test void commandCommonThings() { - configCommon(OnBothClassAndMethod.class, new OnBothClassAndMethod()) + configCommon(OnBothClassAndMethod.class, new OnBothClassAndMethod(), "command1", new Class[] { }) .run((context) -> { CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, CommandRegistrationFactoryBean.class); @@ -75,13 +75,30 @@ class CommandRegistrationFactoryBeanTests { assertThat(registration.getAliases().get(0).getCommand()).isEqualTo("three four"); assertThat(registration.getGroup()).isEqualTo("group2"); }); + configCommon(OnBothClassAndMethod.class, new OnBothClassAndMethod(), "command2", new Class[] { }) + .run((context) -> { + CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, + CommandRegistrationFactoryBean.class); + assertThat(fb).isNotNull(); + CommandRegistration registration = fb.getObject(); + assertThat(registration).isNotNull(); + assertThat(registration.getCommand()).isEqualTo("one three"); + assertThat(registration.getAliases()).hasSize(2); + assertThat(registration.getAliases().get(0).getCommand()).isEqualTo("three four"); + assertThat(registration.getAliases().get(1).getCommand()).isEqualTo("three five"); + assertThat(registration.getGroup()).isEqualTo("group2"); + }); } @Command(command = "one", alias = "three", group = "group1") private static class OnBothClassAndMethod { @Command(command = "two", alias = "four", group = "group2") - void command(){ + void command1(){ + } + + @Command(command = "three", alias = { "four", "five" }, group = "group2") + void command2(){ } } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/AliasCommands.java b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/AliasCommands.java index 3f8625e5..661b0c4f 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/AliasCommands.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/AliasCommands.java @@ -18,10 +18,26 @@ package org.springframework.shell.samples.e2e; import org.springframework.context.annotation.Bean; import org.springframework.shell.command.CommandRegistration; import org.springframework.shell.command.annotation.Command; +import org.springframework.shell.standard.ShellComponent; +import org.springframework.shell.standard.ShellMethod; import org.springframework.stereotype.Component; public class AliasCommands { + @ShellComponent + public static class LegacyAnnotation extends BaseE2ECommands { + + @ShellMethod(key = { LEGACY_ANNO + "alias-1", LEGACY_ANNO + "aliasfor-1" }, group = GROUP) + public String testAlias1LegacyAnnotation() { + return "Hello from alias command"; + } + + @ShellMethod(key = { LEGACY_ANNO + "alias-2", LEGACY_ANNO + "alias1for-2", LEGACY_ANNO + "alias2for-2" }, group = GROUP) + public String testAlias2LegacyAnnotation() { + return "Hello from alias command"; + } + } + @Command(command = BaseE2ECommands.ANNO, alias = BaseE2ECommands.ANNO, group = BaseE2ECommands.GROUP) public static class AliasCommandsAnnotation extends BaseE2ECommands { @@ -29,6 +45,11 @@ public class AliasCommands { public String testAlias1Annotation() { return "Hello from alias command"; } + + @Command(command = "alias-2", alias = { "alias1for-2", "alias2for-2" }) + public String testAlias2Annotation() { + return "Hello from alias command"; + } } @Component @@ -49,6 +70,25 @@ public class AliasCommands { .and() .build(); } + + @Bean + public CommandRegistration testAlias2Registration(CommandRegistration.BuilderSupplier builder) { + return builder.get() + .command(REG, "alias-2") + .group(GROUP) + .withAlias() + .command(REG, "alias1for-2") + .and() + .withAlias() + .command(REG, "alias2for-2") + .and() + .withTarget() + .function(ctx -> { + return "Hello from alias command"; + }) + .and() + .build(); + } } } diff --git a/spring-shell-standard-commands/src/main/resources/template/help-command-default.stg b/spring-shell-standard-commands/src/main/resources/template/help-command-default.stg index 044633c2..4242b743 100644 --- a/spring-shell-standard-commands/src/main/resources/template/help-command-default.stg +++ b/spring-shell-standard-commands/src/main/resources/template/help-command-default.stg @@ -70,7 +70,7 @@ availability(availability) ::= << aliases(aliases) ::= << <("ALSO KNOWN AS"); format="style-highlight"> - <(aliases); separator=", "> + }; separator=", "> >>