From 32436acd72461ab2454916718349a9892f717472 Mon Sep 17 00:00:00 2001 From: James White Date: Wed, 24 Apr 2024 17:23:09 +0100 Subject: [PATCH] Added custom message to ensure only one --- .../com/opengamma/strata/collect/Guavate.java | 26 +++++++++++++++++++ .../opengamma/strata/collect/GuavateTest.java | 11 ++++++++ 2 files changed, 37 insertions(+) diff --git a/modules/collect/src/main/java/com/opengamma/strata/collect/Guavate.java b/modules/collect/src/main/java/com/opengamma/strata/collect/Guavate.java index d5a90ada35..95bf48d9ee 100644 --- a/modules/collect/src/main/java/com/opengamma/strata/collect/Guavate.java +++ b/modules/collect/src/main/java/com/opengamma/strata/collect/Guavate.java @@ -682,6 +682,7 @@ public static Predicate not(Predicate predicate) { * * @param the type of element in the stream * @return the operator + * @throws IllegalArgumentException if more than one element is present */ public static BinaryOperator ensureOnlyOne() { return (a, b) -> { @@ -690,6 +691,31 @@ public static BinaryOperator ensureOnlyOne() { }; } + /** + * Reducer used in a stream to ensure there is no more than one matching element. + *

+ * This method returns an operator that can be used with {@link Stream#reduce(BinaryOperator)} + * that returns either zero or one elements from the stream. Unlike {@link Stream#findFirst()} + * or {@link Stream#findAny()}, this approach ensures an exception is thrown if there + * is more than one element in the stream. + *

+ * This would be used as follows (with a static import): + *

+   *   stream.filter(...).reduce(ensureOnlyOne()).get();
+   * 
+ * + * @param the type of element in the stream + * @param message the message template for the {@link IllegalArgumentException} with "{}" placeholders + * @param args the arguments for the message + * @return the operator + * @throws IllegalArgumentException if more than one element is present + */ + public static BinaryOperator ensureOnlyOne(String message, Object... args) { + return (a, b) -> { + throw new IllegalArgumentException(Messages.format(message, args)); + }; + } + //------------------------------------------------------------------------- /** * Function used in a stream to cast instances to a particular type without filtering. diff --git a/modules/collect/src/test/java/com/opengamma/strata/collect/GuavateTest.java b/modules/collect/src/test/java/com/opengamma/strata/collect/GuavateTest.java index 176748dfa9..a0363c1f69 100644 --- a/modules/collect/src/test/java/com/opengamma/strata/collect/GuavateTest.java +++ b/modules/collect/src/test/java/com/opengamma/strata/collect/GuavateTest.java @@ -424,6 +424,17 @@ public void test_ensureOnlyOne() { assertThatIllegalArgumentException().isThrownBy(() -> Stream.of("a", "b").reduce(Guavate.ensureOnlyOne())); } + @Test + public void test_ensureOnlyOne_withCustomMessage() { + String message = "Expected one letter but found multiple for date {}"; + LocalDate arg = LocalDate.of(2024, 4, 24); + assertThat(Stream.empty().reduce(Guavate.ensureOnlyOne(message, arg))).isEqualTo(Optional.empty()); + assertThat(Stream.of("a").reduce(Guavate.ensureOnlyOne(message, arg))).isEqualTo(Optional.of("a")); + assertThatIllegalArgumentException().isThrownBy(() -> Stream.of("a", "b") + .reduce(Guavate.ensureOnlyOne(message, arg))) + .withMessage(Messages.format(message, arg)); + } + //------------------------------------------------------------------------- @Test public void test_casting() {