All Downloads are FREE. Search and download functionalities are using the official Maven repository.

me.hltj.vertx.future.CompositeFutureTuple2 Maven / Gradle / Ivy

There is a newer version: 1.1.2
Show newest version
/*
 * vertx-future-utils - Convenient Utilities for Vert.x Future
 * https://github.com/hltj/vertx-future-utils
 *
 * Copyright (C) 2020  JiaYanwei  https://hltj.me
 *
 * This code is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This code 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see .
 *
 * Please contact me (jiaywe#at#gmail.com, replace the '#at#' with 'at')
 * if you need additional information or have any questions.
 */
package me.hltj.vertx.future;

import io.vertx.core.CompositeFuture;
import io.vertx.core.Future;
import lombok.ToString;
import me.hltj.vertx.function.Consumer3;
import me.hltj.vertx.function.Function3;

import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Supplier;

import static me.hltj.vertx.FutureUtils.joinWrap;

/**
 * The composite {@link Future} tuple warps a {@link CompositeFuture} and a {@link FutureTuple2}.
 * 

* Not only retains the type parameters of the original {@code Future}s, * but also provide many convenient operations as a complement to {@code CompositeFuture}. * * @param the type parameter of the 1st {@code Future} * @param the type parameter of the 2nd {@code Future} */ @ToString(includeFieldNames = false) final public class CompositeFutureTuple2 extends CompositeFutureWrapper { private final FutureTuple2 tuple2; private CompositeFutureTuple2(CompositeFuture composite, FutureTuple2 tuple2) { super(composite); this.tuple2 = tuple2; } /** * Create a {@link CompositeFutureTuple2} based on a {@link CompositeFuture} and a {@link FutureTuple2}. * * @param the type parameter of the 1st {@code Future} * @param the type parameter of the 2nd {@code Future} * @param tuple2 the {@code FutureTuple2} * @param compose the {@code CompositeFuture} * @return the {@code CompositeFutureTuple2} */ public static CompositeFutureTuple2 of(FutureTuple2 tuple2, CompositeFuture compose) { return new CompositeFutureTuple2<>(compose, tuple2); } /** * Return the original {@link FutureTuple2}. */ public FutureTuple2 tuple() { return tuple2; } /** * Run side-effect code likes {@link CompositeFutureWrapper#use(Consumer)}, but the {@code consumer3} takes the * original two {@link Future}s as additional parameters. *

* Likes {@link CompositeFutureWrapper#use(Consumer)}, a useful scenario is to capture the original * two {@code Future}s in the functions that passed as parameters of {@code CompositeFuture}'s methods. e.g. : *

     *     Future<Double> future0 = Future.succeededFuture(1.0);
     *     Future<Integer> future1 = Future.failedFuture("error");
     *     FutureUtils.join(future0, future1).use((composite, fut0, fut1) ->
     *             composite.onComplete(_ar ->
     *                     System.out.println(String.format("original futures: (%s, %s)", fut0, fut1))
     *             )
     *     );
     * 
* * @param consumer3 the side-effect code that takes the {@code CompositeFuture} and the original * two {@code Future}s as parameters */ public void use(Consumer3, Future> consumer3) { consumer3.accept(composite, tuple2.get_0(), tuple2.get_1()); } /** * Map the original {@link CompositeFuture} and the original two {@link Future}s. *

* Likes {@link CompositeFutureTuple2#use(Consumer3)} but return a {@code Future}, a useful scenario is to capture * the original two {@code Future}s in the functions that passed as parameters of {@code CompositeFuture}'s * methods. e.g. : * *

     *     Future<Double> future0 = Future.succeededFuture(1.0);
     *     Future<Integer> future1 = Future.failedFuture("error");
     *     Future<String> strFuture = FutureUtils.tuple(future0, future1)
     *             .otherwiseEmpty()
     *             .join()
     *             .with((composite, fut0, fut1) ->
     *                     composite.map(_x -> String.format("original futures: (%s, %s)", fut0, fut1))
     *             );
     * 
* * @param function3 the function to map * @param the result type of the {@code function3} * @return the result of {@code function3} application */ public R with(Function3, Future, R> function3) { return function3.apply(composite, tuple2.get_0(), tuple2.get_1()); } /** * Alias for {@link #through(BiFunction)}. */ public Future mapAnyway(BiFunction, Future, R> function2) { return through(function2); } /** * Map a function that takes the original two {@link Future}s on complete no matter whether succeeded or failed. * * @param function2 the function to map on complete * @param the result type of the {@code function2} * @return the result {@code Future} */ public Future through(BiFunction, Future, R> function2) { return joinThrough(function2.andThen(Future::succeededFuture)); } /** * Alias for {@link #joinThrough(BiFunction)}. */ public Future flatMapAnyway(BiFunction, Future, Future> function2) { return joinThrough(function2); } /** * Map a function that takes the original two {@link Future}s on complete no matter whether succeeded or failed, * and join (also known as {@code flatten}) the result before return. * * @param function2 the function to map on complete * @param the type parameter of the result type of the {@code function} * @return the result {@code Future} */ public Future joinThrough(BiFunction, Future, Future> function2) { Supplier> supplier = () -> function2.apply(tuple2.get_0(), tuple2.get_1()); return composite.compose(_x -> joinWrap(supplier), _t -> joinWrap(supplier)); } /** * Alias for {@link CompositeFutureTuple2#applift(BiFunction)}. */ public Future mapTyped(BiFunction function2) { return applift(function2); } /** * Apply a function that accept both results of the original {@link Future}s on success, and return * a {@link Future}. *

* It likes lifting the function and then applying it to the original {@code Future}s, this is also the origin of * the name. *

* When the composite future fails, the failure will be propagated to the returned future and the function will not * be called. *

* When the composite future succeeds, the function will be called. If the function throws a non-checked exception, * the returned future will be failed with this exception. Otherwise, the returned future will be a future succeed * with the function return value. * * @param function2 the function * @param the result type of {@code function2} * @return the result {@code Future} */ public Future applift(BiFunction function2) { return composite.map(future -> function2.apply(composite.resultAt(0), composite.resultAt(1))); } /** * Alias for {@link CompositeFutureTuple2#joinApplift(BiFunction)}. */ public Future flatMapTyped(BiFunction> function2) { return joinApplift(function2); } /** * Apply a function that accept both results of the original {@link Future}s on success, and return * a {@link Future}, where the function itself return a {@link Future}. *

* It likes lifting the function and then applying it to the original {@code Future}s, and joining (also known * as {@code flatten}ing) the nested result {@code Future}s before return, this is also the origin of the name. *

* When the composite future fails, the failure will be propagated to the returned future and the function will not * be called. *

* When the composite future succeeds, the function will be called. If the function throws a non-checked exception, * the returned future will be failed with this exception. Otherwise, the returned future will be the function * returned future. * * @param function2 the function * @param the result type of {@code function2} * @return the result {@code Future} */ public Future joinApplift(BiFunction> function2) { return composite.flatMap(future -> function2.apply(composite.resultAt(0), composite.resultAt(1))); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy