package com.boardgamegeek.util;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentResolver;
import android.content.Context;
import android.content.OperationApplicationException;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.RemoteException;
import android.provider.BaseColumns;
import com.boardgamegeek.provider.BggContract;
import java.io.Closeable;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import timber.log.Timber;
public class ResolverUtils {
private ResolverUtils() {
}
public static ContentProviderResult[] applyBatch(Context context, ArrayList<ContentProviderOperation> batch) {
return applyBatch(context, batch, null);
}
public static ContentProviderResult[] applyBatch(Context context, ArrayList<ContentProviderOperation> batch, String debugMessage) {
ContentResolver resolver = context.getContentResolver();
if (batch != null && batch.size() > 0) {
if (PreferencesUtils.getAvoidBatching(context)) {
ContentProviderResult[] results = new ContentProviderResult[batch.size()];
for (int i = 0; i < batch.size(); i++) {
results[i] = applySingle(resolver, batch.get(i), debugMessage);
}
return results;
} else {
try {
return resolver.applyBatch(BggContract.CONTENT_AUTHORITY, batch);
} catch (OperationApplicationException | RemoteException e) {
String m = "Applying batch: " + debugMessage;
Timber.e(e, m);
throw new RuntimeException(m, e);
}
}
}
return new ContentProviderResult[] {};
}
private static ContentProviderResult applySingle(ContentResolver resolver, ContentProviderOperation cpo, String debugMessage) {
ArrayList<ContentProviderOperation> batch = new ArrayList<>(1);
batch.add(cpo);
try {
ContentProviderResult[] result = resolver.applyBatch(BggContract.CONTENT_AUTHORITY, batch);
if (result.length > 0) {
return result[0];
}
} catch (OperationApplicationException | RemoteException e) {
String m = cpo.toString() + "\n" + debugMessage;
Timber.e(e, m);
throw new RuntimeException(m, e);
}
return null;
}
/*
* Determines if the URI exists in the resolver
*/
public static boolean rowExists(ContentResolver resolver, Uri uri) {
return getCount(resolver, uri) > 0;
}
/**
* Get the number of rows at this URI.
*/
public static int getCount(ContentResolver resolver, Uri uri) {
Cursor cursor = resolver.query(uri, new String[] { BaseColumns._ID }, null, null, null);
if (cursor != null) {
try {
return cursor.getCount();
} finally {
closeCursor(cursor);
}
}
return 0;
}
/*
* Use the content resolver to get an integer from the specified column at the URI. Returns 0 if there's not exactly
* one row at the URI.
*/
public static int queryInt(ContentResolver resolver, Uri uri, String columnName) {
return queryInt(resolver, uri, columnName, 0);
}
/*
* Use the content resolver to get an integer from the specified column at the URI. Returns defaultValue if there's
* not exactly one row at the URI.
*/
public static int queryInt(ContentResolver resolver, Uri uri, String columnName, int defaultValue) {
return queryInt(resolver, uri, columnName, defaultValue, null, null);
}
/*
* Use the content resolver to get an integer from the specified column at the URI with the selection applied.
* Returns defaultValue if there's not exactly one row at the URI.
*/
public static int queryInt(ContentResolver resolver, Uri uri, String columnName, int defaultValue, String selection, String[] selectionArgs) {
Cursor cursor = resolver.query(uri, new String[] { columnName }, selection, selectionArgs, null);
try {
int count = cursor != null ? cursor.getCount() : 0;
if (count != 1) {
return defaultValue;
}
cursor.moveToFirst();
return cursor.getInt(0);
} finally {
closeCursor(cursor);
}
}
/*
* Use the content resolver to get a long from the specified column at the URI. Returns 0 if there's not
* exactly one row at the URI.
*/
public static long queryLong(ContentResolver resolver, Uri uri, String columnName) {
return queryLong(resolver, uri, columnName, 0);
}
/*
* Use the content resolver to get a long from the specified column at the URI. Returns defaultValue if there's not
* exactly one row at the URI.
*/
public static long queryLong(ContentResolver resolver, Uri uri, String columnName, int defaultValue) {
return queryLong(resolver, uri, columnName, defaultValue, null, null);
}
/*
* Use the content resolver to get a long from the specified column at the URI with the selection applied. Returns
* defaultValue if there's not exactly one row at the URI.
*/
public static long queryLong(ContentResolver resolver, Uri uri, String columnName, int defaultValue,
String selection, String[] selectionArgs) {
Cursor cursor = resolver.query(uri, new String[] { columnName }, selection, selectionArgs, null);
try {
int count = cursor != null ? cursor.getCount() : 0;
if (count != 1) {
return defaultValue;
}
cursor.moveToFirst();
return cursor.getLong(0);
} finally {
closeCursor(cursor);
}
}
/*
* Use the content resolver to get a list of integers from the specified column at the URI.
*/
public static List<Integer> queryInts(ContentResolver resolver, Uri uri, String columnName) {
return queryInts(resolver, uri, columnName, null, null);
}
/*
* Use the content resolver to get a list of integers from the specified column at the URI.
*/
public static List<Integer> queryInts(ContentResolver resolver, Uri uri, String columnName, String selection, String[] selectionArgs) {
return queryInts(resolver, uri, columnName, selection, selectionArgs, null);
}
/*
* Use the content resolver to get a list of integers from the specified column at the URI.
*/
public static List<Integer> queryInts(ContentResolver resolver, Uri uri, String columnName, String selection, String[] selectionArgs, String sortOrder) {
List<Integer> list = new ArrayList<>();
Cursor cursor = resolver.query(uri, new String[] { columnName }, selection, selectionArgs, sortOrder);
try {
while (cursor != null && cursor.moveToNext()) {
list.add(cursor.getInt(0));
}
} finally {
closeCursor(cursor);
}
return list;
}
/*
* Use the content resolver to get a list of longs from the specified column at the URI.
*/
public static List<Long> queryLongs(ContentResolver resolver, Uri uri, String columnName) {
return queryLongs(resolver, uri, columnName, null, null);
}
/*
* Use the content resolver to get a list of longs from the specified column at the URI.
*/
public static List<Long> queryLongs(ContentResolver resolver, Uri uri, String columnName, String selection, String[] selectionArgs) {
return queryLongs(resolver, uri, columnName, selection, selectionArgs, null);
}
/*
* Use the content resolver to get a list of longs from the specified column at the URI.
*/
public static List<Long> queryLongs(ContentResolver resolver, Uri uri, String columnName, String selection, String[] selectionArgs, String sortOrder) {
List<Long> list = new ArrayList<>();
Cursor cursor = resolver.query(uri, new String[] { columnName }, selection, selectionArgs, sortOrder);
try {
while (cursor != null && cursor.moveToNext()) {
list.add(cursor.getLong(0));
}
} finally {
closeCursor(cursor);
}
return list;
}
/*
* Use the content resolver to get a list of strings from the specified column at the URI.
*/
public static List<String> queryStrings(ContentResolver resolver, Uri uri, String columnName) {
return queryStrings(resolver, uri, columnName, null, null);
}
/*
* Use the content resolver to get a list of strings from the specified column at the URI.
*/
public static List<String> queryStrings(ContentResolver resolver, Uri uri, String columnName, String selection, String[] selectionArgs) {
return queryStrings(resolver, uri, columnName, selection, selectionArgs, null);
}
/*
* Use the content resolver to get a list of strings from the specified column at the URI.
*/
public static List<String> queryStrings(ContentResolver resolver, Uri uri, String columnName, String selection, String[] selectionArgs, String sortOrder) {
List<String> list = new ArrayList<>();
Cursor cursor = resolver.query(uri, new String[] { columnName }, selection, selectionArgs, sortOrder);
try {
while (cursor != null && cursor.moveToNext()) {
list.add(cursor.getString(0));
}
} finally {
closeCursor(cursor);
}
return list;
}
/*
* Use the content resolver to get a string from the specified column at the URI. Returns null if there's not
* exactly one row at the URI.
*/
public static String queryString(ContentResolver resolver, Uri uri, String columnName) {
String value;
Cursor cursor = resolver.query(uri, new String[] { columnName }, null, null, null);
try {
int count = cursor != null ? cursor.getCount() : 0;
if (count != 1) {
return null;
}
cursor.moveToFirst();
value = cursor.getString(0);
} finally {
closeCursor(cursor);
}
return value;
}
/*
* Loads a bitmap from the URI. Returns null if the URI is invalid or the bitmap can't be created.
*/
public static Bitmap getBitmapFromContentProvider(ContentResolver resolver, Uri uri) {
InputStream stream = null;
try {
stream = resolver.openInputStream(uri);
} catch (FileNotFoundException e) {
Timber.d(e, "Couldn't find drawable: %s", uri);
}
if (stream != null) {
Bitmap bitmap = BitmapFactory.decodeStream(stream);
closeStream(stream);
return bitmap;
}
return null;
}
private static void closeCursor(Cursor cursor) {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
}
private static void closeStream(Closeable stream) {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
Timber.e(e, "Could not close stream");
}
}
}
}