001package com.box.sdk;
002
003/**
004 * Abstraction on how SDK is doing pagination. Can be used to start offset or marker based pagination.
005 */
006public final class PagingParameters {
007    /**
008     * Default limit value.
009     */
010    public static final long DEFAULT_LIMIT = 1000;
011    private static final int MAXIMUM_ALLOWED_OFFSET = 300_000;
012    private final long limit;
013    private final boolean useMarker;
014    private final Long offset;
015    private final String marker;
016
017    private PagingParameters(long limit, boolean useMarker, Long offset, String marker) {
018        this.limit = limit;
019        this.useMarker = useMarker;
020        this.offset = offset;
021        this.marker = marker;
022    }
023
024    /**
025     * Starts marker based pagination.
026     * @param limit how many elements per request should be fetched.
027     * @return PagingParameters setup to start marker based pagination.
028     */
029    public static PagingParameters marker(long limit) {
030        return new PagingParameters(limit, true, null, null);
031    }
032
033    /**
034     * Starts offset based pagination.
035     * @param offset where offset pagination should start. Offset cannot be larger than 300000.
036     * @param limit how many elements per request should be fetched.
037     * @return PagingParameters setup to start offset based pagination.
038     */
039    public static PagingParameters offset(long offset, long limit) {
040        if (offset > MAXIMUM_ALLOWED_OFFSET) {
041            throw new IllegalArgumentException(
042                "The maximum offset for offset-based pagination is 300000."
043                    + " Marker-based pagination is recommended when a higher offset is needed."
044            );
045        }
046        return new PagingParameters(limit, false, offset, null);
047    }
048
049    QueryStringBuilder asQueryStringBuilder() {
050        QueryStringBuilder result = new QueryStringBuilder()
051            .appendParam("limit", limit);
052        if (useMarker) {
053            result.appendParam("usemarker", "true");
054            if (marker != null) {
055                result.appendParam("marker", marker);
056            }
057        } else {
058            result.appendParam("offset", offset);
059        }
060        return result;
061    }
062
063    boolean isMarkerBasedPaging() {
064        return useMarker;
065    }
066
067    PagingParameters nextMarker(String nextMarker) {
068        if (!useMarker) {
069            throw new IllegalArgumentException(
070                "Cannot change offset paging to marker based paging. Use PagingParameters#nextOffset(long)."
071            );
072        }
073        return new PagingParameters(limit, true, null, nextMarker);
074    }
075
076    PagingParameters nextOffset(long nextOffset) {
077        if (useMarker) {
078            throw new IllegalArgumentException(
079                "Cannot change marker paging to offset based paging. Use PagingParameters#nextMarker(String)."
080            );
081        }
082        return PagingParameters.offset(nextOffset + limit, limit);
083    }
084
085    long getLimit() {
086        return limit;
087    }
088}