Skip to content

Commit 091493e

Browse files
committed
Implement recoverAndTry and recoverAllAndTry
1 parent b341a5f commit 091493e

File tree

2 files changed

+115
-0
lines changed

2 files changed

+115
-0
lines changed

vavr/src/main/java/io/vavr/control/Try.java

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -981,6 +981,62 @@ default Try<T> recoverWith(Function<? super Throwable, ? extends Try<? extends T
981981
}
982982
}
983983

984+
/**
985+
* Returns {@code this}, if this is a {@link Try.Success}, otherwise attempts to recover from any failure
986+
* by evaluating the given {@code recoveryAttempt} (via {@link Try#of(CheckedFunction0)}).
987+
*
988+
* <pre>{@code
989+
* // = Success(5)
990+
* Try.of(() -> 5)
991+
* .recoverAllAndTry(() -> 10);
992+
*
993+
* // = Success(10)
994+
* Try.of(() -> 1/0)
995+
* .recoverAllAndTry(() -> 10);
996+
* }</pre>
997+
*
998+
* @param recoveryAttempt A checked function that provides a fallback in case of a failure
999+
* @return a {@code Try} that is either this {@code Success} or a new {@code Try} evaluated from {@code recoveryAttempt}
1000+
* @throws NullPointerException if {@code recoveryAttempt} is null
1001+
*/
1002+
public final Try<T> recoverAllAndTry(CheckedFunction0<? extends T> recoveryAttempt) {
1003+
Objects.requireNonNull(recoveryAttempt, "recoveryAttempt is null");
1004+
return isFailure() ? of(recoveryAttempt) : this;
1005+
}
1006+
1007+
/**
1008+
* Returns {@code this}, if this is a {@link Try.Success}, otherwise attempts to recover from failure when the
1009+
* underlying cause is assignable to the specified {@code exceptionType}, by evaluating the given
1010+
* {@code recoveryAttempt} (via {@link Try#of(CheckedFunction0)}).
1011+
*
1012+
* <pre>{@code
1013+
* // = Success(5)
1014+
* Try.of(() -> 5)
1015+
* .recoverAndTry(ArithmeticException.class, () -> 10);
1016+
*
1017+
* // = Success(10)
1018+
* Try.of(() -> 1/0)
1019+
* .recoverAndTry(ArithmeticException.class, () -> 10);
1020+
*
1021+
* // = Failure(java.lang.ArithmeticException: / by zero)
1022+
* Try.of(() -> 1/0)
1023+
* .recoverAndTry(NullPointerException.class, () -> 10);
1024+
* }</pre>
1025+
*
1026+
* @param <X> The type of the exception that may be recovered
1027+
* @param exceptionType The specific exception type that should trigger the recovery
1028+
* @param recoveryAttempt A checked function that provides a fallback in case of a matching failure
1029+
* @return a {@code Try} that is either this {@code Success}, or a new {@code Try} evaluated from {@code recoveryAttempt}
1030+
* @throws NullPointerException if {@code exceptionType} or {@code recoveryAttempt} is null
1031+
*/
1032+
public final <X extends Throwable> Try<T> recoverAndTry(Class<X> exceptionType, CheckedFunction0<? extends T> recoveryAttempt) {
1033+
Objects.requireNonNull(exceptionType, "exceptionType is null");
1034+
Objects.requireNonNull(recoveryAttempt, "recoveryAttempt is null");
1035+
return isFailure() && exceptionType.isAssignableFrom(getCause().getClass())
1036+
? of(recoveryAttempt)
1037+
: this;
1038+
}
1039+
9841040
/**
9851041
* Converts this {@code Try} to an {@link Either}.
9861042
*

vavr/src/test/java/io/vavr/control/TryTest.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -949,6 +949,65 @@ public void shouldNotRecoverFailureWhenExceptionTypeIsntAssignable() {
949949
assertThat(Try.of(() -> {throw error;}).recoverWith(Error.class, success()).getCause()).isSameAs(error);
950950
}
951951

952+
// -- recoverAllAndTry
953+
954+
@Test
955+
public void shouldRecoverFailure() {
956+
assertThat(failure()
957+
.recoverAllAndTry(() -> OK))
958+
.isEqualTo(Try.success(OK));
959+
}
960+
961+
@Test
962+
public void shouldNotRecoverSuccess() {
963+
final String initialValue = "INITIAL";
964+
final String attemptValue = "RECOVERY";
965+
assertThat(Try.success(initialValue)
966+
.recoverAllAndTry(() -> attemptValue))
967+
.isEqualTo(Try.success(initialValue));
968+
}
969+
970+
@Test
971+
public void shouldThrowNullPointerExceptionWhenRecoveryAttemptIsNull() {
972+
assertThrows(NullPointerException.class, () -> failure().recoverAllAndTry(null));
973+
}
974+
975+
// -- recoverAndTry
976+
977+
@Test
978+
public void shouldRecoverCorrectTypeOfFailure() {
979+
assertThat(Try.failure(new RuntimeException())
980+
.recoverAndTry(RuntimeException.class, () -> OK))
981+
.isEqualTo(Try.success(OK));
982+
}
983+
984+
@Test
985+
public void shouldNotRecoverIncorrectTypeOfFailure() {
986+
Try<Object> initialFailure = Try.failure(new RuntimeException());
987+
assertThat(initialFailure
988+
.recoverAndTry(IllegalStateException.class, () -> OK))
989+
.isEqualTo(initialFailure);
990+
}
991+
992+
@Test
993+
public void shouldNotRecoverSuccessForRecoverAndTry() {
994+
final String initialValue = "INITIAL";
995+
final String attemptValue = "RECOVERY";
996+
assertThat(Try.success(initialValue)
997+
.recoverAndTry(Throwable.class, () -> attemptValue))
998+
.isEqualTo(Try.success(initialValue));
999+
}
1000+
1001+
@Test
1002+
public void shouldThrowNullPointerExceptionWhenExceptionTypeIsNull() {
1003+
assertThrows(NullPointerException.class, () -> failure().recoverAndTry(null, () -> OK));
1004+
}
1005+
1006+
@Test
1007+
public void shouldThrowNullPointerExceptionWhenRecoveryAttemptIsNullForRecoverAndTry() {
1008+
assertThrows(NullPointerException.class, () -> failure().recoverAndTry(Throwable.class, null));
1009+
}
1010+
9521011
// -- onFailure
9531012

9541013
@Test

0 commit comments

Comments
 (0)