io.vertx.up.unity.Complex Maven / Gradle / Ivy
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