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
This commit is contained in:
Janne Valkealahti
2023-06-22 16:00:00 +01:00
parent 811f1f9a55
commit cdd703efa4
6 changed files with 87 additions and 13 deletions

View File

@@ -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<String> 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))

View File

@@ -189,9 +189,9 @@ class CommandRegistrationFactoryBean implements FactoryBean<CommandRegistration>
}
// 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

View File

@@ -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<Command> groupValue1 = MergedAnnotations.from(GroupValues1.class)

View File

@@ -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(){
}
}