/*
* Copyright 2012 GitHub Inc.
*
* 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.github.mobile.core;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.egit.github.core.client.NoSuchPageException;
import org.eclipse.egit.github.core.client.PageIterator;
/**
* Generic resource pager for elements with an id that can be paged
*
* @param <E>
*/
public abstract class ResourcePager<E> {
/**
* Next page to request
*/
protected int page = 1;
/**
* Number of pages to request
*/
protected int count = 1;
/**
* All resources retrieved
*/
protected final Map<Object, E> resources = new LinkedHashMap<Object, E>();
/**
* Are more pages available?
*/
protected boolean hasMore;
/**
* Reset the number of the next page to be requested from {@link #next()}
* and clear all stored state
*
* @return this pager
*/
public ResourcePager<E> reset() {
page = 1;
return clear();
}
/**
* Clear all stored resources and have the next call to {@link #next()} load
* all previously loaded pages
*
* @return this pager
*/
public ResourcePager<E> clear() {
count = Math.max(1, page - 1);
page = 1;
resources.clear();
hasMore = true;
return this;
}
/**
* Get number of resources loaded into this pager
*
* @return number of resources
*/
public int size() {
return resources.size();
}
/**
* Get resources
*
* @return resources
*/
public List<E> getResources() {
return new ArrayList<E>(resources.values());
}
/**
* Get the next page of issues
*
* @return true if more pages
* @throws IOException
*/
public boolean next() throws IOException {
boolean emptyPage = false;
PageIterator<E> iterator = createIterator(page, -1);
try {
for (int i = 0; i < count && iterator.hasNext(); i++) {
Collection<E> resourcePage = iterator.next();
emptyPage = resourcePage.isEmpty();
if (emptyPage)
break;
for (E resource : resourcePage) {
resource = register(resource);
if (resource == null)
continue;
resources.put(getId(resource), resource);
}
}
// Set page to count value if first call after call to reset()
if (count > 1) {
page = count;
count = 1;
}
page++;
} catch (NoSuchPageException e) {
hasMore = false;
throw e.getCause();
}
hasMore = iterator.hasNext() && !emptyPage;
return hasMore;
}
/**
* Are more pages available to request?
*
* @return true if the last call to {@link #next()} returned true, false
* otherwise
*/
public boolean hasMore() {
return hasMore;
}
/**
* Callback to register a fetched resource before it is stored in this pager
* <p>
* Sub-classes may override
*
* @param resource
* @return resource
*/
protected E register(final E resource) {
return resource;
}
/**
* Get id for resource
*
* @param resource
* @return id
*/
protected abstract Object getId(E resource);
/**
* Create iterator to return given page and size
*
* @param page
* @param size
* @return iterator
*/
public abstract PageIterator<E> createIterator(final int page,
final int size);
}