package com.novoda.downloadmanager.lib;
import android.content.ContentUris;
import android.database.Cursor;
import android.database.CursorWrapper;
import android.net.Uri;
import java.io.File;
/**
* This class wraps a cursor returned by DownloadProvider -- the "underlying cursor" -- and
* presents a different set of columns, those defined in the DownloadManager.COLUMN_* constants.
* Some columns correspond directly to underlying values while others are computed from
* underlying data.
*/
class CursorTranslator extends CursorWrapper {
private final Uri baseUri;
private final PublicFacingStatusTranslator statusTranslator;
public CursorTranslator(Cursor cursor, Uri baseUri, PublicFacingStatusTranslator statusTranslator) {
super(cursor);
this.baseUri = baseUri;
this.statusTranslator = statusTranslator;
}
@Override
public int getInt(int columnIndex) {
return (int) getLong(columnIndex);
}
@Override
public long getLong(int columnIndex) {
String columnName = getColumnName(columnIndex);
switch (columnName) {
case DownloadManager.COLUMN_REASON:
return getReason(super.getInt(getColumnIndex(DownloadContract.Downloads.COLUMN_STATUS)));
case DownloadManager.COLUMN_STATUS:
return getStatus(super.getInt(getColumnIndex(DownloadContract.Downloads.COLUMN_STATUS)));
case DownloadManager.COLUMN_BATCH_STATUS:
return getStatus(super.getInt(getColumnIndex(DownloadContract.Batches.COLUMN_STATUS)));
default:
return super.getLong(columnIndex);
}
}
private long getReason(int status) {
switch (getStatus(status)) {
case DownloadManager.STATUS_FAILED:
return getErrorCode(status);
case DownloadManager.STATUS_PAUSED:
return getPausedReason(status);
default:
return 0; // arbitrary value when status is not an error
}
}
private int getStatus(int rawStatus) {
return statusTranslator.translate(rawStatus);
}
@Override
public String getString(int columnIndex) {
return getColumnName(columnIndex).equals(DownloadManager.COLUMN_LOCAL_URI) ? getLocalUri() : super.getString(columnIndex);
}
private String getLocalUri() {
long destinationType = getLong(getColumnIndex(DownloadContract.Downloads.COLUMN_DESTINATION));
if (destinationType == DownloadsDestination.DESTINATION_FILE_URI
|| destinationType == DownloadsDestination.DESTINATION_EXTERNAL
|| destinationType == DownloadsDestination.DESTINATION_NON_DOWNLOADMANAGER_DOWNLOAD) {
String localPath = getString(getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));
if (localPath == null) {
return null;
}
return Uri.fromFile(new File(localPath)).toString();
}
// return content URI for cache download
long downloadId = getLong(getColumnIndex(DownloadContract.Downloads._ID));
return ContentUris.withAppendedId(baseUri, downloadId).toString();
}
private long getPausedReason(int status) {
switch (status) {
case DownloadStatus.WAITING_TO_RETRY:
return DownloadManager.PAUSED_WAITING_TO_RETRY;
case DownloadStatus.WAITING_FOR_NETWORK:
return DownloadManager.PAUSED_WAITING_FOR_NETWORK;
case DownloadStatus.QUEUED_FOR_WIFI:
return DownloadManager.PAUSED_QUEUED_FOR_WIFI;
case DownloadStatus.QUEUED_DUE_CLIENT_RESTRICTIONS:
return DownloadManager.PAUSED_QUEUED_DUE_CLIENT_RESTRICTIONS;
default:
return DownloadManager.PAUSED_UNKNOWN;
}
}
private long getErrorCode(int status) {
if (isHttpClientError(status) || isHttpServerError(status)) {
// HTTP status code
return status;
}
switch (status) {
case DownloadStatus.FILE_ERROR:
return DownloadManager.ERROR_FILE_ERROR;
case DownloadStatus.UNHANDLED_HTTP_CODE:
case DownloadStatus.UNHANDLED_REDIRECT:
return DownloadManager.ERROR_UNHANDLED_HTTP_CODE;
case DownloadStatus.HTTP_DATA_ERROR:
return DownloadManager.ERROR_HTTP_DATA_ERROR;
case DownloadStatus.TOO_MANY_REDIRECTS:
return DownloadManager.ERROR_TOO_MANY_REDIRECTS;
case DownloadStatus.INSUFFICIENT_SPACE_ERROR:
return DownloadManager.ERROR_INSUFFICIENT_SPACE;
case DownloadStatus.DEVICE_NOT_FOUND_ERROR:
return DownloadManager.ERROR_DEVICE_NOT_FOUND;
case DownloadStatus.CANNOT_RESUME:
return DownloadManager.ERROR_CANNOT_RESUME;
case DownloadStatus.FILE_ALREADY_EXISTS_ERROR:
return DownloadManager.ERROR_FILE_ALREADY_EXISTS;
default:
return DownloadManager.ERROR_UNKNOWN;
}
}
private boolean isHttpClientError(int status) {
return 400 <= status && status < DownloadStatus.MIN_ARTIFICIAL_ERROR_STATUS;
}
private boolean isHttpServerError(int status) {
return 500 <= status && status < 600;
}
}