Skip to content

Commit b48b322

Browse files
committed
#1508 - Convenience methods for cardinality on HalFormsOptions.
1 parent 43b9f29 commit b48b322

File tree

2 files changed

+101
-1
lines changed

2 files changed

+101
-1
lines changed

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

+55-1
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ public T withMinItems(Long minItems) {
230230
* @param maxItems must be {@literal null} or greater than zero.
231231
* @return
232232
*/
233-
public T withMaxItems(Long maxItems) {
233+
public T withMaxItems(@Nullable Long maxItems) {
234234

235235
if (maxItems != null && maxItems <= 0) {
236236
throw new IllegalArgumentException("maxItems has to be null or greater than zero!");
@@ -239,6 +239,60 @@ public T withMaxItems(Long maxItems) {
239239
return with(promptField, valueField, minItems, maxItems);
240240
}
241241

242+
/**
243+
* Configures the options return an optional value, i.e. cardinality [0, 1].
244+
*
245+
* @return
246+
*/
247+
public T optional() {
248+
return withMinItems(0L).withMaxItems(1L);
249+
}
250+
251+
/**
252+
* Configures the options return an optional collection, i.e. cardinality [0, *].
253+
*
254+
* @return
255+
*/
256+
public T optionalCollection() {
257+
return withMinItems(0L).withMaxItems(null);
258+
}
259+
260+
/**
261+
* Configures the options return an optional collection with a maximum number of elements, i.e. cardinality [0, n].
262+
*
263+
* @return
264+
*/
265+
public T optionalCollection(long maxItems) {
266+
return withMinItems(0L).withMaxItems(maxItems);
267+
}
268+
269+
/**
270+
* Configures the options return a required value, i.e. cardinality [1, 1].
271+
*
272+
* @return
273+
*/
274+
public T required() {
275+
return withMinItems(1L).withMaxItems(1L);
276+
}
277+
278+
/**
279+
* Configures the options return a required collection, i.e. cardinality [1, *].
280+
*
281+
* @return
282+
*/
283+
public T requiredCollection() {
284+
return withMinItems(1L).withMaxItems(null);
285+
}
286+
287+
/**
288+
* Configures the options return a required collection with a maximum number of items, i.e. cardinality [1, n].
289+
*
290+
* @return
291+
*/
292+
public T requiredCollection(long maxItems) {
293+
return withMinItems(1L).withMaxItems(maxItems);
294+
}
295+
242296
/**
243297
* Create a new concrete {@link AbstractHalFormsOptions}
244298
*

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

+46
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,14 @@
1818
import static org.assertj.core.api.Assertions.*;
1919

2020
import lombok.Getter;
21+
import lombok.Value;
2122

2223
import java.util.Arrays;
2324
import java.util.List;
2425
import java.util.Map;
2526
import java.util.Optional;
27+
import java.util.function.Function;
28+
import java.util.stream.Stream;
2629

2730
import javax.validation.constraints.Max;
2831
import javax.validation.constraints.Min;
@@ -31,16 +34,21 @@
3134

3235
import org.hibernate.validator.constraints.Length;
3336
import org.hibernate.validator.constraints.Range;
37+
import org.junit.jupiter.api.DynamicTest;
3438
import org.junit.jupiter.api.Test;
39+
import org.junit.jupiter.api.TestFactory;
3540
import org.junit.jupiter.params.ParameterizedTest;
3641
import org.junit.jupiter.params.provider.CsvSource;
3742
import org.springframework.hateoas.Link;
3843
import org.springframework.hateoas.LinkRelation;
3944
import org.springframework.hateoas.RepresentationModel;
4045
import org.springframework.hateoas.mediatype.Affordances;
4146
import org.springframework.hateoas.mediatype.MessageResolver;
47+
import org.springframework.hateoas.mediatype.hal.forms.HalFormsOptions.AbstractHalFormsOptions;
48+
import org.springframework.hateoas.mediatype.hal.forms.HalFormsOptions.Inline;
4249
import org.springframework.http.HttpMethod;
4350
import org.springframework.http.MediaType;
51+
import org.springframework.lang.Nullable;
4452

4553
/**
4654
* @author Oliver Drotbohm
@@ -182,6 +190,20 @@ void rendersRegisteredSuggest() {
182190
});
183191
}
184192

193+
@TestFactory
194+
Stream<DynamicTest> expressesCardinalityOnOptions() {
195+
196+
Stream<Cardinality> stream = Stream.of( //
197+
Cardinality.of("optional", AbstractHalFormsOptions::optional, 0L, 1L), //
198+
Cardinality.of("optionalCollection", AbstractHalFormsOptions::optionalCollection, 0L, null), //
199+
Cardinality.of("optionalCollection(n)", it -> it.optionalCollection(5L), 0L, 5L), //
200+
Cardinality.of("required", AbstractHalFormsOptions::required, 1L, 1L), //
201+
Cardinality.of("requiredCollection", AbstractHalFormsOptions::requiredCollection, 1L, null), //
202+
Cardinality.of("requiredCollection(n)", it -> it.requiredCollection(5L), 1L, 5L));
203+
204+
return DynamicTest.stream(stream, Cardinality::toString, Cardinality::verify);
205+
}
206+
185207
@Getter
186208
static class PatternExample extends RepresentationModel<PatternExample> {
187209

@@ -215,4 +237,28 @@ static class Payload {
215237
@Range(min = 8, max = 10) //
216238
Integer range;
217239
}
240+
241+
@Value(staticConstructor = "of")
242+
static class Cardinality {
243+
244+
String title;
245+
Function<AbstractHalFormsOptions<?>, AbstractHalFormsOptions<?>> mapper;
246+
Long expectedMin;
247+
@Nullable Long expectedMax;
248+
249+
void verify() {
250+
251+
Inline inline = HalFormsOptions.inline();
252+
HalFormsOptions result = mapper.apply(inline);
253+
254+
assertThat(result.getMinItems()).isEqualTo(expectedMin);
255+
assertThat(result.getMaxItems()).isEqualTo(expectedMax);
256+
}
257+
258+
@Override
259+
public String toString() {
260+
return String.format("Calling HalFormsOptions.%s() configures minItems to %s and maxItems to %s.", //
261+
title, expectedMin, expectedMax);
262+
}
263+
}
218264
}

0 commit comments

Comments
 (0)