WaitResultBuilder5.java
/**
* Powerunit - A JDK1.8 test framework
* Copyright (C) 2014 Mathieu Boretti.
*
* This file is part of Powerunit
*
* Powerunit is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Powerunit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Powerunit. If not, see <http://www.gnu.org/licenses/>.
*/
package ch.powerunit.extensions.async.lang;
import static java.util.concurrent.CompletableFuture.supplyAsync;
import static java.util.concurrent.ForkJoinPool.commonPool;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.ForkJoinPool;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
/**
* Almost final Step of the builder of {@link CompletableFuture} to define the
* executor it self.
*
* @param <T>
* The type of result of the {@link CompletableFuture}
*
*/
public interface WaitResultBuilder5<T> extends Supplier<Optional<T>> {
/**
* Directly wait for the result of this execution (the execution is run in this
* thread). In case of not ignored exception, an {@link AssertionError} is
* thrown.
* <p>
*
* For example :
*
* <pre>
* WaitResult.of(myCallable).dontIgnoreException().expecting(myPredicate).repeat(2)
* .every(1000, TimeUnit.MILLISECONDS).get()
* </pre>
* <ul>
* <li>If an exception occurs in {@code myCallable}, an {@link AssertionError}
* is thrown</li>
* <li>If no result is available, after the 2 try, an empty {@link Optional} is
* returned.</li>
* <li>Or the result is available in the returned {@link Optional}.</li>
* </ul>
*
* @return the {@link Optional} with the result of the execution
*
* @throws AssertionError
* In case of not ignored exception.
*/
@Override
Optional<T> get();
/**
* Register an action to be done when the retrieval is finish (in success or
* not).
* <p>
* This may be used, for example, to release resources. This method may be used
* several times. In this case, all the registered action will be executed on
* Finish, starting by the first one.
*
* @param action
* the action to be done. May be null (ignored).
* @return a new instance of {@link WaitResultBuilder5} with this new action to
* be done at the end.
* @since 1.1.0
*/
default WaitResultBuilder5<T> onFinish(Runnable action) {
if (action == null) {
return this;
}
return () -> {
try {
return get();
} finally {
action.run();
}
};
}
/**
* Define the executor to be used for the async part.
* <p>
* Both the action to retry and the control on the result will be executed on
* the thread provided by the executor.
*
* @param executor
* the executor to be used. This can't be null.
* @return {@link WaitResultBuilder6 the final step}
*/
default WaitResultBuilder6<T> using(Executor executor) {
return () -> supplyAsync(this, executor);
}
/**
* Define the executor to be used for the async part as using
* {@link ForkJoinPool#commonPool()}.
* <p>
* Both the action to retry and the control on the result will be executed on
* the thread provided by the executor.
*
* @return {@link WaitResultBuilder6 the final step}
* @see ForkJoinPool#commonPool()
*/
default WaitResultBuilder6<T> usingDefaultExecutor() {
return using(commonPool());
}
/**
* Create and start the async execution of the {@link CompletableFuture}.
*
* @param executor
* the executor to be used.
* @return the {@link CompletableFuture}
* @deprecated Replaced by {@code using(executor).asyncExec()}
*/
@Deprecated
default CompletableFuture<Optional<T>> asyncExec(Executor executor) {
return using(executor).asyncExec();
}
/**
* Create and start the async execution of the {@link CompletableFuture} using
* {@link ForkJoinPool#commonPool()}.
*
* @return the {@link CompletableFuture}
* @see #usingDefaultExecutor()
* @see WaitResultBuilder6#asyncExec()
*/
default CompletableFuture<Optional<T>> asyncExec() {
return usingDefaultExecutor().asyncExec();
}
/**
* Directly wait for the result of this execution. In case of not ignored
* exception, an {@link AssertionError} is thrown.
*
* @param executor
* the executor to be used.
*
* @return the {@link Optional} with the result of the execution
*
* @throws AssertionError
* In case of not ignored exception.
* @deprecated Replaced by {@code using(executor).finish()}
*/
@Deprecated
default Optional<T> finish(Executor executor) {
return using(executor).finish();
}
/**
* Directly wait for the result of this execution using
* {@link ForkJoinPool#commonPool()}. In case of not ignored exception, an
* {@link AssertionError} is thrown.
*
* @return the {@link Optional} with the result of the execution
*
* @throws AssertionError
* In case of not ignored exception.
* @see #usingDefaultExecutor()
* @see WaitResultBuilder6#finish()
*/
default Optional<T> finish() {
return usingDefaultExecutor().finish();
}
/**
* Directly wait for a positive result of this execution. In case of not ignored
* exception, or when no result are available, an {@link AssertionError} is
* thrown.
*
* @param executor
* the executor to be used.
*
* @return the value if available
*
* @throws AssertionError
* In case of not ignored exception or missing result.
* @deprecated Replaced by {@code using(executor).finishWithAResult()}
*/
@Deprecated
default T finishWithAResult(Executor executor) {
return using(executor).finishWithAResult();
}
/**
* Directly wait for a positive result of this execution using
* {@link ForkJoinPool#commonPool()}. In case of not ignored exception, or when
* no result are available, an {@link AssertionError} is thrown.
*
* @return the value if available
*
* @throws AssertionError
* In case of not ignored exception or missing result.
* @see #usingDefaultExecutor()
* @see WaitResultBuilder6#finishWithAResult()
*/
default T finishWithAResult() {
return usingDefaultExecutor().finishWithAResult();
}
/**
* Add a mapper fonction, on the result, if applicable. This mapper is executed
* in the target thread.
*
* @param mapper
* the function to convert the result.
* @param <U>
* the target of the mapper.
* @return the {@link WaitResultBuilder5} continuation of the builder
* @see Optional#map(Function)
* @since 1.0.0
*/
default <U> WaitResultBuilder5<U> map(Function<T, U> mapper) {
return () -> get().map(mapper);
}
/**
* Add a flat mapper fonction, on the result, if applicable. This mapper is
* executed in the target thread.
*
* @param mapper
* the function to convert the result.
* @param <U>
* the target of the mapper.
* @return the {@link WaitResultBuilder5} continuation of the builder
* @see Optional#flatMap(Function)
* @since 1.1.0
*/
default <U> WaitResultBuilder5<U> flatMap(Function<T, Optional<U>> mapper) {
return () -> get().flatMap(mapper);
}
/**
* Add a or operation, on the result, if applicable. This or is executed in the
* target thread.
* <p>
* <b>Only available on java 9</b>
*
* @param supplier
* the function to convert the result
* @return the {@link WaitResultBuilder5} continuation of the builder
* @see Optional#or(Supplier)
* @since 1.1.0
*/
default WaitResultBuilder5<T> or(Supplier<? extends Optional<? extends T>> supplier) {
throw new UnsupportedOperationException("Not available on java 8");
}
/**
* Add a filter predicate, on the result, if applicable. This filter is executed
* in the target thread.
*
* @param filter
* the filter
* @return the {@link WaitResultBuilder5} continuation of the builder
* @see Optional#filter(Predicate)
* @since 1.0.0
*/
default WaitResultBuilder5<T> filter(Predicate<T> filter) {
return () -> get().filter(filter);
}
}