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

com.github.robozonky.internal.remote.PaginatedApi Maven / Gradle / Ivy

There is a newer version: 6.4.1
Show newest version
/*
 * Copyright 2020 The RoboZonky Project
 *
 * 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 com.github.robozonky.internal.remote;

import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jboss.resteasy.client.jaxrs.ResteasyClient;

import com.github.robozonky.api.remote.entities.ZonkyApiToken;

class PaginatedApi {

    private static final Logger LOGGER = LogManager.getLogger(PaginatedApi.class);

    private String sortString;
    private final Class api;
    private final String url;
    private final ResteasyClient client;
    private final Supplier tokenSupplier;
    private final RequestCounter counter;

    PaginatedApi(final Class api, final String url, final Supplier token,
            final ResteasyClient client) {
        this(api, url, token, client, null);
    }

    public PaginatedApi(final Class api, final String url, final Supplier token,
            final ResteasyClient client, final RequestCounter counter) {
        this.api = api;
        this.url = url;
        this.client = client;
        this.tokenSupplier = token;
        this.counter = counter;
    }

    public void setSortString(final String sortString) {
        this.sortString = sortString;
    }

    /**
     * Filters are for one-time use only. They need to be thrown away after being used, as they could otherwise be used
     * to store and transfer stale state, such as request headers etc. For the same reason, they must not be shared
     * among threads.
     * 
     * @return
     */
    private RoboZonkyFilter newFilter() {
        return new AuthenticatedFilter(tokenSupplier);
    }

    public  Q execute(final Function function) {
        return this.execute(function, true);
    }

    public  Q execute(final Function function, final boolean trackRequests) {
        return this.execute(function, new Select(), newFilter(), trackRequests);
    }

     Q execute(final Function function, final Select select, final RoboZonkyFilter filter) {
        return execute(function, select, filter, true);
    }

     Q execute(final Function function, final Select select, final RoboZonkyFilter filter,
            final boolean trackRequests) {
        select.accept(filter);
        return execute(function, filter, trackRequests);
    }

     Q execute(final Function function, final RoboZonkyFilter filter, final boolean trackRequests) {
        final T proxy = ProxyFactory.newProxy(client, filter, api, url);
        return Api.call(function, proxy, trackRequests ? counter : null);
    }

    public PaginatedResult execute(final Function> function, final Select select, final int pageNo,
            final int pageSize) {
        return this.execute(function, select, pageNo, pageSize, newFilter());
    }

    PaginatedResult execute(final Function> function, final Select select, final int pageNo,
            final int pageSize, final RoboZonkyFilter filter) {
        if (sortString != null) {
            filter.setRequestHeader("X-Order", sortString);
        }
        filter.setRequestHeader("X-Page", String.valueOf(pageNo));
        filter.setRequestHeader("X-Size", String.valueOf(pageSize));
        LOGGER.trace("Will request page #{} of size {}, sort string is '{}'.", pageNo, pageSize, sortString);
        final List result = this.execute(function, select, filter);
        final int totalSize = filter.getLastResponseHeader("X-Total")
            .map(Integer::parseInt)
            .orElse(0);
        LOGGER.trace("Has {} results in total.", totalSize);
        return new PaginatedResult<>(result, totalSize);
    }
}