package org.wikipedia.database;
import android.content.ContentProviderClient;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.RemoteException;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
public class DatabaseClient<T> {
@NonNull private final ContentProviderClient client;
@NonNull private final DatabaseTable<T> databaseTable;
public DatabaseClient(@NonNull Context context,
@NonNull DatabaseTable<T> databaseTable) {
this(databaseTable.acquireClient(context), databaseTable);
}
public DatabaseClient(@NonNull ContentProviderClient client,
@NonNull DatabaseTable<T> databaseTable) {
this.client = client;
this.databaseTable = databaseTable;
}
public void persist(T obj) {
try {
client.insert(uri(), toContentValues(obj));
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
public Cursor select(@Nullable String selection, @Nullable String[] selectionArgs,
@Nullable String sortOrder) {
return select(uri(), selection, selectionArgs, sortOrder);
}
public Cursor select(@NonNull Uri uri, @Nullable String selection,
@Nullable String[] selectionArgs, @Nullable String sortOrder) {
try {
return client.query(uri, null, selection, selectionArgs, sortOrder);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
public void deleteAll() {
deleteWhere("", new String[] {});
}
public void deleteWhere(String selection, String[] selectionArgs) {
try {
client.delete(uri(), selection, selectionArgs);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
public void delete(@NonNull T obj, @NonNull String[] selectionArgs) {
try {
client.delete(
uri(),
getPrimaryKeySelection(obj, selectionArgs),
getPrimaryKeySelectionArgs(obj)
);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
// TODO: migrate old tables to use unique constraints and just call insertWithOnConflict.
public void upsert(@NonNull T obj, @NonNull String[] selectionArgs) {
try {
int rowsUpdated = client.update(
uri(),
toContentValues(obj),
getPrimaryKeySelection(obj, selectionArgs),
getPrimaryKeySelectionArgs(obj)
);
if (rowsUpdated == 0) {
// TODO: synchronize with other writes. There are two operations performed.
persist(obj);
}
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
public T fromCursor(Cursor cursor) {
return databaseTable.fromCursor(cursor);
}
public ContentValues toContentValues(T obj) {
return databaseTable.toContentValues(obj);
}
public String getPrimaryKeySelection(@NonNull T obj, @NonNull String[] selectionArgs) {
return databaseTable.getPrimaryKeySelection(obj, selectionArgs);
}
public String[] getPrimaryKeySelectionArgs(@NonNull T obj) {
return databaseTable.getPrimaryKeySelectionArgs(obj);
}
protected Uri uri() {
return databaseTable.getBaseContentURI();
}
}