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

com.github.libgraviton.workerbase.PagingResponseIterator Maven / Gradle / Ivy

/**
 * iterator implementation that makes using Graviton pagination a breeze
 */
package com.github.libgraviton.workerbase;

import java.net.URLDecoder;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.fasterxml.jackson.jr.ob.JSON;
import com.google.common.collect.AbstractIterator;
import com.mashape.unirest.http.Headers;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

/**
 * 
 * This class allows to GET resources from Graviton, abstracting pagination.
 * You can just iterate over the set and the Iterator will take care to fetch
 * the next items if available.
 *
 * Important: You *really*should* pass a custom limit(n) RQL
 * expression with your desired pagesize. If you don't, the default Graviton
 * pagesize gets used that is potentially different from what you want.
 *
 * This class has two different constructor implementations:
 * * One where you only pass the request URL and the return will be a
 * {@literal List}. (generic JSON type by Jackson Jr.)
 * * One with URL and a Class type where the return will be {@literal List}. This
 * allows
 * you to serialize to the POJO of your choosing.
 *
 * Example usage (using conversion to DeferredMap), pagesize = 2
 * 
* *
 * {@code
 * PagingResponseIterator pr = new PagingResponseIterator<>(
 *   "http://localhost:8000/person/customer/?limit(2)"
 * );
 *
 * DeferredMap singleElement;
 * while (pr.hasNext()) {
 *   singleElement = pr.next();
 *   System.out.println("customer id = " + singleElement.get("id"));
 * }
 * }
 * 
* * Example usage (using conversion to POJO GravitonFile), pagesize = 1: * *
 * {@code
 * PagingResponseIterator pr2 = new PagingResponseIterator<>(
 *   GravitonFile.class,
 *   "http://localhost:8000/file/?limit(1)"
 * );
 *
 * GravitonFile thefile;
 * while (pr2.hasNext()) {
 *   thefile = pr2.next();
 *   System.out.println("file id = " + thefile.getId());
 * }
 * }
 * 
* * @author List of contributors {@literal } * @see http://swisscom.ch * @version $Id: $Id */ public class PagingResponseIterator extends AbstractIterator { /** * internal iterator */ private Iterator resultSet; /** * last response object */ private HttpResponse response; /** * the next page to fetch (if available) */ private String nextUrl = null; /** * class type to serialize to (if available) */ private Class typeParameterClass; /** * Constructor to serialize to DeferredMap instances * * @param requestUrl url to request * @throws java.lang.Exception if any. */ public PagingResponseIterator(String requestUrl) throws Exception { init(requestUrl); } /** * Constructor to serialize to the object of your choosing * * @param typeParameterClass class type to serialize to * @param requestUrl url to fetch * @throws java.lang.Exception if any. */ public PagingResponseIterator(Class typeParameterClass, String requestUrl) throws Exception { this.typeParameterClass = typeParameterClass; init(requestUrl); } /** * initializes the Iterator by fetching the first page * * @param requestUrl url to fetch * @throws Exception */ private void init(String requestUrl) throws Exception { fetch(requestUrl); parseLinkHeader(); } /** * {@inheritDoc} * * iterator implementation * @see com.google.common.collect.AbstractIterator#computeNext() */ @Override protected T computeNext() { // can we fetch the next? if (!resultSet.hasNext() && nextUrl != null) { try { fetch(nextUrl); // reset next url nextUrl = null; // check for next url parseLinkHeader(); } catch (Exception e) { return endOfData(); } } if (resultSet.hasNext()) { return resultSet.next(); } return endOfData(); } /** * Fetches a page, serializes it and puts it there for the Iterator * * @param fetchUrl url to fetch * @throws Exception */ @SuppressWarnings("unchecked") private void fetch(String fetchUrl) throws Exception { response = Unirest.get(fetchUrl).header("Accept", "application/json").asString(); if (typeParameterClass != null) { resultSet = JSON.std.listOfFrom(typeParameterClass, response.getBody()) .iterator(); } else { resultSet = (Iterator) JSON.std.listFrom(response.getBody()).iterator(); } } /** * Parses the Link header of the response and sets 'nextUrl' accordingly * @throws Exception */ private void parseLinkHeader() throws Exception { Pattern pattern = Pattern.compile("\\<(.*)\\>; rel\\=\\\"next\\\""); Headers headers = response.getHeaders(); if (headers.containsKey("Link")) { String linkHeader = headers.get("Link").get(0); String[] headerParts = linkHeader.split(","); Matcher matcher; for (String singleLinkHeader : headerParts) { matcher = pattern.matcher(singleLinkHeader); if (matcher.matches()) { nextUrl = URLDecoder.decode(matcher.group(1), "UTF-8"); } } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy