synapticloop.scaleway.api.response.BasePaginationResponse.java Source code

Java tutorial

Introduction

Here is the source code for synapticloop.scaleway.api.response.BasePaginationResponse.java

Source

package synapticloop.scaleway.api.response;

/*
 * Copyright (c) 2016-2017 synapticloop.
 * 
 * All rights reserved.
 * 
 * This code may contain contributions from other parties which, where 
 * applicable, will be listed in the default build file for the project 
 * ~and/or~ in a file named CONTRIBUTORS.txt in the root of the project.
 * 
 * This source code and any derived binaries are covered by the terms and 
 * conditions of the Licence agreement ("the Licence").  You may not use this 
 * source code or any derived binaries except in compliance with the Licence.  
 * A copy of the Licence is available in the file named LICENSE.txt shipped with 
 * this source code or binaries.
 */

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/*
 * Copyright (c) 2016 Synapticloop.
 * 
 * All rights reserved.
 * 
 * This code may contain contributions from other parties which, where 
 * applicable, will be listed in the default build file for the project 
 * ~and/or~ in a file named CONTRIBUTORS.txt in the root of the project.
 * 
 * This source code and any derived binaries are covered by the terms and 
 * conditions of the Licence agreement ("the Licence").  You may not use this 
 * source code or any derived binaries except in compliance with the Licence.  
 * A copy of the Licence is available in the file named LICENSE.txt shipped with 
 * this source code or binaries.
 */

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import org.apache.http.Header;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The base pagination response, for responses which include information from
 * the returned headers that include pagination results in the form of two 
 * headers:
 * <ul>
 *   <li>HEADER_X_TOTAL_COUNT = "X-Total-Count" - the total count of results</li>
 *   <li>HEADER_LINK = "Link" - the link which may contain at least one of 'next', 'previous', 'first' or 'last'</li>
 * </ul>
 *
 */
@JsonIgnoreProperties(ignoreUnknown = true)
public abstract class BasePaginationResponse {
    private static final Logger LOGGER = LoggerFactory.getLogger(BasePaginationResponse.class);

    private static final Pattern PATTERN_NEXT = Pattern
            .compile(".*page=(\\d*).*per_page=(\\d*).*rel=\\\"next\\\".*");
    private static final Pattern PATTERN_PREVIOUS = Pattern
            .compile(".*page=(\\d*).*per_page=(\\d*).*rel=\\\"previous\\\".*");
    private static final Pattern PATTERN_LAST = Pattern
            .compile(".*page=(\\d*).*per_page=(\\d*).*rel=\\\"last\\\".*");

    private static final String HEADER_X_TOTAL_COUNT = "X-Total-Count";
    private static final String HEADER_LINK = "Link";

    private int totalCount = 0;
    private int numPerPage = 0;
    private int currentPage = 0;

    /**
     * Parse the pagination headers extracting the required pagination information
     * 
     * @param headers The headers received from the request
     */
    public void parsePaginationHeaders(Header[] headers) {
        for (Header header : headers) {
            String headerName = header.getName();
            switch (headerName) {
            case HEADER_X_TOTAL_COUNT:
                LOGGER.debug("Received '{}' header with value '{}'.", header.getName(), header.getValue());
                this.totalCount = Integer.parseInt(header.getValue());
                break;
            case HEADER_LINK:
                LOGGER.debug("Received '{}' header with value '{}'.", header.getName(), header.getValue());
                // should look something like this:
                // </images?page=2&per_page=50>; rel="next",</images?page=5&per_page=50>; rel="last"
                parseLinkHeader(header.getValue());
                break;
            default:
                break;
            }
        }
    }

    /**
     * Parse the 'Link' header to determine the current page, and the number of 
     * results returned per page
     * 
     * @param value The header value to parse
     */
    private void parseLinkHeader(String value) {
        // should look something like this:
        // </images?page=1&per_page=50>; rel="first",</images?page=4&per_page=50>; rel="previous",</images?page=5&per_page=50>; rel="last"

        Matcher previousMatcher = PATTERN_PREVIOUS.matcher(value);
        if (previousMatcher.matches() && previousMatcher.groupCount() == 2) {
            this.currentPage = Integer.parseInt(previousMatcher.group(1)) + 1;
            this.numPerPage = Integer.parseInt(previousMatcher.group(2));
            return;
        }

        // should look something like this:
        // </images?page=2&per_page=50>; rel="next",</images?page=5&per_page=50>; rel="last"
        Matcher nextMatcher = PATTERN_NEXT.matcher(value);
        if (nextMatcher.matches() && nextMatcher.groupCount() == 2) {
            this.currentPage = Integer.parseInt(nextMatcher.group(1)) - 1;
            this.numPerPage = Integer.parseInt(nextMatcher.group(2));
            return;
        }

        // at this point - there is only one page and we are on it
        // should look something like this:
        // </servers?page=1&per_page=2>; rel="last"
        Matcher lastMatcher = PATTERN_LAST.matcher(value);
        if (lastMatcher.matches() && lastMatcher.groupCount() == 2) {
            this.currentPage = Integer.parseInt(lastMatcher.group(1));
            this.numPerPage = Integer.parseInt(lastMatcher.group(2));
            return;
        }
    }

    /**
     * Return the total count of results for this request
     * 
     * @return The total count of results for this request
     */
    public int getTotalCount() {
        return this.totalCount;
    }

    /**
     * Return the number of results returned per page
     * 
     * @return The number of results returned per page
     */
    public int getNumPerPage() {
        return this.numPerPage;
    }

    /**
     * Return the number of pages of results that exist for this call
     * 
     * @return The number of pages of results that exist for this call
     */
    public int getNumPages() {
        return ((int) Math.ceil(((float) totalCount) / ((float) numPerPage)));
    }

    /**
     * Return the current page number of results for this request
     * 
     * @return The current page number of results for this request
     */
    public int getCurrentPage() {
        return this.currentPage;
    }
}