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:
@@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.shell.command.annotation.support;
|
package org.springframework.shell.command.annotation.support;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.springframework.core.annotation.MergedAnnotation;
|
import org.springframework.core.annotation.MergedAnnotation;
|
||||||
@@ -85,10 +87,10 @@ class CommandAnnotationUtils {
|
|||||||
*
|
*
|
||||||
* @param left the left side annotation
|
* @param left the left side annotation
|
||||||
* @param right the right 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) {
|
static String[][] deduceAlias(MergedAnnotation<?> left, MergedAnnotation<?> right) {
|
||||||
return deduceStringArray(ALIAS, left, right);
|
return deduceStringArrayLeftPrefixes(ALIAS, left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -149,6 +151,21 @@ class CommandAnnotationUtils {
|
|||||||
return mode;
|
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) {
|
private static String[] deduceStringArray(String field, MergedAnnotation<?> left, MergedAnnotation<?> right) {
|
||||||
return Stream.of(left.getStringArray(field), right.getStringArray(field))
|
return Stream.of(left.getStringArray(field), right.getStringArray(field))
|
||||||
|
|||||||
@@ -189,9 +189,9 @@ class CommandRegistrationFactoryBean implements FactoryBean<CommandRegistration>
|
|||||||
}
|
}
|
||||||
|
|
||||||
// alias
|
// alias
|
||||||
String[] deduceAlias = CommandAnnotationUtils.deduceAlias(classAnn, methodAnn);
|
String[][] deduceAlias = CommandAnnotationUtils.deduceAlias(classAnn, methodAnn);
|
||||||
if (deduceAlias.length > 0) {
|
for (String[] a : deduceAlias) {
|
||||||
builder.withAlias().command(deduceAlias);
|
builder.withAlias().command(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
// target
|
// target
|
||||||
|
|||||||
@@ -133,13 +133,13 @@ class CommandAnnotationUtilsTests {
|
|||||||
void testAlias() {
|
void testAlias() {
|
||||||
assertThat(CommandAnnotationUtils.deduceAlias(aliasDefault, aliasDefault)).isEmpty();
|
assertThat(CommandAnnotationUtils.deduceAlias(aliasDefault, aliasDefault)).isEmpty();
|
||||||
assertThat(CommandAnnotationUtils.deduceAlias(aliasDefault, aliasValues1))
|
assertThat(CommandAnnotationUtils.deduceAlias(aliasDefault, aliasValues1))
|
||||||
.isEqualTo(new String[] { "one", "two" });
|
.isEqualTo(new String[][] { { "one" }, { "two" } });
|
||||||
assertThat(CommandAnnotationUtils.deduceAlias(aliasValues1, aliasValues2))
|
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))
|
assertThat(CommandAnnotationUtils.deduceAlias(aliasDefault, aliasValues3))
|
||||||
.isEqualTo(new String[] { "five", "six", "seven" });
|
.isEqualTo(new String[][] { { "five" }, { "six" }, { "seven" } });
|
||||||
assertThat(CommandAnnotationUtils.deduceAlias(aliasDefault, aliasValues4))
|
assertThat(CommandAnnotationUtils.deduceAlias(aliasDefault, aliasValues4))
|
||||||
.isEqualTo(new String[] { "eight", "nine" });
|
.isEqualTo(new String[][] { { "eight" }, { "nine" } });
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MergedAnnotation<Command> groupValue1 = MergedAnnotations.from(GroupValues1.class)
|
private static MergedAnnotation<Command> groupValue1 = MergedAnnotations.from(GroupValues1.class)
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ class CommandRegistrationFactoryBeanTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void commandCommonThings() {
|
void commandCommonThings() {
|
||||||
configCommon(OnBothClassAndMethod.class, new OnBothClassAndMethod())
|
configCommon(OnBothClassAndMethod.class, new OnBothClassAndMethod(), "command1", new Class[] { })
|
||||||
.run((context) -> {
|
.run((context) -> {
|
||||||
CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF,
|
CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF,
|
||||||
CommandRegistrationFactoryBean.class);
|
CommandRegistrationFactoryBean.class);
|
||||||
@@ -75,13 +75,30 @@ class CommandRegistrationFactoryBeanTests {
|
|||||||
assertThat(registration.getAliases().get(0).getCommand()).isEqualTo("three four");
|
assertThat(registration.getAliases().get(0).getCommand()).isEqualTo("three four");
|
||||||
assertThat(registration.getGroup()).isEqualTo("group2");
|
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")
|
@Command(command = "one", alias = "three", group = "group1")
|
||||||
private static class OnBothClassAndMethod {
|
private static class OnBothClassAndMethod {
|
||||||
|
|
||||||
@Command(command = "two", alias = "four", group = "group2")
|
@Command(command = "two", alias = "four", group = "group2")
|
||||||
void command(){
|
void command1(){
|
||||||
|
}
|
||||||
|
|
||||||
|
@Command(command = "three", alias = { "four", "five" }, group = "group2")
|
||||||
|
void command2(){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,10 +18,26 @@ package org.springframework.shell.samples.e2e;
|
|||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.shell.command.CommandRegistration;
|
import org.springframework.shell.command.CommandRegistration;
|
||||||
import org.springframework.shell.command.annotation.Command;
|
import org.springframework.shell.command.annotation.Command;
|
||||||
|
import org.springframework.shell.standard.ShellComponent;
|
||||||
|
import org.springframework.shell.standard.ShellMethod;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
public class AliasCommands {
|
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)
|
@Command(command = BaseE2ECommands.ANNO, alias = BaseE2ECommands.ANNO, group = BaseE2ECommands.GROUP)
|
||||||
public static class AliasCommandsAnnotation extends BaseE2ECommands {
|
public static class AliasCommandsAnnotation extends BaseE2ECommands {
|
||||||
|
|
||||||
@@ -29,6 +45,11 @@ public class AliasCommands {
|
|||||||
public String testAlias1Annotation() {
|
public String testAlias1Annotation() {
|
||||||
return "Hello from alias command";
|
return "Hello from alias command";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Command(command = "alias-2", alias = { "alias1for-2", "alias2for-2" })
|
||||||
|
public String testAlias2Annotation() {
|
||||||
|
return "Hello from alias command";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@@ -49,6 +70,25 @@ public class AliasCommands {
|
|||||||
.and()
|
.and()
|
||||||
.build();
|
.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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ availability(availability) ::= <<
|
|||||||
aliases(aliases) ::= <<
|
aliases(aliases) ::= <<
|
||||||
<if(aliases)>
|
<if(aliases)>
|
||||||
<("ALSO KNOWN AS"); format="style-highlight">
|
<("ALSO KNOWN AS"); format="style-highlight">
|
||||||
<(aliases); separator=", ">
|
<aliases: { a | <a>}; separator=", ">
|
||||||
<endif>
|
<endif>
|
||||||
>>
|
>>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user