Skip to content

Commit 9b8971a

Browse files
committed
#1341 - Added Links.addIf(boolean, Link...).
Additional unit tests to increase coverage.
1 parent b4ce728 commit 9b8971a

File tree

2 files changed

+90
-5
lines changed

2 files changed

+90
-5
lines changed

src/main/java/org/springframework/hateoas/Links.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public static Links of(Link... links) {
7676
* @param links
7777
*/
7878
public static Links of(Iterable<Link> links) {
79-
return new Links(links);
79+
return Links.class.isInstance(links) ? Links.class.cast(links) : new Links(links);
8080
}
8181

8282
/**
@@ -134,6 +134,26 @@ public Links and(Link... links) {
134134
return and(Arrays.asList(links));
135135
}
136136

137+
/**
138+
* Adds the given links if the given condition is {@literal true}. The given {@link Link}s will only be resolved if
139+
* the given condition is {@literal true}. Essentially syntactic sugar to write:<br />
140+
* <code>
141+
* if (a > 3) {
142+
* links = links.and(…);
143+
* }
144+
* </code> as <code>
145+
* links = link.andIf(a > 3, …);
146+
* </code>
147+
*
148+
* @param condition
149+
* @param links must not be {@literal null}.
150+
* @return
151+
*/
152+
@SafeVarargs
153+
public final Links andIf(boolean condition, Link... links) {
154+
return condition ? and(links) : this;
155+
}
156+
137157
/**
138158
* Adds the given links if the given condition is {@literal true}. The given {@link Supplier}s will only be resolved
139159
* if the given condition is {@literal true}. Essentially syntactic sugar to write:<br />

src/test/java/org/springframework/hateoas/LinksUnitTest.java

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,12 +143,31 @@ void detectsContainedLinks() {
143143
assertThat(Links.of(first, second).containsSameLinksAs(Links.of(first, second))).isTrue();
144144
}
145145

146-
@Test // #1322
147-
void conditionallyAddsLink() {
146+
@TestFactory // #1322, #1341
147+
Stream<DynamicTest> conditionallyAddsLink() {
148+
149+
Links links = Links.NONE;
150+
Link link = Link.of("/foo");
148151

149-
Links links = Links.NONE.andIf(true, () -> Link.of("/foo"));
152+
List<NamedLinks> adders = Arrays.asList(//
153+
NamedLinks.of("adds via varargs", links.andIf(true, link)), //
154+
NamedLinks.of("adds via Supplier", links.andIf(true, () -> link)), //
155+
NamedLinks.of("adds via Stream", links.andIf(true, Stream.of(link))));
150156

151-
assertThat(links.getRequiredLink(IanaLinkRelations.SELF).getHref()).isEqualTo("/foo");
157+
Stream<DynamicTest> adderTests = DynamicTest.stream(adders.iterator(), NamedLinks::getName, it -> {
158+
assertThat(it.links.getRequiredLink(IanaLinkRelations.SELF).getHref()).isEqualTo("/foo");
159+
});
160+
161+
List<NamedLinks> nonAdders = Arrays.asList(//
162+
NamedLinks.of("does not add via varargs", links.andIf(false, link)), //
163+
NamedLinks.of("does not add via Supplier", links.andIf(false, () -> link)), //
164+
NamedLinks.of("does not add via Stream", links.andIf(false, Stream.of(link))));
165+
166+
Stream<DynamicTest> nonAdderTests = DynamicTest.stream(nonAdders.iterator(), NamedLinks::getName, it -> {
167+
assertThat(it.links).isEmpty();
168+
});
169+
170+
return Stream.concat(adderTests, nonAdderTests);
152171
}
153172

154173
@Test // #1322
@@ -192,6 +211,52 @@ Stream<DynamicTest> mergesStreamOfLinks() {
192211
.element(0).extracting(Link::getHref).isEqualTo("/foo"));
193212
}
194213

214+
@TestFactory // #1340
215+
Stream<DynamicTest> replacesLinksViaMerge() {
216+
217+
Links links = Links.of(Link.of("/foo"));
218+
Link sameRel = Link.of("/bar");
219+
220+
List<NamedLinks> sources = Arrays.asList(//
221+
NamedLinks.of("replace same rel via varargs", links.merge(MergeMode.REPLACE_BY_REL, sameRel)),
222+
NamedLinks.of("replace same rel via Stream", links.merge(MergeMode.REPLACE_BY_REL, Stream.of(sameRel))));
223+
224+
return DynamicTest.stream(sources.iterator(), NamedLinks::getName,
225+
it -> assertThat(it.links).hasSize(1) //
226+
.element(0).extracting(Link::getHref).isEqualTo("/bar"));
227+
}
228+
229+
@Test
230+
void removesLinkByRel() {
231+
assertThat(Links.of(Link.of("/foo")).without(IanaLinkRelations.SELF)).isEmpty();
232+
}
233+
234+
@Test
235+
void basics() {
236+
237+
Links none = Links.NONE;
238+
239+
assertThat(none.isEmpty()).isTrue();
240+
assertThat(none.stream()).isEmpty();
241+
assertThat(none.hasSingleLink()).isFalse();
242+
assertThat(none.hasSize(0)).isTrue();
243+
assertThat(none.hasLink("self")).isFalse();
244+
245+
Links one = none.and(Link.of("/foo"));
246+
247+
assertThat(one.isEmpty()).isFalse();
248+
assertThat(one.stream()).isNotEmpty();
249+
assertThat(one.hasSingleLink()).isTrue();
250+
assertThat(one.hasSize(1)).isTrue();
251+
assertThat(one.hasLink("self")).isTrue();
252+
253+
Links anotherOne = none.and(Link.of("/foo"));
254+
255+
assertThat(anotherOne).isEqualTo(one);
256+
assertThat(one).isEqualTo(anotherOne);
257+
assertThat(one.hashCode()).isEqualTo(anotherOne.hashCode());
258+
}
259+
195260
@Value(staticConstructor = "of")
196261
static class NamedLinks {
197262
String name;

0 commit comments

Comments
 (0)