diff --git a/src/main/java/io/vavr/control/Try.java b/src/main/java/io/vavr/control/Try.java index 775ba7b7a..1e30f7114 100644 --- a/src/main/java/io/vavr/control/Try.java +++ b/src/main/java/io/vavr/control/Try.java @@ -1398,6 +1398,19 @@ public static WithResources return new WithResources2<>(t1Supplier, t2Supplier); } + /** + * Creates a {@code Try}-with-resources builder that operates on two {@link AutoCloseable} chained (dependent) resources. + * + * @param t1Supplier The supplier of the 1st resource. + * @param t2Function A function which takes the supply of t1 and supplies the 2nd resource. + * @param Type of the 1st resource. + * @param Type of the 2nd resource. + * @return a new {@link WithThreadedResources2} instance. + */ + public static WithThreadedResources2 withResources(CheckedFunction0 t1Supplier, CheckedFunction1 t2Function) { + return new WithThreadedResources2<>(t1Supplier, t2Function); + } + /** * Creates a {@code Try}-with-resources builder that operates on three {@link AutoCloseable} resources. * @@ -1413,6 +1426,21 @@ public static (t1Supplier, t2Supplier, t3Supplier); } + /** + * Creates a {@code Try}-with-resources builder that operates on three {@link AutoCloseable} chained (dependent) resources. + * + * @param t1Supplier The supplier of the 1st resource. + * @param t2Function A function which takes a supply of the 1st resource and supplies the 2nd resource. + * @param t3Function A function which takes a supply of the 2nd resource and supplies the 3rd resource. + * @param Type of the 1st resource. + * @param Type of the 2nd resource. + * @param Type of the 3rd resource. + * @return a new {@link WithThreadedResources3} instance. + */ + public static WithThreadedResources3 withResources(CheckedFunction0 t1Supplier, CheckedFunction1 t2Function, CheckedFunction1 t3Function) { + return new WithThreadedResources3<>(t1Supplier, t2Function, t3Function); + } + /** * Creates a {@code Try}-with-resources builder that operates on four {@link AutoCloseable} resources. * @@ -1581,6 +1609,39 @@ public Try of(CheckedFunction2 f) { } } + /** + * A {@code Try}-with-resources builder that operates on two {@link AutoCloseable} threaded (dependent) resources. + * + * @param Type of the 1st resource. + * @param Type of the 2nd resource. + */ + public static final class WithThreadedResources2 { + + private final CheckedFunction0 t1Supplier; + private final CheckedFunction1 t2Function; + + private WithThreadedResources2(CheckedFunction0 t1Supplier, CheckedFunction1 t2Function) { + this.t1Supplier = t1Supplier; + this.t2Function = t2Function; + } + + /** + * Wraps the result of a computation that may fail in a {@code Try}. + * + * @param f A computation that takes two {@code AutoClosable} resources. + * @param Result type of the computation. + * @return A new {@code Try} instance. + */ + @SuppressWarnings("try")/* https://bugs.openjdk.java.net/browse/JDK-8155591 */ + public Try of(CheckedFunction1 f) { + return Try.of(() -> { + try (T1 t1 = t1Supplier.apply(); T2 t2 = t2Function.apply(t1)) { + return f.apply(t2); + } + }); + } + } + /** * A {@code Try}-with-resources builder that operates on three {@link AutoCloseable} resources. * @@ -1617,6 +1678,42 @@ public Try of(CheckedFunction3 Type of the 1st resource. + * @param Type of the 2nd resource. + * @param Type of the 3rd resource. + */ + public static final class WithThreadedResources3 { + + private final CheckedFunction0 t1Supplier; + private final CheckedFunction1 t2Function; + private final CheckedFunction1 t3Function; + + private WithThreadedResources3(CheckedFunction0 t1Supplier, CheckedFunction1 t2Function, CheckedFunction1 t3Function) { + this.t1Supplier = t1Supplier; + this.t2Function = t2Function; + this.t3Function = t3Function; + } + + /** + * Wraps the result of a computation that may fail in a {@code Try}. + * + * @param f A computation that takes three {@code AutoClosable} resources. + * @param Result type of the computation. + * @return A new {@code Try} instance. + */ + @SuppressWarnings("try")/* https://bugs.openjdk.java.net/browse/JDK-8155591 */ + public Try of(CheckedFunction1 f) { + return Try.of(() -> { + try (T1 t1 = t1Supplier.apply(); T2 t2 = t2Function.apply(t1); T3 t3 = t3Function.apply(t2)) { + return f.apply(t3); + } + }); + } + } + /** * A {@code Try}-with-resources builder that operates on four {@link AutoCloseable} resources. * diff --git a/src/test/java/io/vavr/control/TryTest.java b/src/test/java/io/vavr/control/TryTest.java index a27ccf94e..1005a7db8 100644 --- a/src/test/java/io/vavr/control/TryTest.java +++ b/src/test/java/io/vavr/control/TryTest.java @@ -627,6 +627,50 @@ public void shouldCreateFailureTryWithResources8() { assertThat(closeable8.isClosed).isTrue(); } + @Test + public void shouldCreateSuccessTryWithThreadedResources2() { + final Closeable closeable1 = Closeable.of(1); + final Closeable closeable2 = Closeable.of(2); + final Try actual = Try.withResources(() -> closeable1, i1 -> closeable2).of(i2 -> "" + i2.value); + assertThat(actual).isEqualTo(Success("2")); + assertThat(closeable1.isClosed).isTrue(); + assertThat(closeable2.isClosed).isTrue(); + } + + @Test + public void shouldCreateFailureTryWithThreadedResources2() { + final Closeable closeable1 = Closeable.of(1); + final Closeable closeable2 = Closeable.of(2); + final Try actual = Try.withResources(() -> closeable1, i1 -> closeable2).of(i2 -> { throw new Error(); }); + assertThat(actual.isFailure()).isTrue(); + assertThat(closeable1.isClosed).isTrue(); + assertThat(closeable2.isClosed).isTrue(); + } + + @Test + public void shouldCreateSuccessTryWithChainedResources3() { + final Closeable closeable1 = Closeable.of(1); + final Closeable closeable2 = Closeable.of(2); + final Closeable closeable3 = Closeable.of(3); + final Try actual = Try.withResources(() -> closeable1, i1 -> closeable2, i2 -> closeable3).of(i3 -> "" + i3.value); + assertThat(actual).isEqualTo(Success("3")); + assertThat(closeable1.isClosed).isTrue(); + assertThat(closeable2.isClosed).isTrue(); + assertThat(closeable3.isClosed).isTrue(); + } + + @Test + public void shouldCreateFailureTryWithThreadedResources3() { + final Closeable closeable1 = Closeable.of(1); + final Closeable closeable2 = Closeable.of(2); + final Closeable closeable3 = Closeable.of(3); + final Try actual = Try.withResources(() -> closeable1, i1 -> closeable2, i2 -> closeable3).of(i3 -> { throw new Error(); }); + assertThat(actual.isFailure()).isTrue(); + assertThat(closeable1.isClosed).isTrue(); + assertThat(closeable2.isClosed).isTrue(); + assertThat(closeable3.isClosed).isTrue(); + } + // -- Failure.Cause @Test