Skip to content

Commit bbb8f42

Browse files
committed
#1510 - Support for defining the selected value on HalFormsOptions.
We now expose a HalFormsOptions.withSelectedValue(…) and propagate this into the HAL FORMS property field named "value".
1 parent 3977514 commit bbb8f42

File tree

4 files changed

+82
-27
lines changed

4 files changed

+82
-27
lines changed

src/main/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsOptions.java

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.springframework.util.Assert;
2424
import org.springframework.util.StringUtils;
2525

26+
import com.fasterxml.jackson.annotation.JsonIgnore;
2627
import com.fasterxml.jackson.annotation.JsonInclude;
2728
import com.fasterxml.jackson.annotation.JsonInclude.Include;
2829
import com.fasterxml.jackson.annotation.JsonProperty;
@@ -61,7 +62,7 @@ public static Inline inline(Collection<? extends Object> values) {
6162

6263
Assert.notNull(values, "Values must not be null!");
6364

64-
return new Inline(values, null, null, null, null);
65+
return new Inline(values, null, null, null, null, null);
6566
}
6667

6768
/**
@@ -74,7 +75,7 @@ public static Remote remote(Link link) {
7475

7576
Assert.notNull(link, "Link must not be null!");
7677

77-
return new Remote(link, null, null, null, null);
78+
return new Remote(link, null, null, null, null, null);
7879
}
7980

8081
/**
@@ -122,21 +123,26 @@ public static Remote remote(String href) {
122123
@Nullable
123124
Long getMaxItems();
124125

126+
@Nullable
127+
Object getSelectedValue();
128+
125129
public static abstract class AbstractHalFormsOptions<T extends AbstractHalFormsOptions<T>>
126130
implements HalFormsOptions {
127131

128132
private final @Nullable String promptField, valueField;
129133
private final @Nullable Long minItems, maxItems;
134+
private final @Nullable Object selectedValue;
130135

131136
protected AbstractHalFormsOptions(@Nullable String promptRef, @Nullable String valueRef, @Nullable Long minItems,
132-
@Nullable Long maxItems) {
137+
@Nullable Long maxItems, @Nullable Object selectedValue) {
133138

134139
Assert.isTrue(minItems == null || minItems >= 0, "MinItems must be greater than or equal to 0!");
135140

136141
this.promptField = promptRef;
137142
this.valueField = valueRef;
138143
this.minItems = minItems;
139144
this.maxItems = maxItems;
145+
this.selectedValue = selectedValue;
140146
}
141147

142148
/*
@@ -179,6 +185,17 @@ public Long getMaxItems() {
179185
return maxItems;
180186
}
181187

188+
/*
189+
* (non-Javadoc)
190+
* @see org.springframework.hateoas.mediatype.hal.forms.HalFormsOptions#getSelectedValue()
191+
*/
192+
@Nullable
193+
@Override
194+
@JsonIgnore
195+
public Object getSelectedValue() {
196+
return selectedValue;
197+
}
198+
182199
/**
183200
* Configures the given field to be used as prompt field.
184201
*
@@ -191,7 +208,7 @@ public T withPromptField(String promptField) {
191208
throw new IllegalArgumentException("Prompt field has to either be null or actually have text!");
192209
}
193210

194-
return with(promptField, valueField, minItems, maxItems);
211+
return with(promptField, valueField, minItems, maxItems, selectedValue);
195212
}
196213

197214
/**
@@ -206,7 +223,7 @@ public T withValueField(String valueField) {
206223
throw new IllegalArgumentException("Value field has to either be null or actually have text!");
207224
}
208225

209-
return with(promptField, valueField, minItems, maxItems);
226+
return with(promptField, valueField, minItems, maxItems, selectedValue);
210227
}
211228

212229
/**
@@ -221,7 +238,7 @@ public T withMinItems(Long minItems) {
221238
throw new IllegalArgumentException("minItems has to be null or greater or equal to zero!");
222239
}
223240

224-
return with(promptField, valueField, minItems, maxItems);
241+
return with(promptField, valueField, minItems, maxItems, selectedValue);
225242
}
226243

227244
/**
@@ -230,13 +247,23 @@ public T withMinItems(Long minItems) {
230247
* @param maxItems must be {@literal null} or greater than zero.
231248
* @return
232249
*/
233-
public T withMaxItems(Long maxItems) {
250+
public T withMaxItems(@Nullable Long maxItems) {
234251

235252
if (maxItems != null && maxItems <= 0) {
236253
throw new IllegalArgumentException("maxItems has to be null or greater than zero!");
237254
}
238255

239-
return with(promptField, valueField, minItems, maxItems);
256+
return with(promptField, valueField, minItems, maxItems, selectedValue);
257+
}
258+
259+
/**
260+
* Configured the value to be initially selected
261+
*
262+
* @param value
263+
* @return
264+
*/
265+
public T withSelectedValue(@Nullable Object value) {
266+
return with(promptField, valueField, minItems, maxItems, value);
240267
}
241268

242269
/**
@@ -249,7 +276,7 @@ public T withMaxItems(Long maxItems) {
249276
* @return
250277
*/
251278
protected abstract T with(@Nullable String promptRef, @Nullable String valueRef, @Nullable Long minItems,
252-
@Nullable Long maxItems);
279+
@Nullable Long maxItems, @Nullable Object selectedValue);
253280
}
254281

255282
public static class Inline extends AbstractHalFormsOptions<Inline> {
@@ -262,9 +289,9 @@ public static class Inline extends AbstractHalFormsOptions<Inline> {
262289
* @param valueRef
263290
*/
264291
private Inline(Collection<? extends Object> values, @Nullable String promptRef, @Nullable String valueRef,
265-
@Nullable Long minItems, @Nullable Long maxItems) {
292+
@Nullable Long minItems, @Nullable Long maxItems, @Nullable Object selectedValue) {
266293

267-
super(promptRef, valueRef, minItems, maxItems);
294+
super(promptRef, valueRef, minItems, maxItems, selectedValue);
268295

269296
Assert.notNull(values, "Values must not be null!");
270297

@@ -283,12 +310,12 @@ public Collection<? extends Object> getInline() {
283310

284311
/*
285312
* (non-Javadoc)
286-
* @see org.springframework.hateoas.mediatype.hal.forms.HalFormsOptions.AbstractHalFormsOptions#with(java.lang.String, java.lang.String, java.lang.Long, java.lang.Long)
313+
* @see org.springframework.hateoas.mediatype.hal.forms.HalFormsOptions.AbstractHalFormsOptions#with(java.lang.String, java.lang.String, java.lang.Long, java.lang.Long, java.lang.Object)
287314
*/
288315
@Override
289316
protected Inline with(@Nullable String promptRef, @Nullable String valueRef, @Nullable Long minItems,
290-
@Nullable Long maxItems) {
291-
return new Inline(inline, promptRef, valueRef, minItems, maxItems);
317+
@Nullable Long maxItems, @Nullable Object selectedValue) {
318+
return new Inline(inline, promptRef, valueRef, minItems, maxItems, selectedValue);
292319
}
293320
}
294321

@@ -302,9 +329,9 @@ public static class Remote extends AbstractHalFormsOptions<Remote> {
302329
private final Link link;
303330

304331
private Remote(Link link, @Nullable String promptRef, @Nullable String valueRef, @Nullable Long minItems,
305-
@Nullable Long maxItems) {
332+
@Nullable Long maxItems, @Nullable Object selectedValue) {
306333

307-
super(promptRef, valueRef, minItems, maxItems);
334+
super(promptRef, valueRef, minItems, maxItems, selectedValue);
308335

309336
Assert.notNull(link, "Link must not be null!");
310337

@@ -323,12 +350,12 @@ public Link getLink() {
323350

324351
/*
325352
* (non-Javadoc)
326-
* @see org.springframework.hateoas.mediatype.hal.forms.HalFormsOptions.Foo#withFoo(java.lang.String, java.lang.String)
353+
* @see org.springframework.hateoas.mediatype.hal.forms.HalFormsOptions.AbstractHalFormsOptions#with(java.lang.String, java.lang.String, java.lang.Long, java.lang.Long, java.lang.Object)
327354
*/
328355
@Override
329356
protected Remote with(@Nullable String promptRef, @Nullable String valueRef, @Nullable Long minItems,
330-
@Nullable Long maxItems) {
331-
return new Remote(link, promptRef, valueRef, minItems, maxItems);
357+
@Nullable Long maxItems, @Nullable Object selectedValue) {
358+
return new Remote(link, promptRef, valueRef, minItems, maxItems, selectedValue);
332359
}
333360
}
334361
}

src/main/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsProperty.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@
3838
@JsonInclude(Include.NON_DEFAULT)
3939
final class HalFormsProperty implements Named {
4040

41-
private final String name, value, prompt, regex, placeholder;
41+
private final String name, prompt, regex, placeholder;
42+
private final Object value;
4243
private final boolean templated, multi;
4344
private final @JsonInclude(Include.NON_DEFAULT) boolean readOnly, required;
4445
private final @Nullable Long min, max, minLength, maxLength;
@@ -64,12 +65,13 @@ final class HalFormsProperty implements Named {
6465
this.options = null;
6566
}
6667

67-
private HalFormsProperty(String name, boolean readOnly, String value, String prompt, String regex, boolean templated,
68+
private HalFormsProperty(String name, boolean readOnly, @Nullable Object value, String prompt, String regex,
69+
boolean templated,
6870
boolean required, boolean multi, String placeholder, @Nullable Long min, @Nullable Long max,
6971
@Nullable Long minLength, @Nullable Long maxLength, @Nullable HtmlInputType type,
7072
@Nullable HalFormsOptions options) {
7173

72-
Assert.notNull(name, "name must not be null!");
74+
Assert.notNull(name, "Name must not be null!");
7375

7476
this.name = name;
7577
this.readOnly = readOnly;
@@ -132,7 +134,7 @@ HalFormsProperty withReadOnly(boolean readOnly) {
132134
* @param value
133135
* @return
134136
*/
135-
HalFormsProperty withValue(String value) {
137+
HalFormsProperty withValue(@Nullable Object value) {
136138

137139
return this.value == value ? this
138140
: new HalFormsProperty(this.name, this.readOnly, value, this.prompt, this.regex, this.templated, this.required,
@@ -329,7 +331,7 @@ boolean isReadOnly() {
329331
}
330332

331333
@JsonProperty
332-
String getValue() {
334+
Object getValue() {
333335
return this.value;
334336
}
335337

src/main/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsPropertyFactory.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,13 @@ public List<HalFormsProperty> createProperties(HalFormsAffordanceModel model) {
8080
return Collections.emptyList();
8181
}
8282

83-
HalFormsOptionsFactory options = configuration.getOptionsFactory();
83+
HalFormsOptionsFactory optionsFactory = configuration.getOptionsFactory();
8484

8585
return model.createProperties((payload, metadata) -> {
8686

8787
String inputTypeSource = metadata.getInputType();
8888
HtmlInputType inputType = inputTypeSource == null ? null : HtmlInputType.of(inputTypeSource);
89+
HalFormsOptions options = optionsFactory.getOptions(payload, metadata);
8990

9091
HalFormsProperty property = new HalFormsProperty()
9192
.withName(metadata.getName())
@@ -97,7 +98,8 @@ public List<HalFormsProperty> createProperties(HalFormsAffordanceModel model) {
9798
.withMaxLength(metadata.getMaxLength())
9899
.withRegex(lookupRegex(metadata)) //
99100
.withType(inputType) //
100-
.withOptions(options.getOptions(payload, metadata));
101+
.withValue(options != null ? options.getSelectedValue() : null) //
102+
.withOptions(options);
101103

102104
Function<String, I18nedPropertyMetadata> factory = I18nedPropertyMetadata.factory(payload, property);
103105

src/test/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsTemplateBuilderUnitTest.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ void exposesInputMediaTypeAsContentType() {
158158
}
159159

160160
@Test // #1483
161-
void rendersRegisteredSuggest() {
161+
void rendersInlineOptions() {
162162

163163
List<String> values = Arrays.asList("1234123412341234", "4321432143214321");
164164

@@ -182,6 +182,30 @@ void rendersRegisteredSuggest() {
182182
});
183183
}
184184

185+
@Test // #1510
186+
void propagatesSelectedValueToProperty() {
187+
188+
String selected = "1234123412341234";
189+
List<String> values = Arrays.asList(selected, "4321432143214321");
190+
191+
HalFormsConfiguration configuration = new HalFormsConfiguration()
192+
.withOptions(PatternExample.class, "number",
193+
metadata -> HalFormsOptions.inline(values).withSelectedValue(selected));
194+
195+
RepresentationModel<?> models = new RepresentationModel<>(
196+
Affordances.of(Link.of("/example", LinkRelation.of("create")))
197+
.afford(HttpMethod.POST)
198+
.withInput(PatternExample.class)
199+
.toLink());
200+
201+
Map<String, HalFormsTemplate> templates = new HalFormsTemplateBuilder(configuration, MessageResolver.DEFAULTS_ONLY)
202+
.findTemplates(models);
203+
204+
assertThat(templates.get("default").getPropertyByName("number")).hasValueSatisfying(it -> {
205+
assertThat(it.getValue()).isEqualTo(selected);
206+
});
207+
}
208+
185209
@Getter
186210
static class PatternExample extends RepresentationModel<PatternExample> {
187211

0 commit comments

Comments
 (0)