Skip to content

Commit 2ed984c

Browse files
Added custom message to ensure only one (#2644)
Co-authored-by: James White <[email protected]> Co-authored-by: Stephen Colebourne <[email protected]>
1 parent 502bb6a commit 2ed984c

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

modules/collect/src/main/java/com/opengamma/strata/collect/Guavate.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,7 @@ public static <R> Predicate<R> not(Predicate<R> predicate) {
682682
*
683683
* @param <T> the type of element in the stream
684684
* @return the operator
685+
* @throws IllegalArgumentException if more than one element is present
685686
*/
686687
public static <T> BinaryOperator<T> ensureOnlyOne() {
687688
return (a, b) -> {
@@ -690,6 +691,31 @@ public static <T> BinaryOperator<T> ensureOnlyOne() {
690691
};
691692
}
692693

694+
/**
695+
* Reducer used in a stream to ensure there is no more than one matching element.
696+
* <p>
697+
* This method returns an operator that can be used with {@link Stream#reduce(BinaryOperator)}
698+
* that returns either zero or one elements from the stream. Unlike {@link Stream#findFirst()}
699+
* or {@link Stream#findAny()}, this approach ensures an exception is thrown if there
700+
* is more than one element in the stream.
701+
* <p>
702+
* This would be used as follows (with a static import):
703+
* <pre>
704+
* stream.filter(...).reduce(ensureOnlyOne()).get();
705+
* </pre>
706+
*
707+
* @param <T> the type of element in the stream
708+
* @param message the message template for the {@link IllegalArgumentException} with "{}" placeholders
709+
* @param args the arguments for the message
710+
* @return the operator
711+
* @throws IllegalArgumentException if more than one element is present
712+
*/
713+
public static <T> BinaryOperator<T> ensureOnlyOne(String message, Object... args) {
714+
return (a, b) -> {
715+
throw new IllegalArgumentException(Messages.format(message, args));
716+
};
717+
}
718+
693719
//-------------------------------------------------------------------------
694720
/**
695721
* Function used in a stream to cast instances to a particular type without filtering.

modules/collect/src/test/java/com/opengamma/strata/collect/GuavateTest.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,17 @@ public void test_ensureOnlyOne() {
424424
assertThatIllegalArgumentException().isThrownBy(() -> Stream.of("a", "b").reduce(Guavate.ensureOnlyOne()));
425425
}
426426

427+
@Test
428+
public void test_ensureOnlyOne_withCustomMessage() {
429+
String message = "Expected one letter but found multiple for date {}";
430+
LocalDate arg = LocalDate.of(2024, 4, 24);
431+
assertThat(Stream.empty().reduce(Guavate.ensureOnlyOne(message, arg))).isEqualTo(Optional.empty());
432+
assertThat(Stream.of("a").reduce(Guavate.ensureOnlyOne(message, arg))).isEqualTo(Optional.of("a"));
433+
assertThatIllegalArgumentException().isThrownBy(() -> Stream.of("a", "b")
434+
.reduce(Guavate.ensureOnlyOne(message, arg)))
435+
.withMessage(Messages.format(message, arg));
436+
}
437+
427438
//-------------------------------------------------------------------------
428439
@Test
429440
public void test_casting() {

0 commit comments

Comments
 (0)