From 75ff6e976f52bc68536b5adb592d58ce42c7c9a4 Mon Sep 17 00:00:00 2001 From: Janne Valkealahti Date: Wed, 11 May 2022 07:16:00 +0100 Subject: [PATCH] Fix use of default values - Change parsing to extract and use option default value and also hook it with @ShellOption. - Fixes #409 --- .../shell/command/CommandParser.java | 16 +++++++++ .../shell/command/CommandExecutionTests.java | 19 ++++++++++ .../StandardMethodTargetRegistrar.java | 4 +++ .../StandardMethodTargetRegistrarTests.java | 36 +++++++++++++++++++ 4 files changed, 75 insertions(+) diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandParser.java b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandParser.java index ca78e195..710207ea 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandParser.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandParser.java @@ -18,6 +18,7 @@ package org.springframework.shell.command; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Comparator; import java.util.Deque; import java.util.List; @@ -313,6 +314,21 @@ public interface CommandParser { } }) .collect(Collectors.toList()); + + // Check options which didn't get matched and add parser result + // for those having default value. + List defaultValueOptionsToCheck = new ArrayList<>(options); + results.stream() + .forEach(pr -> { + if (pr.option != null) { + defaultValueOptionsToCheck.remove(pr.option); + } + }); + defaultValueOptionsToCheck.stream() + .filter(co -> co.getDefaultValue() != null) + .forEach(co -> { + results.add(ParserResult.of(co, Collections.emptyList(), co.getDefaultValue(), null)); + }); return ParserResults.of(results); } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/CommandExecutionTests.java b/spring-shell-core/src/test/java/org/springframework/shell/command/CommandExecutionTests.java index 811b1a45..da43ecfc 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/CommandExecutionTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/CommandExecutionTests.java @@ -421,6 +421,25 @@ public class CommandExecutionTests extends AbstractCommandTests { assertThat(pojo1.method4Arg1).isNull(); } + @Test + public void testDefaultValue() { + CommandRegistration r1 = CommandRegistration.builder() + .command("command1") + .withOption() + .longNames("arg1") + .defaultValue("defaultValue1") + // .position(0) + // .arity(OptionArity.EXACTLY_ONE) + .and() + .withTarget() + .method(pojo1, "method4") + .and() + .build(); + execution.evaluate(r1, new String[]{}); + assertThat(pojo1.method4Count).isEqualTo(1); + assertThat(pojo1.method4Arg1).isEqualTo("defaultValue1"); + } + @Test public void testRequiredArg() { CommandRegistration r1 = CommandRegistration.builder() diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/StandardMethodTargetRegistrar.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/StandardMethodTargetRegistrar.java index 949fae78..6b6cb3f4 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/StandardMethodTargetRegistrar.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/StandardMethodTargetRegistrar.java @@ -131,6 +131,10 @@ public class StandardMethodTargetRegistrar implements MethodTargetRegistrar, App if (so.arity() > -1) { optionSpec.arity(0, so.arity()); } + if (!ObjectUtils.nullSafeEquals(so.defaultValue(), ShellOption.NONE) + && !ObjectUtils.nullSafeEquals(so.defaultValue(), ShellOption.NULL)) { + optionSpec.defaultValue(so.defaultValue()); + } } } else { diff --git a/spring-shell-standard/src/test/java/org/springframework/shell/standard/StandardMethodTargetRegistrarTests.java b/spring-shell-standard/src/test/java/org/springframework/shell/standard/StandardMethodTargetRegistrarTests.java index f3de4d8a..36d028d7 100644 --- a/spring-shell-standard/src/test/java/org/springframework/shell/standard/StandardMethodTargetRegistrarTests.java +++ b/spring-shell-standard/src/test/java/org/springframework/shell/standard/StandardMethodTargetRegistrarTests.java @@ -323,4 +323,40 @@ public class StandardMethodTargetRegistrarTests { public void foo3() { } } + + @Test + public void testOptionUseDefaultValue() { + shellContext.setInteractionMode(InteractionMode.NONINTERACTIVE); + applicationContext = new AnnotationConfigApplicationContext(DefaultValuesCommands.class); + registrar.setApplicationContext(applicationContext); + registrar.register(catalog); + + assertThat(catalog.getRegistrations().get("foo1")).isNotNull(); + assertThat(catalog.getRegistrations().get("foo1").getOptions()).hasSize(1); + assertThat(catalog.getRegistrations().get("foo1").getOptions().get(0).getDefaultValue()).isEqualTo("arg1Value"); + + assertThat(catalog.getRegistrations().get("foo2")).isNotNull(); + assertThat(catalog.getRegistrations().get("foo2").getOptions()).hasSize(1); + assertThat(catalog.getRegistrations().get("foo2").getOptions().get(0).getDefaultValue()).isNull(); + + assertThat(catalog.getRegistrations().get("foo3")).isNotNull(); + assertThat(catalog.getRegistrations().get("foo3").getOptions()).hasSize(1); + assertThat(catalog.getRegistrations().get("foo3").getOptions().get(0).getDefaultValue()).isNull(); + } + + @ShellComponent + public static class DefaultValuesCommands { + + @ShellMethod(value = "foo1") + public void foo1(@ShellOption(defaultValue = "arg1Value") String arg1) { + } + + @ShellMethod(value = "foo2") + public void foo2(@ShellOption(defaultValue = ShellOption.NONE) String arg1) { + } + + @ShellMethod(value = "foo") + public void foo3(@ShellOption(defaultValue = ShellOption.NULL) String arg1) { + } + } }