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

discord4j.rest.util.PaginationUtil Maven / Gradle / Ivy

/*
 * This file is part of Discord4J.
 *
 * Discord4J 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.
 *
 * Discord4J 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 Discord4J. If not, see .
 */
package discord4j.rest.util;

import reactor.core.publisher.Flux;

import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Function;
import java.util.function.LongFunction;
import java.util.function.ToLongFunction;

public final class PaginationUtil {

    public static  Flux paginateAfter(final Function, Flux> tProducer,
                                            final ToLongFunction keyExtractor, final long startAt,
                                            final int pageSize) {

        return paginateWithQueryParams(tProducer, keyExtractor, startAt, pageSize, "after", false);
    }

    public static  Flux paginateBefore(final Function, Flux> tProducer,
                                             final ToLongFunction keyExtractor, final long startAt,
                                             final int pageSize) {

        return paginateWithQueryParams(tProducer, keyExtractor, startAt, pageSize, "before", true);
    }

    private static  Flux paginateWithQueryParams(final Function, Flux> tProducer,
                                                       final ToLongFunction keyExtractor, final long startAt,
                                                       final int pageSize, final String queryKey,
                                                       final boolean reverse) {

        final LongFunction> nextPage = id -> {
            final Map parameters = new HashMap<>(2);
            parameters.put("limit", pageSize);
            parameters.put(queryKey, id);

            return tProducer.apply(parameters);
        };

        return paginate(nextPage, keyExtractor, startAt, reverse);
    }

    private static  Flux paginate(final LongFunction> nextPage, final ToLongFunction keyExtractor,
                                        final long startAt, final boolean reverse) {

        final ToLongFunction> updateLast = list ->
                list.isEmpty() ? startAt : keyExtractor.applyAsLong(list.get(list.size() - 1));

        final Comparator comparator = Comparator.comparingLong(keyExtractor);
        final AtomicLong previousStart = new AtomicLong(startAt);

        return Flux.defer(() -> nextPage.apply(previousStart.get()))
                .sort(reverse ? comparator.reversed() : comparator)
                .collectList()
                .doOnNext(list -> previousStart.set(updateLast.applyAsLong(list)))
                .flatMapMany(Flux::fromIterable)
                .repeat(() -> previousStart.get() != startAt);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy