Add Result.recover(Function) and Result.onError(Consumer)
This commit is contained in:
parent
c5247d7c14
commit
28564a2129
4 changed files with 89 additions and 2 deletions
|
@ -80,6 +80,16 @@ class Err<T> implements Result<T> {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<T> recover(final Function<Throwable, Result<T>> f) {
|
||||
return f.apply(error);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(final Consumer<Throwable> errorConsumer) {
|
||||
errorConsumer.accept(error);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object other) {
|
||||
return other instanceof Err && Objects.equals(error, ((Err) other).error);
|
||||
|
|
|
@ -108,6 +108,7 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
|||
|
||||
/**
|
||||
* Swaps the inner Result of a Maybe, so that a Result is on the outside.
|
||||
*
|
||||
* @param maybeResult the Maybe the contains a Result
|
||||
* @param <T> the type of the value that may be in the Result
|
||||
* @return a Result containing a Maybe, the value in the Maybe was the value in a successful Result within the
|
||||
|
@ -177,4 +178,22 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
|||
* @return this Result
|
||||
*/
|
||||
Result<T> peek(Consumer<T> consumer);
|
||||
|
||||
/**
|
||||
* Provide a way to attempt to recover from an error state.
|
||||
*
|
||||
* @param f the function to recover from the error
|
||||
* @return a new Result, either a Success, or if recovery is not possible an other Err.
|
||||
*/
|
||||
Result<T> recover(Function<Throwable, Result<T>> f);
|
||||
|
||||
/**
|
||||
* A handler for error states.
|
||||
*
|
||||
* <p>When this is an error then tne Consumer will be supplier with the error. When this is a success, then nothing
|
||||
* happens.</p>
|
||||
*
|
||||
* @param errorConsumer the consumer to handle the error
|
||||
*/
|
||||
void onError(Consumer<Throwable> errorConsumer);
|
||||
}
|
||||
|
|
|
@ -84,6 +84,16 @@ class Success<T> implements Result<T> {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<T> recover(final Function<Throwable, Result<T>> f) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(final Consumer<Throwable> errorConsumer) {
|
||||
// do nothing - this is not an error
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object other) {
|
||||
return other instanceof Success && Objects.equals(value, ((Success) other).value);
|
||||
|
|
|
@ -452,6 +452,54 @@ public class ResultTest implements WithAssertions {
|
|||
assertThat(peeked).isSameAs(result);
|
||||
}
|
||||
|
||||
@Test public void success_whenOnError_thenIgnore() {
|
||||
//given
|
||||
final Result<Integer> ok = Result.ok(1);
|
||||
//when
|
||||
ok.onError(e -> fail("not an error"));
|
||||
}
|
||||
|
||||
@Test public void error_whenOnError_thenConsume() {
|
||||
//given
|
||||
final RuntimeException exception = new RuntimeException();
|
||||
final Result<Integer> error = Result.error(exception);
|
||||
final AtomicReference<Throwable> capture = new AtomicReference<>();
|
||||
//when
|
||||
error.onError(capture::set);
|
||||
//then
|
||||
assertThat(capture).hasValue(exception);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void success_whenRecover_thenNoChange() {
|
||||
//given
|
||||
final Result<Integer> ok = Result.ok(1);
|
||||
//when
|
||||
final Result<Integer> recovered = ok.recover(e -> Result.ok(2));
|
||||
//then
|
||||
recovered.peek(v -> assertThat(v).isEqualTo(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void error_whenRecover_thenSuccess() {
|
||||
//given
|
||||
final Result<Integer> error = Result.error(new RuntimeException());
|
||||
//when
|
||||
final Result<Integer> recovered = error.recover(e -> Result.ok(2));
|
||||
//then
|
||||
recovered.peek(v -> assertThat(v).isEqualTo(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void error_whenRecoverFails_thenUpdatedError() {
|
||||
//given
|
||||
final Result<Integer> error = Result.error(new RuntimeException("original"));
|
||||
//when
|
||||
final Result<Integer> recovered = error.recover(e -> Result.error(new RuntimeException("updated")));
|
||||
//then
|
||||
recovered.onError(e -> assertThat(e).hasMessage("updated"));
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
private static class UseCase {
|
||||
|
||||
|
|
Loading…
Reference in a new issue