From 93cd27f125ae346406c49b39ce284234057f4632 Mon Sep 17 00:00:00 2001 From: Nicola Di Falco Date: Fri, 4 Aug 2023 14:51:24 +0200 Subject: [PATCH 1/4] feat: adding mandatory flag to string input - Added to flow - Added to component - Add simple test case - Add samples --- .../shell/component/StringInput.java | 67 +++++++++++++++++-- .../shell/component/flow/BaseStringInput.java | 13 +++- .../shell/component/flow/ComponentFlow.java | 3 +- .../shell/component/flow/StringInputSpec.java | 9 ++- .../shell/component/string-input-default.stg | 18 +++++ .../shell/component/StringInputTests.java | 33 +++++++++ .../component/flow/ComponentFlowTests.java | 9 +++ ...using-shell-components-ui-stringinput.adoc | 6 +- .../samples/standard/ComponentCommands.java | 9 +++ .../standard/ComponentFlowCommands.java | 4 ++ 10 files changed, 161 insertions(+), 10 deletions(-) diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/StringInput.java b/spring-shell-core/src/main/java/org/springframework/shell/component/StringInput.java index e94e9d148..44607f055 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/StringInput.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/StringInput.java @@ -44,21 +44,28 @@ public class StringInput extends AbstractTextComponent> renderer) { + this(terminal, name, defaultValue, renderer, false); + } + + public StringInput(Terminal terminal, String name, String defaultValue, + Function> renderer, boolean mandatory) { super(terminal, name, null); setRenderer(renderer != null ? renderer : new DefaultRenderer()); setTemplateLocation("classpath:org/springframework/shell/component/string-input-default.stg"); this.defaultValue = defaultValue; + this.mandatory = mandatory; } /** @@ -70,12 +77,21 @@ public void setMaskCharacter(Character maskCharacter) { this.maskCharacter = maskCharacter; } + /** + * Sets a mandatory flag to check that the result is not empty + * + * @param mandatory if input is required + */ + public void setMandatory(boolean mandatory) { + this.mandatory = mandatory; + } + @Override public StringInputContext getThisContext(ComponentContext context) { if (context != null && currentContext == context) { return currentContext; } - currentContext = StringInputContext.of(defaultValue, maskCharacter); + currentContext = StringInputContext.of(defaultValue, maskCharacter, mandatory); currentContext.setName(getName()); context.stream().forEach(e -> { currentContext.put(e.getKey(), e.getValue()); @@ -116,6 +132,9 @@ protected boolean read(BindingReader bindingReader, KeyMap keyMap, Strin } else if (context.getDefaultValue() != null) { context.setResultValue(context.getDefaultValue()); + } else if (mandatory) { + context.setMessage("This field is mandatory", TextComponentContext.MessageLevel.ERROR); + break; } return true; default: @@ -175,13 +194,27 @@ public interface StringInputContext extends TextComponentContext toTemplateModel() { Map attributes = super.toTemplateModel(); @@ -248,6 +302,7 @@ public Map toTemplateModel() { attributes.put("maskedResultValue", getMaskedResultValue()); attributes.put("maskCharacter", getMaskCharacter()); attributes.put("hasMaskCharacter", hasMaskCharacter()); + attributes.put("mandatory", isMandatory()); Map model = new HashMap<>(); model.put("model", attributes); return model; diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseStringInput.java b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseStringInput.java index 14e165466..17aad93bb 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseStringInput.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseStringInput.java @@ -38,6 +38,7 @@ public abstract class BaseStringInput extends BaseInput impleme private ResultMode resultMode; private String defaultValue; private Character maskCharacter; + private boolean mandatory = false; private Function> renderer; private List> preHandlers = new ArrayList<>(); private List> postHandlers = new ArrayList<>(); @@ -79,6 +80,12 @@ public StringInputSpec maskCharacter(Character maskCharacter) { return this; } + @Override + public StringInputSpec mandatory() { + this.mandatory = true; + return this; + } + @Override public StringInputSpec renderer(Function> renderer) { this.renderer = renderer; @@ -146,6 +153,10 @@ public Character getMaskCharacter() { return maskCharacter; } + public boolean isMandatory() { + return mandatory; + } + public Function> getRenderer() { return renderer; } @@ -169,4 +180,4 @@ public boolean isStoreResult() { public Function getNext() { return next; } -} \ No newline at end of file +} 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 d1ee2c83f..6ce38865c 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 @@ -445,7 +445,7 @@ else if (n.isPresent()) { private Stream stringInputsStream() { return stringInputs.stream().map(input -> { - StringInput selector = new StringInput(terminal, input.getName(), input.getDefaultValue()); + StringInput selector = new StringInput(terminal, input.getName(), input.getDefaultValue(), null, input.isMandatory()); Function, ComponentContext> operation = (context) -> { if (input.getResultMode() == ResultMode.ACCEPT && input.isStoreResult() && StringUtils.hasText(input.getResultValue())) { @@ -465,6 +465,7 @@ private Stream stringInputsStream() { if (input.getResultMode() == ResultMode.VERIFY && StringUtils.hasText(input.getResultValue())) { selector.addPreRunHandler(c -> { c.setDefaultValue(input.getResultValue()); + c.setMandatory(input.isMandatory()); }); } selector.addPostRunHandler(c -> { diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/StringInputSpec.java b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/StringInputSpec.java index c21a0be86..ab639bfc1 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/StringInputSpec.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/StringInputSpec.java @@ -72,6 +72,13 @@ public interface StringInputSpec extends BaseInputSpec { */ StringInputSpec maskCharacter(Character maskCharacter); + /** + * Sets input to mandatory + * + * @return a builder + */ + StringInputSpec mandatory(); + /** * Sets a renderer function. * @@ -128,4 +135,4 @@ public interface StringInputSpec extends BaseInputSpec { * @return the parent builder */ Builder and(); -} \ No newline at end of file +} diff --git a/spring-shell-core/src/main/resources/org/springframework/shell/component/string-input-default.stg b/spring-shell-core/src/main/resources/org/springframework/shell/component/string-input-default.stg index 265163fa4..a013b71bb 100644 --- a/spring-shell-core/src/main/resources/org/springframework/shell/component/string-input-default.stg +++ b/spring-shell-core/src/main/resources/org/springframework/shell/component/string-input-default.stg @@ -1,9 +1,23 @@ +// message +message(model) ::= <% + + <({}); format="style-level-error"> + + <({}); format="style-level-warn"> + + <({}); format="style-level-info"> + +%> + // info section after '? xxx' info(model) ::= <% + + <("[Mandatory]"); format="style-value"> + <("[Default "); format="style-value"><("]"); format="style-value"> @@ -12,6 +26,9 @@ info(model) ::= <% + + <("[Mandatory]"); format="style-value"> + <("[Default "); format="style-value"><("]"); format="style-value"> @@ -32,6 +49,7 @@ result(model) ::= << // component is running running(model) ::= << + >> // main diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/StringInputTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/StringInputTests.java index 1ff6f29cf..341bae819 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/StringInputTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/StringInputTests.java @@ -166,6 +166,39 @@ public void testResultUserInput() throws InterruptedException { assertThat(run1Context.getResultValue()).isEqualTo("test"); } + @Test + public void testResultMandatoryInput() throws InterruptedException { + ComponentContext empty = ComponentContext.empty(); + StringInput component1 = new StringInput(getTerminal()); + component1.setResourceLoader(new DefaultResourceLoader()); + component1.setTemplateExecutor(getTemplateExecutor()); + component1.setMandatory(true); + + service.execute(() -> { + StringInputContext run1Context = component1.run(empty); + result1.set(run1Context); + latch1.countDown(); + }); + + TestBuffer testBuffer = new TestBuffer().cr(); + write(testBuffer.getBytes()); + + latch1.await(2, TimeUnit.SECONDS); + + StringInputContext run1Context = result1.get(); + assertThat(consoleOut()).contains("This field is mandatory"); + assertThat(run1Context).isNull(); + + testBuffer.append("test").cr(); + write(testBuffer.getBytes()); + + latch1.await(2, TimeUnit.SECONDS); + run1Context = result1.get(); + + assertThat(run1Context).isNotNull(); + assertThat(run1Context.getResultValue()).isEqualTo("test"); + } + @Test public void testPassingViaContext() throws InterruptedException { ComponentContext empty = ComponentContext.empty(); diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/flow/ComponentFlowTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/flow/ComponentFlowTests.java index e58e2e70d..9e232536b 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/flow/ComponentFlowTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/flow/ComponentFlowTests.java @@ -52,6 +52,10 @@ public void testSimpleFlow() throws InterruptedException { .withStringInput("field2") .name("Field2") .and() + .withStringInput("field3") + .name("Field3") + .mandatory() + .and() .withPathInput("path1") .name("Path1") .and() @@ -80,6 +84,9 @@ public void testSimpleFlow() throws InterruptedException { // field2 testBuffer = new TestBuffer().append("Field2Value").cr(); write(testBuffer.getBytes()); + // field3 + testBuffer = new TestBuffer().cr().append("Field3Value").cr(); + write(testBuffer.getBytes()); // path1 testBuffer = new TestBuffer().append("fakedir").cr(); write(testBuffer.getBytes()); @@ -95,10 +102,12 @@ public void testSimpleFlow() throws InterruptedException { assertThat(inputWizardResult).isNotNull(); String field1 = inputWizardResult.getContext().get("field1"); String field2 = inputWizardResult.getContext().get("field2"); + String field3 = inputWizardResult.getContext().get("field3"); Path path1 = inputWizardResult.getContext().get("path1"); String single1 = inputWizardResult.getContext().get("single1"); List multi1 = inputWizardResult.getContext().get("multi1"); assertThat(field1).isEqualTo("defaultField1Value"); + assertThat(field3).isEqualTo("Field3Value"); assertThat(field2).isEqualTo("Field2Value"); assertThat(path1.toString()).contains("fakedir"); assertThat(single1).isEqualTo("value1"); diff --git a/spring-shell-docs/src/main/asciidoc/using-shell-components-ui-stringinput.adoc b/spring-shell-docs/src/main/asciidoc/using-shell-components-ui-stringinput.adoc index b88574a64..a74f50c05 100644 --- a/spring-shell-docs/src/main/asciidoc/using-shell-components-ui-stringinput.adoc +++ b/spring-shell-docs/src/main/asciidoc/using-shell-components-ui-stringinput.adoc @@ -3,7 +3,8 @@ ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs] The string input component asks a user for simple text input, optionally masking values -if the content contains something sensitive. The following listing shows an example: +if the content contains something sensitive. The input can also be required (at least 1 char). + +The following listing shows an example: ==== [source, java, indent=0] @@ -38,6 +39,9 @@ The context object is `StringInputContext`. The following table lists its contex |`hasMaskCharacter` |`true` if a mask character is set. Otherwise, false. +|`mandatory` +|`true` if the input is required. Otherwise, false. + |`model` |The parent context variables (see <>). |=== diff --git a/spring-shell-samples/src/main/java/org/springframework/shell/samples/standard/ComponentCommands.java b/spring-shell-samples/src/main/java/org/springframework/shell/samples/standard/ComponentCommands.java index a85e994d6..ad404f55e 100644 --- a/spring-shell-samples/src/main/java/org/springframework/shell/samples/standard/ComponentCommands.java +++ b/spring-shell-samples/src/main/java/org/springframework/shell/samples/standard/ComponentCommands.java @@ -56,6 +56,15 @@ public String stringInput(boolean mask) { return "Got value " + context.getResultValue(); } + @ShellMethod(key = "component string required", value = "String input", group = "Components") + public String stringRequired() { + StringInput component = new StringInput(getTerminal(), "Enter value", null, null, true); + component.setResourceLoader(getResourceLoader()); + component.setTemplateExecutor(getTemplateExecutor()); + StringInputContext context = component.run(StringInputContext.empty()); + return "Got value " + context.getResultValue(); + } + @ShellMethod(key = "component path", value = "Path input", group = "Components") public String pathInput() { PathInput component = new PathInput(getTerminal(), "Enter value"); 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 696c1e001..8d5cb3897 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 @@ -62,6 +62,10 @@ public void showcase1() { .withStringInput("field2") .name("Field2") .and() + .withStringInput("field3") + .name("Field3") + .mandatory() + .and() .withConfirmationInput("confirmation1") .name("Confirmation1") .and() From f3c39de20038c7738a093bff4e95f789a2aa3f02 Mon Sep 17 00:00:00 2001 From: Nicola Di Falco Date: Mon, 7 Aug 2023 13:55:30 +0200 Subject: [PATCH 2/4] feat: rename mandatory to required --- .../shell/component/StringInput.java | 46 +++++++++---------- .../shell/component/flow/BaseStringInput.java | 11 ++--- .../shell/component/flow/ComponentFlow.java | 7 ++- .../shell/component/flow/StringInputSpec.java | 5 +- .../shell/component/string-input-default.stg | 8 ++-- .../shell/component/StringInputTests.java | 7 ++- .../component/flow/ComponentFlowTests.java | 7 ++- ...using-shell-components-ui-stringinput.adoc | 2 +- .../standard/ComponentFlowCommands.java | 3 +- 9 files changed, 44 insertions(+), 52 deletions(-) diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/StringInput.java b/spring-shell-core/src/main/java/org/springframework/shell/component/StringInput.java index 44607f055..130893468 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/StringInput.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/StringInput.java @@ -26,11 +26,9 @@ import org.jline.utils.AttributedString; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.springframework.shell.component.StringInput.StringInputContext; import org.springframework.shell.component.context.ComponentContext; import org.springframework.shell.component.support.AbstractTextComponent; -import org.springframework.shell.component.support.AbstractTextComponent.TextComponentContext; import org.springframework.util.StringUtils; /** @@ -44,7 +42,7 @@ public class StringInput extends AbstractTextComponent> renderer, boolean mandatory) { + Function> renderer, boolean required) { super(terminal, name, null); setRenderer(renderer != null ? renderer : new DefaultRenderer()); setTemplateLocation("classpath:org/springframework/shell/component/string-input-default.stg"); this.defaultValue = defaultValue; - this.mandatory = mandatory; + this.required = required; } /** @@ -78,12 +76,12 @@ public void setMaskCharacter(Character maskCharacter) { } /** - * Sets a mandatory flag to check that the result is not empty + * Sets a required flag to check that the result is not empty * - * @param mandatory if input is required + * @param required if input is required */ - public void setMandatory(boolean mandatory) { - this.mandatory = mandatory; + public void setRequired(boolean required) { + this.required = required; } @Override @@ -91,7 +89,7 @@ public StringInputContext getThisContext(ComponentContext context) { if (context != null && currentContext == context) { return currentContext; } - currentContext = StringInputContext.of(defaultValue, maskCharacter, mandatory); + currentContext = StringInputContext.of(defaultValue, maskCharacter, required); currentContext.setName(getName()); context.stream().forEach(e -> { currentContext.put(e.getKey(), e.getValue()); @@ -132,7 +130,7 @@ protected boolean read(BindingReader bindingReader, KeyMap keyMap, Strin } else if (context.getDefaultValue() != null) { context.setResultValue(context.getDefaultValue()); - } else if (mandatory) { + } else if (required) { context.setMessage("This field is mandatory", TextComponentContext.MessageLevel.ERROR); break; } @@ -197,16 +195,16 @@ public interface StringInputContext extends TextComponentContext toTemplateModel() { attributes.put("maskedResultValue", getMaskedResultValue()); attributes.put("maskCharacter", getMaskCharacter()); attributes.put("hasMaskCharacter", hasMaskCharacter()); - attributes.put("mandatory", isMandatory()); + attributes.put("required", isRequired()); Map model = new HashMap<>(); model.put("model", attributes); return model; diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseStringInput.java b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseStringInput.java index 17aad93bb..78fc0dde0 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseStringInput.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseStringInput.java @@ -21,7 +21,6 @@ import java.util.function.Function; import org.jline.utils.AttributedString; - import org.springframework.shell.component.StringInput.StringInputContext; import org.springframework.shell.component.flow.ComponentFlow.BaseBuilder; import org.springframework.shell.component.flow.ComponentFlow.Builder; @@ -38,7 +37,7 @@ public abstract class BaseStringInput extends BaseInput impleme private ResultMode resultMode; private String defaultValue; private Character maskCharacter; - private boolean mandatory = false; + private boolean required = false; private Function> renderer; private List> preHandlers = new ArrayList<>(); private List> postHandlers = new ArrayList<>(); @@ -81,8 +80,8 @@ public StringInputSpec maskCharacter(Character maskCharacter) { } @Override - public StringInputSpec mandatory() { - this.mandatory = true; + public StringInputSpec required() { + this.required = true; return this; } @@ -153,8 +152,8 @@ public Character getMaskCharacter() { return maskCharacter; } - public boolean isMandatory() { - return mandatory; + public boolean isRequired() { + return required; } public Function> getRenderer() { 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 6ce38865c..f5d9dede5 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 @@ -31,11 +31,11 @@ import org.jline.terminal.Terminal; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.springframework.core.OrderComparator; import org.springframework.core.Ordered; import org.springframework.core.io.ResourceLoader; import org.springframework.shell.component.ConfirmationInput; +import org.springframework.shell.component.ConfirmationInput.ConfirmationInputContext; import org.springframework.shell.component.MultiItemSelector; import org.springframework.shell.component.MultiItemSelector.MultiItemSelectorContext; import org.springframework.shell.component.PathInput; @@ -43,7 +43,6 @@ import org.springframework.shell.component.SingleItemSelector; import org.springframework.shell.component.SingleItemSelector.SingleItemSelectorContext; import org.springframework.shell.component.StringInput; -import org.springframework.shell.component.ConfirmationInput.ConfirmationInputContext; import org.springframework.shell.component.StringInput.StringInputContext; import org.springframework.shell.component.context.ComponentContext; import org.springframework.shell.component.support.SelectorItem; @@ -445,7 +444,7 @@ else if (n.isPresent()) { private Stream stringInputsStream() { return stringInputs.stream().map(input -> { - StringInput selector = new StringInput(terminal, input.getName(), input.getDefaultValue(), null, input.isMandatory()); + StringInput selector = new StringInput(terminal, input.getName(), input.getDefaultValue(), null, input.isRequired()); Function, ComponentContext> operation = (context) -> { if (input.getResultMode() == ResultMode.ACCEPT && input.isStoreResult() && StringUtils.hasText(input.getResultValue())) { @@ -465,7 +464,7 @@ private Stream stringInputsStream() { if (input.getResultMode() == ResultMode.VERIFY && StringUtils.hasText(input.getResultValue())) { selector.addPreRunHandler(c -> { c.setDefaultValue(input.getResultValue()); - c.setMandatory(input.isMandatory()); + c.setRequired(input.isRequired()); }); } selector.addPostRunHandler(c -> { diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/StringInputSpec.java b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/StringInputSpec.java index ab639bfc1..3628895bc 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/StringInputSpec.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/StringInputSpec.java @@ -20,7 +20,6 @@ import java.util.function.Function; import org.jline.utils.AttributedString; - import org.springframework.shell.component.StringInput.StringInputContext; import org.springframework.shell.component.context.ComponentContext; import org.springframework.shell.component.flow.ComponentFlow.Builder; @@ -73,11 +72,11 @@ public interface StringInputSpec extends BaseInputSpec { StringInputSpec maskCharacter(Character maskCharacter); /** - * Sets input to mandatory + * Sets input to required * * @return a builder */ - StringInputSpec mandatory(); + StringInputSpec required(); /** * Sets a renderer function. diff --git a/spring-shell-core/src/main/resources/org/springframework/shell/component/string-input-default.stg b/spring-shell-core/src/main/resources/org/springframework/shell/component/string-input-default.stg index a013b71bb..d38851c90 100644 --- a/spring-shell-core/src/main/resources/org/springframework/shell/component/string-input-default.stg +++ b/spring-shell-core/src/main/resources/org/springframework/shell/component/string-input-default.stg @@ -15,8 +15,8 @@ info(model) ::= <% - - <("[Mandatory]"); format="style-value"> + + <("[Required]"); format="style-value"> <("[Default "); format="style-value"><("]"); format="style-value"> @@ -26,8 +26,8 @@ info(model) ::= <% - - <("[Mandatory]"); format="style-value"> + + <("[Required]"); format="style-value"> <("[Default "); format="style-value"><("]"); format="style-value"> diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/StringInputTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/StringInputTests.java index 341bae819..d09964509 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/StringInputTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/StringInputTests.java @@ -15,6 +15,8 @@ */ package org.springframework.shell.component; +import static org.assertj.core.api.Assertions.assertThat; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.nio.charset.StandardCharsets; @@ -28,13 +30,10 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; - import org.springframework.core.io.DefaultResourceLoader; import org.springframework.shell.component.StringInput.StringInputContext; import org.springframework.shell.component.context.ComponentContext; -import static org.assertj.core.api.Assertions.assertThat; - public class StringInputTests extends AbstractShellTests { private ExecutorService service; @@ -172,7 +171,7 @@ public void testResultMandatoryInput() throws InterruptedException { StringInput component1 = new StringInput(getTerminal()); component1.setResourceLoader(new DefaultResourceLoader()); component1.setTemplateExecutor(getTemplateExecutor()); - component1.setMandatory(true); + component1.setRequired(true); service.execute(() -> { StringInputContext run1Context = component1.run(empty); diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/flow/ComponentFlowTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/flow/ComponentFlowTests.java index 9e232536b..bff644de8 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/flow/ComponentFlowTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/flow/ComponentFlowTests.java @@ -15,6 +15,8 @@ */ package org.springframework.shell.component.flow; +import static org.assertj.core.api.Assertions.assertThat; + import java.nio.file.Path; import java.util.Arrays; import java.util.HashMap; @@ -27,11 +29,8 @@ import java.util.concurrent.atomic.AtomicReference; import org.junit.jupiter.api.Test; - import org.springframework.shell.component.flow.ComponentFlow.ComponentFlowResult; -import static org.assertj.core.api.Assertions.assertThat; - public class ComponentFlowTests extends AbstractShellTests { @Test @@ -54,7 +53,7 @@ public void testSimpleFlow() throws InterruptedException { .and() .withStringInput("field3") .name("Field3") - .mandatory() + .required() .and() .withPathInput("path1") .name("Path1") diff --git a/spring-shell-docs/src/main/asciidoc/using-shell-components-ui-stringinput.adoc b/spring-shell-docs/src/main/asciidoc/using-shell-components-ui-stringinput.adoc index a74f50c05..ba05ef07f 100644 --- a/spring-shell-docs/src/main/asciidoc/using-shell-components-ui-stringinput.adoc +++ b/spring-shell-docs/src/main/asciidoc/using-shell-components-ui-stringinput.adoc @@ -39,7 +39,7 @@ The context object is `StringInputContext`. The following table lists its contex |`hasMaskCharacter` |`true` if a mask character is set. Otherwise, false. -|`mandatory` +|`required` |`true` if the input is required. Otherwise, false. |`model` 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 8d5cb3897..0a49157d0 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 @@ -24,7 +24,6 @@ import java.util.stream.IntStream; import org.jline.terminal.impl.DumbTerminal; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.shell.command.CommandExecution.CommandParserExceptionsException; @@ -64,7 +63,7 @@ public void showcase1() { .and() .withStringInput("field3") .name("Field3") - .mandatory() + .required() .and() .withConfirmationInput("confirmation1") .name("Confirmation1") From 9529dcc337b30f3eb468b04f863aebbad270dd24 Mon Sep 17 00:00:00 2001 From: Nicola Di Falco Date: Tue, 8 Aug 2023 09:58:42 +0200 Subject: [PATCH 3/4] fix: revert removed import and merge samples --- .../shell/component/StringInput.java | 1 + .../shell/samples/standard/ComponentCommands.java | 14 +++----------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/StringInput.java b/spring-shell-core/src/main/java/org/springframework/shell/component/StringInput.java index 130893468..fa370f5ec 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/StringInput.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/StringInput.java @@ -29,6 +29,7 @@ import org.springframework.shell.component.StringInput.StringInputContext; import org.springframework.shell.component.context.ComponentContext; import org.springframework.shell.component.support.AbstractTextComponent; +import org.springframework.shell.component.support.AbstractTextComponent.TextComponentContext; import org.springframework.util.StringUtils; /** diff --git a/spring-shell-samples/src/main/java/org/springframework/shell/samples/standard/ComponentCommands.java b/spring-shell-samples/src/main/java/org/springframework/shell/samples/standard/ComponentCommands.java index ad404f55e..1ff9ed08f 100644 --- a/spring-shell-samples/src/main/java/org/springframework/shell/samples/standard/ComponentCommands.java +++ b/spring-shell-samples/src/main/java/org/springframework/shell/samples/standard/ComponentCommands.java @@ -45,10 +45,11 @@ public class ComponentCommands extends AbstractShellComponent { @ShellMethod(key = "component string", value = "String input", group = "Components") - public String stringInput(boolean mask) { - StringInput component = new StringInput(getTerminal(), "Enter value", "myvalue"); + public String stringInput(boolean mask, boolean required) { + StringInput component = new StringInput(getTerminal(), "Enter value", null); component.setResourceLoader(getResourceLoader()); component.setTemplateExecutor(getTemplateExecutor()); + component.setRequired(required); if (mask) { component.setMaskCharacter('*'); } @@ -56,15 +57,6 @@ public String stringInput(boolean mask) { return "Got value " + context.getResultValue(); } - @ShellMethod(key = "component string required", value = "String input", group = "Components") - public String stringRequired() { - StringInput component = new StringInput(getTerminal(), "Enter value", null, null, true); - component.setResourceLoader(getResourceLoader()); - component.setTemplateExecutor(getTemplateExecutor()); - StringInputContext context = component.run(StringInputContext.empty()); - return "Got value " + context.getResultValue(); - } - @ShellMethod(key = "component path", value = "Path input", group = "Components") public String pathInput() { PathInput component = new PathInput(getTerminal(), "Enter value"); From 28e5d29147087d990f94258e9874eff4872ae0a3 Mon Sep 17 00:00:00 2001 From: Nicola Di Falco Date: Wed, 9 Aug 2023 07:10:06 +0200 Subject: [PATCH 4/4] fix: display required only if no default value --- .../shell/component/string-input-default.stg | 10 ++++------ .../shell/samples/standard/ComponentCommands.java | 5 +++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/spring-shell-core/src/main/resources/org/springframework/shell/component/string-input-default.stg b/spring-shell-core/src/main/resources/org/springframework/shell/component/string-input-default.stg index d38851c90..58872a089 100644 --- a/spring-shell-core/src/main/resources/org/springframework/shell/component/string-input-default.stg +++ b/spring-shell-core/src/main/resources/org/springframework/shell/component/string-input-default.stg @@ -15,22 +15,20 @@ info(model) ::= <% - - <("[Required]"); format="style-value"> - <("[Default "); format="style-value"><("]"); format="style-value"> + + <("[Required]"); format="style-value"> - - <("[Required]"); format="style-value"> - <("[Default "); format="style-value"><("]"); format="style-value"> + + <("[Required]"); format="style-value"> diff --git a/spring-shell-samples/src/main/java/org/springframework/shell/samples/standard/ComponentCommands.java b/spring-shell-samples/src/main/java/org/springframework/shell/samples/standard/ComponentCommands.java index 1ff9ed08f..64ba5b09c 100644 --- a/spring-shell-samples/src/main/java/org/springframework/shell/samples/standard/ComponentCommands.java +++ b/spring-shell-samples/src/main/java/org/springframework/shell/samples/standard/ComponentCommands.java @@ -39,14 +39,15 @@ import org.springframework.shell.standard.AbstractShellComponent; import org.springframework.shell.standard.ShellComponent; import org.springframework.shell.standard.ShellMethod; +import org.springframework.shell.standard.ShellOption; import org.springframework.util.StringUtils; @ShellComponent public class ComponentCommands extends AbstractShellComponent { @ShellMethod(key = "component string", value = "String input", group = "Components") - public String stringInput(boolean mask, boolean required) { - StringInput component = new StringInput(getTerminal(), "Enter value", null); + public String stringInput(boolean mask, boolean required, @ShellOption(defaultValue = ShellOption.NULL) String defaultValue) { + StringInput component = new StringInput(getTerminal(), "Enter value", defaultValue); component.setResourceLoader(getResourceLoader()); component.setTemplateExecutor(getTemplateExecutor()); component.setRequired(required);