From 25721dd63d4e5ba506b2dcee33539e8b3266ed1a Mon Sep 17 00:00:00 2001 From: Janne Valkealahti Date: Mon, 13 Jun 2022 09:27:16 +0100 Subject: [PATCH] ConfirmationInput should have resultValue - Add flow hooks to ConfirmationInput so that user is able to pass a flag from an options so that component can bypass interactive mode. - Fixes #445 --- .../component/flow/BaseConfirmationInput.java | 22 ++++++ .../shell/component/flow/ComponentFlow.java | 5 ++ .../component/flow/ConfirmationInputSpec.java | 15 ++++ .../component/flow/ComponentFlowTests.java | 6 ++ .../standard/ComponentFlowCommands.java | 68 ++++++++++++++++++- 5 files changed, 114 insertions(+), 2 deletions(-) diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseConfirmationInput.java b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseConfirmationInput.java index 5367282c..f92ec594 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseConfirmationInput.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseConfirmationInput.java @@ -35,6 +35,8 @@ public abstract class BaseConfirmationInput extends BaseInput> renderer; private List> preHandlers = new ArrayList<>(); private List> postHandlers = new ArrayList<>(); @@ -52,6 +54,18 @@ public abstract class BaseConfirmationInput extends BaseInput> getRenderer() { return renderer; } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/ComponentFlow.java b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/ComponentFlow.java index cd4d308b..7bc9c9e9 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/ComponentFlow.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/ComponentFlow.java @@ -521,6 +521,11 @@ public interface ComponentFlow { return confirmationInputs.stream().map(input -> { ConfirmationInput selector = new ConfirmationInput(terminal, input.getName(), input.getDefaultValue()); Function, ComponentContext> operation = (context) -> { + if (input.getResultMode() == ResultMode.ACCEPT && input.isStoreResult() + && input.getResultValue() != null) { + context.put(input.getId(), input.getResultValue()); + return context; + } selector.setResourceLoader(resourceLoader); selector.setTemplateExecutor(templateExecutor); if (StringUtils.hasText(input.getTemplateLocation())) { diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/ConfirmationInputSpec.java b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/ConfirmationInputSpec.java index 8f0f28e8..2f4b39b9 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/ConfirmationInputSpec.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/ConfirmationInputSpec.java @@ -39,6 +39,21 @@ public interface ConfirmationInputSpec extends BaseInputSpec id4 = inputWizardResult.getContext().get("id4"); + Boolean id5 = inputWizardResult.getContext().get("id5"); assertThat(id1).isEqualTo("value1"); assertThat(id2.toString()).contains("value2"); assertThat(id3).isEqualTo("value3"); assertThat(id4).containsExactlyInAnyOrder("value4"); + assertThat(id5).isFalse(); } @Test diff --git a/spring-shell-samples/src/main/java/org/springframework/shell/samples/standard/ComponentFlowCommands.java b/spring-shell-samples/src/main/java/org/springframework/shell/samples/standard/ComponentFlowCommands.java index c28f6d66..c8939801 100644 --- a/spring-shell-samples/src/main/java/org/springframework/shell/samples/standard/ComponentFlowCommands.java +++ b/spring-shell-samples/src/main/java/org/springframework/shell/samples/standard/ComponentFlowCommands.java @@ -15,6 +15,7 @@ */ package org.springframework.shell.samples.standard; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -24,7 +25,9 @@ import java.util.stream.IntStream; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.shell.component.flow.ComponentFlow; +import org.springframework.shell.component.flow.ResultMode; import org.springframework.shell.component.flow.SelectItem; +import org.springframework.shell.component.flow.ComponentFlow.ComponentFlowResult; import org.springframework.shell.standard.AbstractShellComponent; import org.springframework.shell.standard.ShellComponent; import org.springframework.shell.standard.ShellMethod; @@ -36,8 +39,8 @@ public class ComponentFlowCommands extends AbstractShellComponent { @Autowired private ComponentFlow.Builder componentFlowBuilder; - @ShellMethod(key = "flow showcase", value = "Showcase", group = "Flow") - public void showcase() { + @ShellMethod(key = "flow showcase1", value = "Showcase", group = "Flow") + public void showcase1() { Map single1SelectItems = new HashMap<>(); single1SelectItems.put("key1", "value1"); single1SelectItems.put("key2", "value2"); @@ -69,6 +72,67 @@ public class ComponentFlowCommands extends AbstractShellComponent { flow.run(); } + @ShellMethod(key = "flow showcase2", value = "Showcase with options", group = "Flow") + public String showcase2( + @ShellOption(help = "Field1 value", defaultValue = ShellOption.NULL) String field1, + @ShellOption(help = "Field2 value", defaultValue = ShellOption.NULL) String field2, + @ShellOption(help = "Confirmation1 value", defaultValue = ShellOption.NULL) Boolean confirmation1, + @ShellOption(help = "Path1 value", defaultValue = ShellOption.NULL) String path1, + @ShellOption(help = "Single1 value", defaultValue = ShellOption.NULL) String single1, + @ShellOption(help = "Multi1 value", defaultValue = ShellOption.NULL) List multi1 + ) { + Map single1SelectItems = new HashMap<>(); + single1SelectItems.put("key1", "value1"); + single1SelectItems.put("key2", "value2"); + List multi1SelectItems = Arrays.asList(SelectItem.of("key1", "value1"), + SelectItem.of("key2", "value2"), SelectItem.of("key3", "value3")); + List multi1ResultValues = multi1 != null ? multi1 : new ArrayList<>(); + ComponentFlow flow = componentFlowBuilder.clone().reset() + .withStringInput("field1") + .name("Field1") + .defaultValue("defaultField1Value") + .resultValue(field1) + .resultMode(ResultMode.ACCEPT) + .and() + .withStringInput("field2") + .name("Field2") + .resultValue(field2) + .resultMode(ResultMode.ACCEPT) + .and() + .withConfirmationInput("confirmation1") + .name("Confirmation1") + .resultValue(confirmation1) + .resultMode(ResultMode.ACCEPT) + .and() + .withPathInput("path1") + .name("Path1") + .resultValue(path1) + .resultMode(ResultMode.ACCEPT) + .and() + .withSingleItemSelector("single1") + .name("Single1") + .selectItems(single1SelectItems) + .resultValue(single1) + .resultMode(ResultMode.ACCEPT) + .and() + .withMultiItemSelector("multi1") + .name("Multi1") + .selectItems(multi1SelectItems) + .resultValues(multi1ResultValues) + .resultMode(ResultMode.ACCEPT) + .and() + .build(); + ComponentFlowResult result = flow.run(); + StringBuilder buf = new StringBuilder(); + result.getContext().stream().forEach(e -> { + buf.append(e.getKey()); + buf.append(" = "); + buf.append(e.getValue()); + buf.append("\n"); + }); + return buf.toString(); + } + @ShellMethod(key = "flow conditional", value = "Second component based on first", group = "Flow") public void conditional() { Map single1SelectItems = new HashMap<>();