/* * Copyright 2014 Sonoport (Asia) Pte Ltd * * 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.sonoport.freesound.query; import java.util.HashMap; import java.util.List; import java.util.Map; import org.json.JSONObject; import com.sonoport.freesound.response.PagingResponse; import com.sonoport.freesound.response.mapping.PagingResponseMapper; /** * Extension of {@link JSONResponseQuery} that represents API calls that can return results that span multiple pages. * The main example of this are search queries, where there may be too many results to return in one go. Results are * returned as an instance of {@link PagingResponse} which contains the common elements relating to the paging, plus a * list of the current page of results. * * @param <Q> The type of the {@link PagingQuery} (required to implement Fluent API elements) * @param <I> The DTO type of the items in the list */ public abstract class PagingQuery<Q extends PagingQuery<Q, I>, I extends Object> extends JSONResponseQuery<List<I>> { /** The default page size if none is specified. */ public static final int DEFAULT_PAGE_SIZE = 15; /** The maximum size of a single page. 150 is the specified maximum in the API documentation. */ public static final int MAXIMUM_PAGE_SIZE = 150; /** The page that will be requested in the query. */ private int page; /** The number of results to return per page. */ private int pageSize; /** * @param httpRequestMethod HTTP method to use for query * @param path The URI path to the API endpoint * @param resultsMapper {@link PagingResponseMapper} to convert results */ protected PagingQuery( final HTTPRequestMethod httpRequestMethod, final String path, final PagingResponseMapper<I> resultsMapper) { this(httpRequestMethod, path, resultsMapper, DEFAULT_PAGE_SIZE); } /** * @param httpRequestMethod HTTP method to use for query * @param path The URI path to the API endpoint * @param resultsMapper {@link PagingResponseMapper} to convert results * @param pageSize The number of results per page */ protected PagingQuery( final HTTPRequestMethod httpRequestMethod, final String path, final PagingResponseMapper<I> resultsMapper, final int pageSize) { this(httpRequestMethod, path, resultsMapper, pageSize, 1); } /** * @param httpRequestMethod HTTP method to use for query * @param path The URI path to the API endpoint * @param resultsMapper {@link PagingResponseMapper} to convert results * @param pageSize The number of results per page * @param startPage The page to start at */ protected PagingQuery( final HTTPRequestMethod httpRequestMethod, final String path, final PagingResponseMapper<I> resultsMapper, final int pageSize, final int startPage) { super(httpRequestMethod, path, resultsMapper); setPageSize(pageSize); setPage(startPage); } @Override public PagingResponse<I> processResponse( final int httpResponseCode, final String httpResponseStatusString, final JSONObject freesoundResponse) { final PagingResponse<I> response = new PagingResponse<>(httpResponseCode, httpResponseStatusString); if (response.isErrorResponse()) { response.setErrorDetails(extractErrorMessage(freesoundResponse)); } else { final PagingResponseMapper<I> resultsMapper = (PagingResponseMapper<I>) getResultsMapper(); response.setCount(resultsMapper.extractCount(freesoundResponse)); response.setNextPageURI(resultsMapper.extractNextPageURI(freesoundResponse)); response.setPreviousPageURI(resultsMapper.extractPreviousPageURI(freesoundResponse)); response.setResults(resultsMapper.map(freesoundResponse)); } return response; } /** * Set the page of results to retrieve in the query, using a Fluent API style. * * @param pageNumber The page number to retrieve * @return The current query */ @SuppressWarnings("unchecked") public Q page(final int pageNumber) { setPage(pageNumber); return (Q) this; } /** * Set the number of results to return per page, using a Fluent API style. * * @param pageSize The number of results per page * @return The current query */ @SuppressWarnings("unchecked") public Q pageSize(final int pageSize) { setPageSize(pageSize); return (Q) this; } @Override public Map<String, Object> getQueryParameters() { final Map<String, Object> queryParams = new HashMap<>(); queryParams.put("page", Integer.valueOf(page)); queryParams.put("page_size", Integer.valueOf(pageSize)); return queryParams; } /** * @return the page */ public int getPage() { return page; } /** * @param page the page to set */ public void setPage(final int page) { if (page < 1) { throw new IllegalArgumentException("Must specifiy a page number greater than 0"); } this.page = page; } /** * @return the pageSize */ public int getPageSize() { return pageSize; } /** * @param pageSize the pageSize to set */ public void setPageSize(final int pageSize) { if (pageSize < 1) { throw new IllegalArgumentException("Must specifiy a page size greater than 0"); } else if (pageSize > MAXIMUM_PAGE_SIZE) { throw new IllegalArgumentException( String.format("Cannot specify a page size greater than %s", MAXIMUM_PAGE_SIZE)); } this.pageSize = pageSize; } }