Add SelectItem to flow single selector api

- This change makes single/multi same on an api level
  where single selector used key/value map and multi
  selector used list of SelectItem's.
- We still keep use of map on a single select but those
  essentially go directly via SelectItem's.
- Fixes #946
This commit is contained in:
Janne Valkealahti
2023-12-18 10:03:36 +00:00
parent 934fcbd4ef
commit 56dffe0223
5 changed files with 68 additions and 18 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2022 the original author or authors.
* Copyright 2022-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,11 +17,11 @@ package org.springframework.shell.component.flow;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.jline.utils.AttributedString;
@@ -40,7 +40,7 @@ public abstract class BaseSingleItemSelector extends BaseInput<SingleItemSelecto
private String name;
private String resultValue;
private ResultMode resultMode;
private Map<String, String> selectItems = new HashMap<>();
private List<SelectItem> selectItems = new ArrayList<>();
private String defaultSelect;
private Comparator<SelectorItem<String>> comparator;
private Function<SingleItemSelectorContext<String, SelectorItem<String>>, List<AttributedString>> renderer;
@@ -75,13 +75,22 @@ public abstract class BaseSingleItemSelector extends BaseInput<SingleItemSelecto
@Override
public SingleItemSelectorSpec selectItem(String name, String item) {
this.selectItems.put(name, item);
selectItems.add(SelectItem.of(name, item));
return this;
}
@Override
public SingleItemSelectorSpec selectItems(Map<String, String> selectItems) {
this.selectItems.putAll(selectItems);
List<SelectItem> items = selectItems.entrySet().stream()
.map(e -> SelectItem.of(e.getKey(), e.getValue()))
.collect(Collectors.toList());
selectItems(items);
return this;
}
@Override
public SingleItemSelectorSpec selectItems(List<SelectItem> selectItems) {
this.selectItems.addAll(selectItems);
return this;
}
@@ -163,7 +172,7 @@ public abstract class BaseSingleItemSelector extends BaseInput<SingleItemSelecto
return resultMode;
}
public Map<String, String> getSelectItems() {
public List<SelectItem> getSelectItems() {
return selectItems;
}
@@ -202,4 +211,4 @@ public abstract class BaseSingleItemSelector extends BaseInput<SingleItemSelecto
public Function<SingleItemSelectorContext<String, SelectorItem<String>>, String> getNext() {
return next;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2022 the original author or authors.
* Copyright 2022-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -565,9 +565,9 @@ public interface ComponentFlow {
private Stream<OrderedInputOperation> singleItemSelectorsStream() {
return singleInputs.stream().map(input -> {
List<SelectorItem<String>> selectorItems = input.getSelectItems().entrySet().stream()
.map(e -> SelectorItem.of(e.getKey(), e.getValue()))
.collect(Collectors.toList());
List<SelectorItem<String>> selectorItems = input.getSelectItems().stream()
.map(si -> SelectorItem.of(si.name(), si.item()))
.collect(Collectors.toList());
// setup possible item for initial expose
String defaultSelect = input.getDefaultSelect();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2022 the original author or authors.
* Copyright 2022-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -65,6 +65,7 @@ public interface SingleItemSelectorSpec extends BaseInputSpec<SingleItemSelector
* @param name the name
* @param item the item
* @return a builder
* @see #selectItems(List)
*/
SingleItemSelectorSpec selectItem(String name, String item);
@@ -73,9 +74,18 @@ public interface SingleItemSelectorSpec extends BaseInputSpec<SingleItemSelector
*
* @param selectItems the select items
* @return a builder
* @see #selectItems(List)
*/
SingleItemSelectorSpec selectItems(Map<String, String> selectItems);
/**
* Adds a list of select items.
*
* @param selectItems the select items
* @return a builder
*/
SingleItemSelectorSpec selectItems(List<SelectItem> selectItems);
/**
* Automatically selects and exposes a given item.
*
@@ -156,4 +166,4 @@ public interface SingleItemSelectorSpec extends BaseInputSpec<SingleItemSelector
* @return the parent builder
*/
Builder and();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2022 the original author or authors.
* Copyright 2022-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,7 +28,9 @@ import java.util.concurrent.atomic.AtomicReference;
import org.junit.jupiter.api.Test;
import org.springframework.shell.component.flow.ComponentFlow.Builder;
import org.springframework.shell.component.flow.ComponentFlow.ComponentFlowResult;
import org.springframework.test.util.ReflectionTestUtils;
import static org.assertj.core.api.Assertions.assertThat;
@@ -339,4 +341,34 @@ public class ComponentFlowTests extends AbstractShellTests {
String single1 = inputWizardResult.getContext().get("single1");
assertThat(single1).isEqualTo("value2");
}
@Test
@SuppressWarnings("unchecked")
public void testBuilderSingleTypes() {
List<SelectItem> selectItems1 = Arrays.asList(SelectItem.of("key1", "value1"), SelectItem.of("key2", "value2"));
Map<String, String> selectItems2 = new HashMap<>();
selectItems2.put("key2", "value2");
selectItems2.put("key3", "value3");
Builder builder1 = ComponentFlow.builder()
.withSingleItemSelector("field1")
.selectItems(selectItems1)
.and();
Builder builder2 = ComponentFlow.builder()
.withSingleItemSelector("field2")
.selectItems(selectItems2)
.and();
List<BaseSingleItemSelector> field1 = (List<BaseSingleItemSelector>) ReflectionTestUtils.getField(builder1,
"singleItemSelectors");
List<BaseSingleItemSelector> field2 = (List<BaseSingleItemSelector>) ReflectionTestUtils.getField(builder2,
"singleItemSelectors");
assertThat(field1).hasSize(1);
assertThat(field2).hasSize(1);
List<SelectItem> selectItems11 = (List<SelectItem>) ReflectionTestUtils.getField(field1.get(0), "selectItems");
List<SelectItem> selectItems21 = (List<SelectItem>) ReflectionTestUtils.getField(field2.get(0), "selectItems");
assertThat(selectItems11).hasSize(2);
assertThat(selectItems21).hasSize(2);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2022 the original author or authors.
* Copyright 2022-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,9 +33,8 @@ public class FlowComponentSnippets {
private ComponentFlow.Builder componentFlowBuilder;
public void runFlow() {
Map<String, String> single1SelectItems = new HashMap<>();
single1SelectItems.put("key1", "value1");
single1SelectItems.put("key2", "value2");
List<SelectItem> single1SelectItems = Arrays.asList(SelectItem.of("key1", "value1"),
SelectItem.of("key2", "value2"));
List<SelectItem> multi1SelectItems = Arrays.asList(SelectItem.of("key1", "value1"),
SelectItem.of("key2", "value2"), SelectItem.of("key3", "value3"));
ComponentFlow flow = componentFlowBuilder.clone().reset()