Commit 391f2bb6 by olly Committed by Oliver Woodman

Remove indirection in DefaultDownloadIndex

DefaultDownloadIndex is currently just forwarding all calls to its
inner class. getDownloadTable() handles initialization, but this
doesn't really seem different to having an initialization method. It
doesn't guarantee initialization happens, since a bad method
implementation could try and access downloadTable directly, just as
a bad method implementation could forget to call the initialization
method. Hence this change removes the indirection.

PiperOrigin-RevId: 232482228
parent 784906b8
...@@ -39,89 +39,6 @@ public final class DefaultDownloadIndex implements DownloadIndex { ...@@ -39,89 +39,6 @@ public final class DefaultDownloadIndex implements DownloadIndex {
@VisibleForTesting /* package */ static final int TABLE_VERSION = 1; @VisibleForTesting /* package */ static final int TABLE_VERSION = 1;
private final DatabaseProvider databaseProvider;
@Nullable private DownloadsTable downloadTable;
/**
* Creates a DefaultDownloadIndex which stores the {@link DownloadState}s on a SQLite database
* provided by {@code databaseProvider}.
*
* @param databaseProvider A DatabaseProvider which provides the database which will be used to
* store DownloadStatus table.
*/
public DefaultDownloadIndex(DatabaseProvider databaseProvider) {
this.databaseProvider = databaseProvider;
}
@Override
@Nullable
public DownloadState getDownloadState(String id) {
return getDownloadTable().get(id);
}
@Override
public DownloadStateCursor getDownloadStates(@DownloadState.State int... states) {
return getDownloadTable().get(states);
}
@Override
public void putDownloadState(DownloadState downloadState) {
getDownloadTable().replace(downloadState);
}
@Override
public void removeDownloadState(String id) {
getDownloadTable().delete(id);
}
private DownloadsTable getDownloadTable() {
if (downloadTable == null) {
downloadTable = new DownloadsTable(databaseProvider);
}
return downloadTable;
}
private static final class DownloadStateCursorImpl implements DownloadStateCursor {
private final Cursor cursor;
private DownloadStateCursorImpl(Cursor cursor) {
this.cursor = cursor;
}
@Override
public DownloadState getDownloadState() {
return DownloadsTable.getDownloadState(cursor);
}
@Override
public int getCount() {
return cursor.getCount();
}
@Override
public int getPosition() {
return cursor.getPosition();
}
@Override
public boolean moveToPosition(int position) {
return cursor.moveToPosition(position);
}
@Override
public void close() {
cursor.close();
}
@Override
public boolean isClosed() {
return cursor.isClosed();
}
}
private static final class DownloadsTable {
private static final String COLUMN_ID = "id"; private static final String COLUMN_ID = "id";
private static final String COLUMN_TYPE = "title"; private static final String COLUMN_TYPE = "title";
private static final String COLUMN_URI = "subtitle"; private static final String COLUMN_URI = "subtitle";
...@@ -213,64 +130,37 @@ public final class DefaultDownloadIndex implements DownloadIndex { ...@@ -213,64 +130,37 @@ public final class DefaultDownloadIndex implements DownloadIndex {
private final DatabaseProvider databaseProvider; private final DatabaseProvider databaseProvider;
public DownloadsTable(DatabaseProvider databaseProvider) { private boolean initialized;
this.databaseProvider = databaseProvider;
int version =
VersionTable.getVersion(
databaseProvider.getReadableDatabase(), VersionTable.FEATURE_OFFLINE);
if (version == VersionTable.VERSION_UNSET || version > TABLE_VERSION) {
SQLiteDatabase writableDatabase = databaseProvider.getWritableDatabase();
writableDatabase.beginTransaction();
try {
VersionTable.setVersion(writableDatabase, VersionTable.FEATURE_OFFLINE, TABLE_VERSION);
writableDatabase.execSQL(SQL_DROP_TABLE_IF_EXISTS);
writableDatabase.execSQL(SQL_CREATE_TABLE);
writableDatabase.setTransactionSuccessful();
} finally {
writableDatabase.endTransaction();
}
} else if (version < TABLE_VERSION) {
// There is no previous version currently.
throw new IllegalStateException();
}
}
public void replace(DownloadState downloadState) { /**
ContentValues values = new ContentValues(); * Creates a DefaultDownloadIndex which stores the {@link DownloadState}s on a SQLite database
values.put(COLUMN_ID, downloadState.id); * provided by {@code databaseProvider}.
values.put(COLUMN_TYPE, downloadState.type); *
values.put(COLUMN_URI, downloadState.uri.toString()); * @param databaseProvider A DatabaseProvider which provides the database which will be used to
values.put(COLUMN_CACHE_KEY, downloadState.cacheKey); * store DownloadStatus table.
values.put(COLUMN_STATE, downloadState.state); */
values.put(COLUMN_DOWNLOAD_PERCENTAGE, downloadState.downloadPercentage); public DefaultDownloadIndex(DatabaseProvider databaseProvider) {
values.put(COLUMN_DOWNLOADED_BYTES, downloadState.downloadedBytes); this.databaseProvider = databaseProvider;
values.put(COLUMN_TOTAL_BYTES, downloadState.totalBytes);
values.put(COLUMN_FAILURE_REASON, downloadState.failureReason);
values.put(COLUMN_STOP_FLAGS, downloadState.stopFlags);
values.put(COLUMN_NOT_MET_REQUIREMENTS, downloadState.notMetRequirements);
values.put(COLUMN_START_TIME_MS, downloadState.startTimeMs);
values.put(COLUMN_UPDATE_TIME_MS, downloadState.updateTimeMs);
values.put(COLUMN_STREAM_KEYS, encodeStreamKeys(downloadState.streamKeys));
values.put(COLUMN_CUSTOM_METADATA, downloadState.customMetadata);
SQLiteDatabase writableDatabase = databaseProvider.getWritableDatabase();
writableDatabase.replace(TABLE_NAME, /* nullColumnHack= */ null, values);
} }
@Override
@Nullable @Nullable
public DownloadState get(String id) { public DownloadState getDownloadState(String id) {
String[] selectionArgs = {id}; ensureInitialized();
try (Cursor cursor = query(COLUMN_SELECTION_ID, selectionArgs)) { try (Cursor cursor = getCursor(COLUMN_SELECTION_ID, new String[] {id})) {
if (cursor.getCount() == 0) { if (cursor.getCount() == 0) {
return null; return null;
} }
cursor.moveToNext(); cursor.moveToNext();
DownloadState downloadState = getDownloadState(cursor); DownloadState downloadState = getDownloadStateForCurrentRow(cursor);
Assertions.checkState(id.equals(downloadState.id)); Assertions.checkState(id.equals(downloadState.id));
return downloadState; return downloadState;
} }
} }
public DownloadStateCursor get(@DownloadState.State int... states) { @Override
public DownloadStateCursor getDownloadStates(@DownloadState.State int... states) {
ensureInitialized();
String selection = null; String selection = null;
if (states.length > 0) { if (states.length > 0) {
StringBuilder selectionBuilder = new StringBuilder(); StringBuilder selectionBuilder = new StringBuilder();
...@@ -284,16 +174,66 @@ public final class DefaultDownloadIndex implements DownloadIndex { ...@@ -284,16 +174,66 @@ public final class DefaultDownloadIndex implements DownloadIndex {
selectionBuilder.append(')'); selectionBuilder.append(')');
selection = selectionBuilder.toString(); selection = selectionBuilder.toString();
} }
Cursor cursor = query(selection, /* selectionArgs= */ null); Cursor cursor = getCursor(selection, /* selectionArgs= */ null);
return new DownloadStateCursorImpl(cursor); return new DownloadStateCursorImpl(cursor);
} }
public void delete(String id) { @Override
String[] selectionArgs = {id}; public void putDownloadState(DownloadState downloadState) {
databaseProvider.getWritableDatabase().delete(TABLE_NAME, COLUMN_SELECTION_ID, selectionArgs); ensureInitialized();
SQLiteDatabase writableDatabase = databaseProvider.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(COLUMN_ID, downloadState.id);
values.put(COLUMN_TYPE, downloadState.type);
values.put(COLUMN_URI, downloadState.uri.toString());
values.put(COLUMN_CACHE_KEY, downloadState.cacheKey);
values.put(COLUMN_STATE, downloadState.state);
values.put(COLUMN_DOWNLOAD_PERCENTAGE, downloadState.downloadPercentage);
values.put(COLUMN_DOWNLOADED_BYTES, downloadState.downloadedBytes);
values.put(COLUMN_TOTAL_BYTES, downloadState.totalBytes);
values.put(COLUMN_FAILURE_REASON, downloadState.failureReason);
values.put(COLUMN_STOP_FLAGS, downloadState.stopFlags);
values.put(COLUMN_NOT_MET_REQUIREMENTS, downloadState.notMetRequirements);
values.put(COLUMN_START_TIME_MS, downloadState.startTimeMs);
values.put(COLUMN_UPDATE_TIME_MS, downloadState.updateTimeMs);
values.put(COLUMN_STREAM_KEYS, encodeStreamKeys(downloadState.streamKeys));
values.put(COLUMN_CUSTOM_METADATA, downloadState.customMetadata);
writableDatabase.replace(TABLE_NAME, /* nullColumnHack= */ null, values);
}
@Override
public void removeDownloadState(String id) {
ensureInitialized();
databaseProvider
.getWritableDatabase()
.delete(TABLE_NAME, COLUMN_SELECTION_ID, new String[] {id});
} }
private Cursor query(@Nullable String selection, @Nullable String[] selectionArgs) { private void ensureInitialized() {
if (initialized) {
return;
}
SQLiteDatabase readableDatabase = databaseProvider.getReadableDatabase();
int version = VersionTable.getVersion(readableDatabase, VersionTable.FEATURE_OFFLINE);
if (version == VersionTable.VERSION_UNSET || version > TABLE_VERSION) {
SQLiteDatabase writableDatabase = databaseProvider.getWritableDatabase();
writableDatabase.beginTransaction();
try {
VersionTable.setVersion(writableDatabase, VersionTable.FEATURE_OFFLINE, TABLE_VERSION);
writableDatabase.execSQL(SQL_DROP_TABLE_IF_EXISTS);
writableDatabase.execSQL(SQL_CREATE_TABLE);
writableDatabase.setTransactionSuccessful();
} finally {
writableDatabase.endTransaction();
}
} else if (version < TABLE_VERSION) {
// There is no previous version currently.
throw new IllegalStateException();
}
initialized = true;
}
private Cursor getCursor(@Nullable String selection, @Nullable String[] selectionArgs) {
String sortOrder = COLUMN_START_TIME_MS + " ASC"; String sortOrder = COLUMN_START_TIME_MS + " ASC";
return databaseProvider return databaseProvider
.getReadableDatabase() .getReadableDatabase()
...@@ -307,7 +247,7 @@ public final class DefaultDownloadIndex implements DownloadIndex { ...@@ -307,7 +247,7 @@ public final class DefaultDownloadIndex implements DownloadIndex {
sortOrder); sortOrder);
} }
private static DownloadState getDownloadState(Cursor cursor) { private static DownloadState getDownloadStateForCurrentRow(Cursor cursor) {
return new DownloadState( return new DownloadState(
cursor.getString(COLUMN_INDEX_ID), cursor.getString(COLUMN_INDEX_ID),
cursor.getString(COLUMN_INDEX_TYPE), cursor.getString(COLUMN_INDEX_TYPE),
...@@ -361,5 +301,43 @@ public final class DefaultDownloadIndex implements DownloadIndex { ...@@ -361,5 +301,43 @@ public final class DefaultDownloadIndex implements DownloadIndex {
} }
return streamKeys; return streamKeys;
} }
private static final class DownloadStateCursorImpl implements DownloadStateCursor {
private final Cursor cursor;
private DownloadStateCursorImpl(Cursor cursor) {
this.cursor = cursor;
}
@Override
public DownloadState getDownloadState() {
return getDownloadStateForCurrentRow(cursor);
}
@Override
public int getCount() {
return cursor.getCount();
}
@Override
public int getPosition() {
return cursor.getPosition();
}
@Override
public boolean moveToPosition(int position) {
return cursor.moveToPosition(position);
}
@Override
public void close() {
cursor.close();
}
@Override
public boolean isClosed() {
return cursor.isClosed();
}
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment