package com.crossbow.volley; import android.support.annotation.NonNull; import com.android.volley.Request; import com.android.volley.VolleyError; import com.android.volley.VolleyLog; import com.android.volley.toolbox.ByteArrayPool; import java.io.File; import java.util.LinkedList; /** */ public abstract class FileRequest<T> implements Comparable<FileRequest>{ private MarkerLog markerLog = new MarkerLog(); private boolean canceled; /** * path to the file on disk */ private String filePath; /** * Error listener for errors */ private FileResponse.ErrorListener errorListener; /** * Request number, used by file queue */ private int sequence; /** * FileQueue the file queue that the request is a part of */ private FileQueue fileQueue; /** * ByteArrayPool the byte array pool used for reading and writing */ private ByteArrayPool byteArrayPool; /** * Tag used to cancel a request */ private Object tag; /** * DEFAULT_BUFFER_SIZE */ private static int DEFAULT_BUFFER_SIZE = 4096; /** * The Priority of the request. This is used to order the requests in the queue. Same {@link Request.Priority Priority} */ public Request.Priority getPriority() { return Request.Priority.NORMAL; } public void setByteArrayPool(ByteArrayPool byteArrayPool) { this.byteArrayPool = byteArrayPool; } /** * Creates a new file request to the file path */ public FileRequest(String filePath, FileResponse.ErrorListener errorListener) { if(filePath == null) { throw new IllegalArgumentException("File Path cant be null"); } this.errorListener = errorListener; this.filePath = filePath; } public abstract FileResponse<T> doFileWork(File file) throws VolleyError; public final void preformDelivery(FileResponse<T> response) { deliverResult(response.data); } public final void preformError(VolleyError volleyError) { deliverError(volleyError); } /** * The path to the file for this request * @return the file path */ public String getFilePath() { return filePath; } protected void deliverError(VolleyError error) { if(errorListener != null) { errorListener.onErrorResponse(error); } } /** * Mark this request as canceled */ public void cancel() { this.canceled = true; } protected void setFileQueue(FileQueue fileQueue) { this.fileQueue = fileQueue; } /** * @return true if a request is canceled */ public boolean isCanceled() { return canceled; } /** * @return the tag for this request */ public Object getTag() { return tag; } /** * Sets the tag for this request, Used to cancel requests already in flight * @param tag the tag to set */ public void setTag(Object tag) { this.tag = tag; } /** * set the sequence number (Used for ordering) * @param sequence the sequence number */ public void sequence(int sequence) { this.sequence = sequence; } /** * get the sequence number */ public int getSequence() { return sequence; } public void mark(String message) { markerLog.addMark(message); } @Override public int compareTo(@NonNull FileRequest another) { Request.Priority left = this.getPriority(); Request.Priority right = another.getPriority(); // High-priority requests are "lesser" so they are sorted to the front. // Equal priorities are sorted by sequence number to provide FIFO ordering. return left == right ? getSequence() - another.getSequence() : right.ordinal() - left.ordinal(); } protected void finish() { VolleyLog.d(getFilePath()); markerLog.log(); fileQueue.finishRequest(this); } protected abstract void deliverResult(T result); private static class MarkerLog { private LinkedList<Marker> markers = new LinkedList<>(); private static final Object LOCK = new Object(); public void log() { synchronized (LOCK) { long startTime = 0; for (int i = 0; i < markers.size(); i++) { Marker marker = markers.get(i); if(i == 0) { marker.log(0); } else { double diff = (Math.abs(startTime - marker.time)) / 1000f; marker.log(diff); } startTime = marker.time; } } } public void addMark(String message) { Marker marker = new Marker(message); synchronized (LOCK) { markers.add(marker); } } private static class Marker { private long time; private String msg; public Marker(String msg) { time = System.nanoTime() / 1000; this.msg = msg; } public void log(double timeDiff) { VolleyLog.d("(+%-4.3f)ms %s", timeDiff, msg); } } } }