Add thenWith(Function)
This commit is contained in:
parent
fb6b65e6de
commit
f6eb27450f
6 changed files with 137 additions and 3 deletions
|
@ -5,6 +5,7 @@ CHANGELOG
|
||||||
------
|
------
|
||||||
|
|
||||||
* Add `andThen(Function)`
|
* Add `andThen(Function)`
|
||||||
|
* Add `thenWith(Function)`
|
||||||
|
|
||||||
0.9.0
|
0.9.0
|
||||||
-----
|
-----
|
||||||
|
|
|
@ -96,6 +96,11 @@ class Err<T> implements Result<T> {
|
||||||
return Result.error(error);
|
return Result.error(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Result<T> thenWith(final Function<T, WithResultContinuation<T>> f) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(final Object other) {
|
public boolean equals(final Object other) {
|
||||||
return other instanceof Err && Objects.equals(error, ((Err) other).error);
|
return other instanceof Err && Objects.equals(error, ((Err) other).error);
|
||||||
|
|
|
@ -202,7 +202,6 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
||||||
*
|
*
|
||||||
* <p>Combination of {@link #flatMap(Function)} and {@link #of(Callable)}.</p>
|
* <p>Combination of {@link #flatMap(Function)} and {@link #of(Callable)}.</p>
|
||||||
*
|
*
|
||||||
* <p>Syntax is:</p>
|
|
||||||
* <pre><code>
|
* <pre><code>
|
||||||
* Integer doSomething() {...}
|
* Integer doSomething() {...}
|
||||||
* String doSomethingElse(final Integer value) {...}
|
* String doSomethingElse(final Integer value) {...}
|
||||||
|
@ -212,9 +211,29 @@ public interface Result<T> extends Functor<T, Result<?>> {
|
||||||
*
|
*
|
||||||
* <p>When the Result is an Err, then the original error is carried over and the Callable is never called.</p>
|
* <p>When the Result is an Err, then the original error is carried over and the Callable is never called.</p>
|
||||||
*
|
*
|
||||||
* @param f the function to map the Success value to the Callable
|
* @param f the function to map the Success value into the Callable
|
||||||
* @param <R> the type of the final Result
|
* @param <R> the type of the final Result
|
||||||
* @return a new Result
|
* @return a new Result
|
||||||
*/
|
*/
|
||||||
<R> Result<R> andThen(Function<T, Callable<R>> f);
|
<R> Result<R> andThen(Function<T, Callable<R>> f);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform the continuation with the current Result value then return the current Result, assuming there was no
|
||||||
|
* error in the continuation.
|
||||||
|
*
|
||||||
|
* <pre><code>
|
||||||
|
* Integer doSomething() {...}
|
||||||
|
* void doSomethingElse(final Integer value) {...}
|
||||||
|
* Result<Integer> r = Result.of(() -> doSomething())
|
||||||
|
* .thenWith(value -> () -> doSomethingElse(value));
|
||||||
|
* </code></pre>
|
||||||
|
*
|
||||||
|
* <p>Where the Result is an Err, then the Result is returned immediately and the continuation is ignored.</p>
|
||||||
|
* <p>Where the Result is a Success, then if an exception is thrown by the continuation the Result returned will be
|
||||||
|
* a new error Result containing that exception, otherwise the original Result will be returned.</p>
|
||||||
|
*
|
||||||
|
* @param f the function to map the Success value into the result continuation
|
||||||
|
* @return the Result or a new error Result
|
||||||
|
*/
|
||||||
|
Result<T> thenWith(Function<T, WithResultContinuation<T>> f);
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,6 +100,11 @@ class Success<T> implements Result<T> {
|
||||||
return Result.of(f.apply(value));
|
return Result.of(f.apply(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Result<T> thenWith(final Function<T, WithResultContinuation<T>> f) {
|
||||||
|
return f.apply(value).call(this);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(final Object other) {
|
public boolean equals(final Object other) {
|
||||||
return other instanceof Success && Objects.equals(value, ((Success) other).value);
|
return other instanceof Success && Objects.equals(value, ((Success) other).value);
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
/**
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017 Paul Campbell
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||||
|
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||||
|
* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all copies
|
||||||
|
* or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.kemitix.mon.result;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Callable-like interface for performing an action with a Result that, if there are no errors is returned as-is, but
|
||||||
|
* if there is an error then a new error Result is returned.
|
||||||
|
*
|
||||||
|
* @param <T> the type of the current Result value
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface WithResultContinuation<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to make use of the Result value.
|
||||||
|
*
|
||||||
|
* @throws Exception to replace the current Result with an error
|
||||||
|
*/
|
||||||
|
void run() throws Exception;
|
||||||
|
|
||||||
|
@SuppressWarnings({"illegalcatch", "javadocmethod"})
|
||||||
|
default Result<T> call(final Result<T> currentResult) {
|
||||||
|
try {
|
||||||
|
run();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
return Result.error(e);
|
||||||
|
}
|
||||||
|
return currentResult;
|
||||||
|
}
|
||||||
|
}
|
|
@ -540,7 +540,7 @@ public class ResultTest implements WithAssertions {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void error_andThenError_thenError() {
|
public void error_andThenError_thenOriginalError() {
|
||||||
//given
|
//given
|
||||||
final RuntimeException exception1 = new RuntimeException();
|
final RuntimeException exception1 = new RuntimeException();
|
||||||
final Result<Object> error = Result.error(exception1);
|
final Result<Object> error = Result.error(exception1);
|
||||||
|
@ -553,6 +553,61 @@ public class ResultTest implements WithAssertions {
|
||||||
result.onError(e -> assertThat(e).isSameAs(exception1));
|
result.onError(e -> assertThat(e).isSameAs(exception1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void success_whenThenWith_whenOkay_thenSuccess() {
|
||||||
|
//given
|
||||||
|
final Result<Integer> ok = Result.ok(1);
|
||||||
|
//when
|
||||||
|
final Result<Integer> result = ok.thenWith(v -> () -> {
|
||||||
|
// do something with v
|
||||||
|
});
|
||||||
|
//then
|
||||||
|
assertThat(result.isOkay()).isTrue();
|
||||||
|
result.peek(v -> assertThat(v).isEqualTo(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void success_whenThenWith_whenError_thenError() {
|
||||||
|
//given
|
||||||
|
final Result<Integer> ok = Result.ok(1);
|
||||||
|
final RuntimeException exception = new RuntimeException();
|
||||||
|
//when
|
||||||
|
final Result<Integer> result = ok.thenWith(v -> () -> {
|
||||||
|
throw exception;
|
||||||
|
});
|
||||||
|
//then
|
||||||
|
assertThat(result.isError()).isTrue();
|
||||||
|
result.onError(e -> assertThat(e).isSameAs(exception));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void error_whenThenWith_whenOkay_thenError() {
|
||||||
|
//given
|
||||||
|
final RuntimeException exception = new RuntimeException();
|
||||||
|
final Result<Integer> error = Result.error(exception);
|
||||||
|
//when
|
||||||
|
final Result<Integer> result = error.thenWith(v -> () -> {
|
||||||
|
// do something with v
|
||||||
|
});
|
||||||
|
//then
|
||||||
|
assertThat(result.isError()).isTrue();
|
||||||
|
result.onError(e -> assertThat(e).isSameAs(exception));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void error_whenThenWith_whenError_thenOriginalError() {
|
||||||
|
//given
|
||||||
|
final RuntimeException exception = new RuntimeException();
|
||||||
|
final Result<Integer> error = Result.error(exception);
|
||||||
|
//when
|
||||||
|
final Result<Integer> result = error.thenWith(v -> () -> {
|
||||||
|
throw new RuntimeException();
|
||||||
|
});
|
||||||
|
//then
|
||||||
|
assertThat(result.isError()).isTrue();
|
||||||
|
result.onError(e -> assertThat(e).isSameAs(exception));
|
||||||
|
}
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
private static class UseCase {
|
private static class UseCase {
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue