/*
* Copyright 2013-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.cloudfoundry.util;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.Optional;
import java.util.function.Function;
/**
* A utility class to provide functions for handling {@link org.cloudfoundry.client.v2.PaginatedResponse}s and those containing lists of {@link org.cloudfoundry.client.v2.Resource}s.
*/
public final class PaginationUtils {
private PaginationUtils() {
}
/**
* Generate the stream of resources accumulated from a series of responses obtained from the page supplier.
*
* @param pageSupplier a function from integers to {@link Mono}s of {@link org.cloudfoundry.client.v2.PaginatedResponse}s.
* @param <T> the type of resource in the list on each {@link org.cloudfoundry.client.v2.PaginatedResponse}.
* @param <U> the type of {@link org.cloudfoundry.client.v2.PaginatedResponse}.
* @return a stream of <code>T</code> objects.
*/
public static <T extends org.cloudfoundry.client.v2.Resource<?>, U extends org.cloudfoundry.client.v2.PaginatedResponse<T>> Flux<T> requestClientV2Resources(
Function<Integer, Mono<U>> pageSupplier) {
return pageSupplier
.apply(1)
.flatMapMany(requestClientV2AdditionalPages(pageSupplier))
.flatMap(ResourceUtils::getResources);
}
/**
* Generate the stream of resources accumulated from a series of responses obtained from the page supplier.
*
* @param pageSupplier a function from integers to {@link Mono}s of {@link org.cloudfoundry.client.v3.PaginatedResponse}s.
* @param <T> the type of resource in the list on each {@link org.cloudfoundry.client.v3.PaginatedResponse}.
* @param <U> the type of {@link org.cloudfoundry.client.v3.PaginatedResponse}.
* @return a stream of <code>T</code> objects.
*/
@SuppressWarnings("rawtypes")
public static <T, U extends org.cloudfoundry.client.v3.PaginatedResponse<T>> Flux<T> requestClientV3Resources(Function<Integer, Mono<U>> pageSupplier) {
return pageSupplier
.apply(1)
.flatMapMany(requestClientV3AdditionalPages(pageSupplier))
.flatMapIterable(org.cloudfoundry.client.v3.PaginatedResponse::getResources);
}
/**
* Generate the stream of resources accumulated from a series of responses obtained from the page supplier.
*
* @param pageSupplier a function from integers to {@link Mono}s of {@link org.cloudfoundry.uaa.PaginatedResponse}s.
* @param <T> the type of resource in the list on each {@link org.cloudfoundry.uaa.PaginatedResponse}.
* @param <U> the type of {@link org.cloudfoundry.uaa.PaginatedResponse}.
* @return a stream of <code>T</code> objects.
*/
@SuppressWarnings("rawtypes")
public static <T, U extends org.cloudfoundry.uaa.PaginatedResponse<T>> Flux<T> requestUaaResources(Function<Integer, Mono<U>> pageSupplier) {
return pageSupplier
.apply(1)
.flatMapMany(requestUaaAdditionalPages(pageSupplier))
.flatMapIterable(org.cloudfoundry.uaa.PaginatedResponse::getResources);
}
private static <T> Function<T, Flux<T>> requestAdditionalPages(Function<Integer, Mono<T>> pageSupplier, Function<T, Integer> totalPagesSupplier) {
return response -> {
Integer totalPages = Optional.ofNullable(totalPagesSupplier.apply(response)).orElse(1);
return Flux
.range(2, totalPages - 1)
.flatMap(pageSupplier)
.startWith(response)
.buffer()
.flatMapIterable(d -> d);
};
}
private static <T extends org.cloudfoundry.client.v2.PaginatedResponse<?>> Function<T, Flux<T>> requestClientV2AdditionalPages(Function<Integer, Mono<T>> pageSupplier) {
return requestAdditionalPages(pageSupplier, response -> response.getTotalPages());
}
private static <T extends org.cloudfoundry.client.v3.PaginatedResponse<?>> Function<T, Flux<T>> requestClientV3AdditionalPages(Function<Integer, Mono<T>> pageSupplier) {
return requestAdditionalPages(pageSupplier, response -> response.getPagination().getTotalPages());
}
private static <T extends org.cloudfoundry.uaa.PaginatedResponse<?>> Function<T, Flux<T>> requestUaaAdditionalPages(Function<Integer, Mono<T>> pageSupplier) {
return response -> {
Integer totalPages = (response.getTotalResults() - 1) / response.getItemsPerPage() + 1;
return Flux
.range(1, totalPages - 1)
.map(page -> 1 + (page * response.getItemsPerPage()))
.flatMap(pageSupplier)
.startWith(response)
.buffer()
.flatMapIterable(d -> d);
};
}
}