From 12c5ed2989606b7a5bdeaca98cbd3c6d7fa0153f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9da=20Housni=20Alaoui?= Date: Fri, 13 Feb 2026 16:15:23 +0100 Subject: [PATCH] Support HAL-Forms options 'selectedValues' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Réda Housni Alaoui --- .../mediatype/hal/forms/HalFormsOptions.java | 58 +++++++++++++------ .../HalFormsJacksonModuleIntegrationTest.java | 8 ++- 2 files changed, 47 insertions(+), 19 deletions(-) diff --git a/src/main/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsOptions.java b/src/main/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsOptions.java index 941d70938..e711880a7 100644 --- a/src/main/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsOptions.java +++ b/src/main/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsOptions.java @@ -63,7 +63,7 @@ public static Inline inline(Collection values) { Assert.notNull(values, "Values must not be null!"); - return new Inline(values, null, null, null, null, null); + return new Inline(values, null, null, null, null, null, null); } /** @@ -76,7 +76,7 @@ public static Remote remote(Link link) { Assert.notNull(link, "Link must not be null!"); - return new Remote(link, null, null, null, null, null); + return new Remote(link, null, null, null, null, null, null); } /** @@ -127,15 +127,19 @@ public static Remote remote(String href) { @Nullable Object getSelectedValue(); + @Nullable + Object getSelectedValues(); + public static abstract class AbstractHalFormsOptions> implements HalFormsOptions { private final @Nullable String promptField, valueField; private final @Nullable Long minItems, maxItems; private final @Nullable Object selectedValue; + private final @Nullable Object selectedValues; protected AbstractHalFormsOptions(@Nullable String promptRef, @Nullable String valueRef, @Nullable Long minItems, - @Nullable Long maxItems, @Nullable Object selectedValue) { + @Nullable Long maxItems, @Nullable Object selectedValue, @Nullable Object selectedValues) { Assert.isTrue(minItems == null || minItems >= 0, "MinItems must be greater than or equal to 0!"); @@ -144,6 +148,7 @@ protected AbstractHalFormsOptions(@Nullable String promptRef, @Nullable String v this.minItems = minItems; this.maxItems = maxItems; this.selectedValue = selectedValue; + this.selectedValues = selectedValues; } /* @@ -201,6 +206,13 @@ public Object getSelectedValue() { return selectedValue; } + @Nullable + @Override + @JsonProperty + public Object getSelectedValues() { + return selectedValues; + } + /** * Configures the given field to be used as prompt field. * @@ -213,7 +225,7 @@ public T withPromptField(String promptField) { throw new IllegalArgumentException("Prompt field has to either be null or actually have text!"); } - return with(promptField, valueField, minItems, maxItems, selectedValue); + return with(promptField, valueField, minItems, maxItems, selectedValue, selectedValues); } /** @@ -228,7 +240,7 @@ public T withValueField(String valueField) { throw new IllegalArgumentException("Value field has to either be null or actually have text!"); } - return with(promptField, valueField, minItems, maxItems, selectedValue); + return with(promptField, valueField, minItems, maxItems, selectedValue, selectedValues); } /** @@ -243,7 +255,7 @@ public T withMinItems(Long minItems) { throw new IllegalArgumentException("minItems has to be null or greater or equal to zero!"); } - return with(promptField, valueField, minItems, maxItems, selectedValue); + return with(promptField, valueField, minItems, maxItems, selectedValue, selectedValues); } /** @@ -258,7 +270,7 @@ public T withMaxItems(@Nullable Long maxItems) { throw new IllegalArgumentException("maxItems has to be null or greater than zero!"); } - return with(promptField, valueField, minItems, maxItems, selectedValue); + return with(promptField, valueField, minItems, maxItems, selectedValue, selectedValues); } /** @@ -266,9 +278,21 @@ public T withMaxItems(@Nullable Long maxItems) { * * @param value * @return + * @deprecated Use {@link #withSelectedValues(Object)} instead */ + @Deprecated(forRemoval = true) public T withSelectedValue(@Nullable Object value) { - return with(promptField, valueField, minItems, maxItems, value); + return with(promptField, valueField, minItems, maxItems, value, selectedValues); + } + + /** + * Configured the values to be initially selected + * + * @param values + * @return + */ + public T withSelectedValues(@Nullable Object values) { + return with(promptField, valueField, minItems, maxItems, selectedValue, values); } /** @@ -281,7 +305,7 @@ public T withSelectedValue(@Nullable Object value) { * @return */ protected abstract T with(@Nullable String promptRef, @Nullable String valueRef, @Nullable Long minItems, - @Nullable Long maxItems, @Nullable Object selectedValue); + @Nullable Long maxItems, @Nullable Object selectedValue, @Nullable Object selectedValues); } public static class Inline extends AbstractHalFormsOptions { @@ -294,9 +318,9 @@ public static class Inline extends AbstractHalFormsOptions { * @param valueRef */ private Inline(Collection values, @Nullable String promptRef, @Nullable String valueRef, - @Nullable Long minItems, @Nullable Long maxItems, @Nullable Object selectedValue) { + @Nullable Long minItems, @Nullable Long maxItems, @Nullable Object selectedValue, @Nullable Object selectedValues) { - super(promptRef, valueRef, minItems, maxItems, selectedValue); + super(promptRef, valueRef, minItems, maxItems, selectedValue, selectedValues); Assert.notNull(values, "Values must not be null!"); @@ -319,8 +343,8 @@ public Collection getInline() { */ @Override protected Inline with(@Nullable String promptRef, @Nullable String valueRef, @Nullable Long minItems, - @Nullable Long maxItems, @Nullable Object selectedValue) { - return new Inline(inline, promptRef, valueRef, minItems, maxItems, selectedValue); + @Nullable Long maxItems, @Nullable Object selectedValue, @Nullable Object selectedValues) { + return new Inline(inline, promptRef, valueRef, minItems, maxItems, selectedValue, selectedValues); } } @@ -334,9 +358,9 @@ public static class Remote extends AbstractHalFormsOptions { private final Link link; private Remote(Link link, @Nullable String promptRef, @Nullable String valueRef, @Nullable Long minItems, - @Nullable Long maxItems, @Nullable Object selectedValue) { + @Nullable Long maxItems, @Nullable Object selectedValue, @Nullable Object selectedValues) { - super(promptRef, valueRef, minItems, maxItems, selectedValue); + super(promptRef, valueRef, minItems, maxItems, selectedValue, selectedValues); Assert.notNull(link, "Link must not be null!"); @@ -359,8 +383,8 @@ public Link getLink() { */ @Override protected Remote with(@Nullable String promptRef, @Nullable String valueRef, @Nullable Long minItems, - @Nullable Long maxItems, @Nullable Object selectedValue) { - return new Remote(link, promptRef, valueRef, minItems, maxItems, selectedValue); + @Nullable Long maxItems, @Nullable Object selectedValue, @Nullable Object selectedValues) { + return new Remote(link, promptRef, valueRef, minItems, maxItems, selectedValue, selectedValues); } } } diff --git a/src/test/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsJacksonModuleIntegrationTest.java b/src/test/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsJacksonModuleIntegrationTest.java index f9f3feb21..f68ae5286 100644 --- a/src/test/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsJacksonModuleIntegrationTest.java +++ b/src/test/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsJacksonModuleIntegrationTest.java @@ -466,7 +466,8 @@ void rendersFullInlineOptions() { .withPromptField("my-prompt-field") .withValueField("my-value-field") .withMinItems(2L) - .withMaxItems(3L); + .withMaxItems(3L) + .withSelectedValues(List.of("bar", "baz")); getCuriedMapper() .assertSerializes(options) @@ -478,6 +479,7 @@ void rendersFullInlineOptions() { assertThat(result.read("$.valueField", String.class)).isEqualTo("my-value-field"); assertThat(result.read("$.minItems", Long.class)).isEqualTo(2L); assertThat(result.read("$.maxItems", Long.class)).isEqualTo(3L); + assertThat(result.read("$.selectedValues", List.class)).isEqualTo(List.of("bar", "baz")); }); } @@ -490,7 +492,8 @@ void rendersFullRemoteOptions() { .withPromptField("my-prompt-field") .withValueField("my-value-field") .withMinItems(2L) - .withMaxItems(3L); + .withMaxItems(3L) + .withSelectedValues(List.of("bar", "baz")); getCuriedMapper() .assertSerializes(options) @@ -503,6 +506,7 @@ void rendersFullRemoteOptions() { assertThat(result.read("$.valueField", String.class)).isEqualTo("my-value-field"); assertThat(result.read("$.minItems", Long.class)).isEqualTo(2L); assertThat(result.read("$.maxItems", Long.class)).isEqualTo(3L); + assertThat(result.read("$.selectedValues", List.class)).isEqualTo(List.of("bar", "baz")); }); }