public static <IN> CompletableFuture<IN> whenCompleteAsyncIfNotDone(
		CompletableFuture<IN> completableFuture,
		Executor executor,
		BiConsumer<? super IN, ? super Throwable> whenCompleteFun) {
		return completableFuture.isDone() ?
			completableFuture.whenComplete(whenCompleteFun) :
			completableFuture.whenCompleteAsync(whenCompleteFun, executor);
	}
public static < IN > CompletableFuture < IN > whenCompleteAsyncIfNotDone ( CompletableFuture < IN > completableFuture , Executor executor , BiConsumer < ? super IN , ? super Throwable > whenCompleteFun ) { return completableFuture . isDone ( ) ? completableFuture . whenComplete ( whenCompleteFun ) : completableFuture . whenCompleteAsync ( whenCompleteFun , executor ) ; }
This function takes a {@link CompletableFuture} and a bi-consumer to call on completion of this future. If the
input future is already done, this function returns {@link CompletableFuture#whenComplete(BiConsumer)}.
Otherwise, the return value is {@link CompletableFuture#whenCompleteAsync(BiConsumer, Executor)} with the given
executor.

@param completableFuture the completable future for which we want to call #whenComplete.
@param executor the executor to run the whenComplete function if the future is not yet done.
@param whenCompleteFun the bi-consumer function to call when the future is completed.
@param <IN> type of the input future.
@return the new completion stage.