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

io.vertx.up.unity.Complex Maven / Gradle / Ivy

There is a newer version: 0.9.0
Show newest version
package io.vertx.up.unity;

import io.vertx.core.Future;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.up.atom.Refer;
import io.vertx.up.atom.query.Pagination;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

class Complex {
    /**
     * This function executed on input reference
     * 1) If predicate = true, return executor(T) -> Future
     * 2) If predicate = false, return Future
     * return T in other situations.
     *
     * @param input     input T reference
     * @param predicate Check whether the T reference is ok for `executor`
     * @param executor  The continue executor on T
     * @param        The entity object, now it support JsonObject/JsonArray
     *
     * @return Future for result
     */
    static  Future complex(final T input, final Predicate predicate, final Supplier> executor) {
        if (Objects.isNull(input)) {
            return To.future(null);
        } else {
            if (Objects.isNull(executor)) {
                return To.future(input);
            } else {
                if (Objects.isNull(predicate)) {
                    return executor.get();
                } else {
                    if (predicate.test(input)) {
                        return executor.get();
                    } else {
                        return To.future(input);
                    }
                }
            }
        }
    }

    /**
     * The workflow for current function
     * 1 - Pagination `first` will be consumed by `pageConsumer` first,
     * 2 - Get the first response by `responseBuilder` function to get first result.
     * 3 - Generate `total` by `totalConsumer` function to get the total records number.
     * 4 - Based on Pagination ( include total ), generate Set pagination.
     * 5 - Each group call `pageConsumer` again ( exclude first )
     * 6 - Get List result, call fnReduce to generate new R
     *
     * @param first           The pagination object ( Pager + total )
     * @param totalConsumer   The total consumer that consume the response of 1st to generate `Pagination`
     * @param pageConsumer    The default consumer for Pagination to get `Pagination`
     * @param responseBuilder The builder for result building
     * @param fnReduce        The combine function to calculate R + R -> R such as List.addAll(list)
     * @param              The response of `pageConsumer`
     * @param              The final result of `responseBuilder`
     *
     * @return Final result for batch
     */
    static  Future complex(final Pagination first,
                                    final Function> totalConsumer,
                                    final Function> pageConsumer,
                                    final Function> responseBuilder,
                                    final BinaryOperator fnReduce) {
        /*
         * First response to get based on `pageConsumer`
         */
        final Refer firstResult = new Refer();
        return pageConsumer.apply(first)
            /*
             * Get response R,
             */
            .compose(response -> responseBuilder.apply(response)
                .compose(firstResult::future)
                .compose(nil -> totalConsumer.apply(response))
                .compose(total -> {
                    first.setTotal(total);
                    return Ux.future(first);
                })
            )
            .compose(Pagination::scatterAsync)
            .compose(pageSet -> {
                if (pageSet.isEmpty()) {
                    /*
                     * No more page
                     */
                    return Ux.future(firstResult.get());
                } else {
                    final List> futures = new ArrayList<>();
                    pageSet.stream()
                        .map(each -> pageConsumer.apply(each).compose(responseBuilder))
                        .forEach(futures::add);
                    return Ux.thenCombineT(futures).compose(list -> {
                        final R result = list.stream().reduce(fnReduce).orElse(null);
                        final R firstRef = firstResult.get();
                        return Ux.future(fnReduce.apply(firstRef, result));
                    });
                }
            })
            .otherwise(Ux.otherwise(() -> null));
    }

    static Function> complex(final Function> total, final Function> page, final Function> result) {
        return first -> Complex.complex(first, total, page, result, JsonArray::addAll);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy