package com.asana.iterator; import com.asana.models.ResultBodyCollection; import com.asana.requests.CollectionRequest; import java.io.IOException; import java.util.Collection; import java.util.Iterator; import java.util.NoSuchElementException; /** * Abstract iterator (implemented by CollectionPageIterator and EventsPageIterator) that loads one page of items at a * time, automatically updating the pagination parameter (e.x. the "offset" or "sync" token). Also exposes an * "items" iterator to iterate over the individual items. */ abstract public class PageIterator<T> implements Iterator<Collection<T>> { protected CollectionRequest<T> request; protected long itemLimit; protected long pageSize; protected long count; protected Object continuation; public PageIterator(CollectionRequest<T> request) { this.request = request; this.continuation = ""; this.count = 0; this.pageSize = (Integer) request.options.get("page_size"); this.itemLimit = request.options.containsKey("item_limit") ? (Integer) request.options.get("item_limit") : -1; if (this.itemLimit <= 0) { this.itemLimit = Long.MAX_VALUE; } } private long currentLimit() { return Math.min(this.pageSize, this.itemLimit - this.count); } @Override public boolean hasNext() { return this.continuation != null && currentLimit() > 0; } @Override public Collection<T> next() throws NoSuchElementException { this.request.query("limit", currentLimit()); try { ResultBodyCollection<T> result = this.getNext(); this.continuation = this.getContinuation(result); if (result.data != null) { this.count += result.data.size(); } return result.data; } catch (IOException error) { NoSuchElementException newError = new NoSuchElementException(); newError.initCause(error); throw newError; } } @Override public void remove() { throw new UnsupportedOperationException(); } public ItemIterator<T> items() { return new ItemIterator<T>(this); } abstract protected ResultBodyCollection<T> getNext() throws IOException; abstract protected Object getContinuation(ResultBodyCollection<T> result); }