package com.instructure.canvasapi.utilities;
import com.instructure.canvasapi.model.CanvasModel;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import retrofit.RetrofitError;
import retrofit.client.Response;
/**
* A generic bridge to get around pagination when needed.
*
* Usage: Use this as your CanvasCallback and implement the ExhaustiveBridgeEvents callback.
* In the ExhaustiveBridgeEvents callback add your 'next' api call until exhausted.
* @param <T>
*/
public class ExhaustiveBridgeCallback<T extends CanvasModel> extends CanvasCallback<T[]>{
private CanvasCallback<T[]> callback;
private ExhaustiveBridgeEvents eventsCallback;
private List<T> networkItems = new ArrayList<>();
private List<T> cacheItems = new ArrayList<>();
private Class<T> clazz;
public interface ExhaustiveBridgeEvents {
void performApiCallWithExhaustiveCallback(CanvasCallback callback, String nextUrl, boolean isCached);
}
public ExhaustiveBridgeCallback(Class<T> clazz, CanvasCallback<T[]> callback, ExhaustiveBridgeEvents exhaustiveBridgeEvents) {
super(callback.statusDelegate);
this.callback = callback;
this.clazz = clazz;
this.eventsCallback = exhaustiveBridgeEvents;
if(eventsCallback == null) {
throw new UnsupportedOperationException("ExhaustiveBridgeEvents cannot be null");
}
}
@Override
public void cache(T[] ts, LinkHeaders linkHeaders, Response response) {
if (callback.isCancelled()) {
return;
}
String nextURL = linkHeaders.nextURL;
Collections.addAll(cacheItems, ts);
if(nextURL == null) { // Items exhaustively paginated
T[] toArray = cacheItems.toArray((T[]) Array.newInstance(clazz, networkItems.size()));
callback.cache(toArray, linkHeaders, response);
} else { // Get the next page
eventsCallback.performApiCallWithExhaustiveCallback(this, nextURL, true);
}
}
@Override
public void firstPage(T[] ts, LinkHeaders linkHeaders, Response response) {
if (callback.isCancelled()) {
return;
}
String nextURL = linkHeaders.nextURL;
Collections.addAll(networkItems, ts);
if(nextURL == null) { // Items exhaustively paginated
T[] toArray = networkItems.toArray((T[]) Array.newInstance(clazz, networkItems.size()));
callback.firstPage(toArray, linkHeaders, response);
} else { // Get the next page
eventsCallback.performApiCallWithExhaustiveCallback(this, nextURL, false);
}
}
@Override
public boolean onFailure(RetrofitError retrofitError) {
return callback.onFailure(retrofitError);
}
// region Getter & Setters
public ExhaustiveBridgeEvents getEventsCallback() {
return eventsCallback;
}
public void setEventsCallback(ExhaustiveBridgeEvents eventsCallback) {
this.eventsCallback = eventsCallback;
}
// endregion
}