diff --git a/cffu-core/src/main/java/io/foldright/cffu/CompletableFutureUtils.java b/cffu-core/src/main/java/io/foldright/cffu/CompletableFutureUtils.java index a67dc677..ebb816ae 100644 --- a/cffu-core/src/main/java/io/foldright/cffu/CompletableFutureUtils.java +++ b/cffu-core/src/main/java/io/foldright/cffu/CompletableFutureUtils.java @@ -2376,7 +2376,9 @@ public static CompletableFuture thenCombineFastFail( final Object[] result = new Object[css.length]; final CompletableFuture[] resultSetterCfs = createResultSetterCfs(css, result); - return allFastFailOf(resultSetterCfs).thenApply(unused -> fn.apply((T) result[0], (U) result[1])); + CompletableFuture ret = allFastFailOf(resultSetterCfs) + .thenApply(unused -> fn.apply((T) result[0], (U) result[1])); + return thenCompose0(cfThis, ret); } /** @@ -2418,8 +2420,9 @@ public static CompletableFuture thenCombineFastFailAsync( final Object[] result = new Object[css.length]; final CompletableFuture[] resultSetterCfs = createResultSetterCfs(css, result); - return allFastFailOf(resultSetterCfs) + CompletableFuture ret = allFastFailOf(resultSetterCfs) .thenApplyAsync(unused -> fn.apply((T) result[0], (U) result[1]), executor); + return thenCompose0(cfThis, ret); } @SuppressWarnings("unchecked") @@ -2428,6 +2431,19 @@ private static CompletionStage[] requireThisAndOtherNonNull( return new CompletionStage[]{requireNonNull(cfThis, "cfThis is null"), requireNonNull(other, "other is null")}; } + /** + * Returns a new CompletableFuture that its runtime type(including minimal-stage) + * is same as parameter {@code cfType} and its result is same as parameter {@code cfValue}. + * + * Implementation Note: Calling this method is necessary + * because Cffu internal use type CompletableFuture to represent minimal-stage(NOT type safe). + */ + @SuppressWarnings("unchecked") + private static CompletableFuture thenCompose0( + CompletableFuture cfType, CompletionStage cfValue) { + return cfType.thenCompose(v -> (CompletionStage) cfValue); + } + /** * Returns a new CompletableFuture that, when tow given stage both complete normally, * is executed with the two results as arguments to the supplied action. @@ -2448,7 +2464,9 @@ public static CompletableFuture thenAcceptBothFastFail( final Object[] result = new Object[css.length]; final CompletableFuture[] resultSetterCfs = createResultSetterCfs(css, result); - return allFastFailOf(resultSetterCfs).thenRun(() -> action.accept((T) result[0], (U) result[1])); + CompletableFuture ret = allFastFailOf(resultSetterCfs) + .thenRun(() -> action.accept((T) result[0], (U) result[1])); + return thenCompose0(cfThis, ret); } /** @@ -2490,7 +2508,9 @@ public static CompletableFuture thenAcceptBothFastFailAsync( final Object[] result = new Object[css.length]; final CompletableFuture[] resultSetterCfs = createResultSetterCfs(css, result); - return allFastFailOf(resultSetterCfs).thenRunAsync(() -> action.accept((T) result[0], (U) result[1]), executor); + CompletableFuture ret = allFastFailOf(resultSetterCfs) + .thenRunAsync(() -> action.accept((T) result[0], (U) result[1]), executor); + return thenCompose0(cfThis, ret); } /** @@ -2507,7 +2527,8 @@ public static CompletableFuture runAfterBothFastFail( final CompletionStage[] css = requireThisAndOtherNonNull(cfThis, other); requireNonNull(action, "action is null"); - return allFastFailOf(css).thenRun(action); + CompletableFuture ret = allFastFailOf(css).thenRun(action); + return thenCompose0(cfThis, ret); } /** @@ -2541,7 +2562,8 @@ public static CompletableFuture runAfterBothFastFailAsync( requireNonNull(action, "action is null"); requireNonNull(executor, "executor is null"); - return allFastFailOf(css).thenRunAsync(action, executor); + CompletableFuture ret = allFastFailOf(css).thenRunAsync(action, executor); + return thenCompose0(cfThis, ret); } // endregion @@ -2566,7 +2588,8 @@ public static CompletableFuture applyToEitherSuccess( final CompletionStage[] css = requireThisAndOtherNonNull(cfThis, other); requireNonNull(fn, "fn is null"); - return anySuccessOf(css).thenApply(fn); + CompletableFuture ret = anySuccessOf(css).thenApply(fn); + return thenCompose0(cfThis, ret); } /** @@ -2599,7 +2622,8 @@ public static CompletableFuture applyToEitherSuccessAsync( requireNonNull(fn, "fn is null"); requireNonNull(executor, "executor is null"); - return anySuccessOf(css).thenApplyAsync(fn, executor); + CompletableFuture ret = anySuccessOf(css).thenApplyAsync(fn, executor); + return thenCompose0(cfThis, ret); } /** @@ -2614,7 +2638,8 @@ public static CompletableFuture acceptEitherSuccess( final CompletionStage[] css = requireThisAndOtherNonNull(cfThis, other); requireNonNull(action, "action is null"); - return anySuccessOf(css).thenAccept(action); + CompletableFuture ret = anySuccessOf(css).thenAccept(action); + return thenCompose0(cfThis, ret); } /** @@ -2645,7 +2670,8 @@ public static CompletableFuture acceptEitherSuccessAsync( requireNonNull(action, "action is null"); requireNonNull(executor, "executor is null"); - return anySuccessOf(css).thenAcceptAsync(action, executor); + CompletableFuture ret = anySuccessOf(css).thenAcceptAsync(action, executor); + return thenCompose0(cfThis, ret); } /** @@ -2662,7 +2688,8 @@ public static CompletableFuture runAfterEitherSuccess( final CompletionStage[] css = requireThisAndOtherNonNull(cfThis, other); requireNonNull(action, "action is null"); - return anySuccessOf(css).thenRun(action); + CompletableFuture ret = anySuccessOf(css).thenRun(action); + return thenCompose0(cfThis, ret); } /** @@ -2696,7 +2723,8 @@ public static CompletableFuture runAfterEitherSuccessAsync( requireNonNull(action, "action is null"); requireNonNull(executor, "executor is null"); - return anySuccessOf(css).thenRunAsync(action, executor); + CompletableFuture ret = anySuccessOf(css).thenRunAsync(action, executor); + return thenCompose0(cfThis, ret); } // endregion