package net.kornan.framework.activeandroid.content;
import java.util.ArrayList;
import java.util.List;
import net.kornan.framework.activeandroid.ActiveAndroid;
import net.kornan.framework.activeandroid.Cache;
import net.kornan.framework.activeandroid.Configuration;
import net.kornan.framework.activeandroid.Model;
import net.kornan.framework.activeandroid.TableInfo;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.net.Uri;
import android.util.SparseArray;
public class ContentProvider extends android.content.ContentProvider {
//////////////////////////////////////////////////////////////////////////////////////
// PRIVATE CONSTANTS
//////////////////////////////////////////////////////////////////////////////////////
private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
private static final SparseArray<Class<? extends Model>> TYPE_CODES = new SparseArray<Class<? extends Model>>();
//////////////////////////////////////////////////////////////////////////////////////
// PRIVATE MEMBERS
//////////////////////////////////////////////////////////////////////////////////////
private static String sAuthority;
private static SparseArray<String> sMimeTypeCache = new SparseArray<String>();
//////////////////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
//////////////////////////////////////////////////////////////////////////////////////
@Override
public boolean onCreate() {
ActiveAndroid.initialize(getConfiguration());
sAuthority = getAuthority();
final List<TableInfo> tableInfos = new ArrayList<TableInfo>(Cache.getTableInfos());
final int size = tableInfos.size();
for (int i = 0; i < size; i++) {
final TableInfo tableInfo = tableInfos.get(i);
final int tableKey = (i * 2) + 1;
final int itemKey = (i * 2) + 2;
// content://<authority>/<table>
URI_MATCHER.addURI(sAuthority, tableInfo.getTableName().toLowerCase(), tableKey);
TYPE_CODES.put(tableKey, tableInfo.getType());
// content://<authority>/<table>/<id>
URI_MATCHER.addURI(sAuthority, tableInfo.getTableName().toLowerCase() + "/#", itemKey);
TYPE_CODES.put(itemKey, tableInfo.getType());
}
return true;
}
@Override
public String getType(Uri uri) {
final int match = URI_MATCHER.match(uri);
String cachedMimeType = sMimeTypeCache.get(match);
if (cachedMimeType != null) {
return cachedMimeType;
}
final Class<? extends Model> type = getModelType(uri);
final boolean single = ((match % 2) == 0);
StringBuilder mimeType = new StringBuilder();
mimeType.append("vnd");
mimeType.append(".");
mimeType.append(sAuthority);
mimeType.append(".");
mimeType.append(single ? "item" : "dir");
mimeType.append("/");
mimeType.append("vnd");
mimeType.append(".");
mimeType.append(sAuthority);
mimeType.append(".");
mimeType.append(Cache.getTableName(type));
sMimeTypeCache.append(match, mimeType.toString());
return mimeType.toString();
}
// SQLite methods
@Override
public Uri insert(Uri uri, ContentValues values) {
final Class<? extends Model> type = getModelType(uri);
final Long id = Cache.openDatabase().insert(Cache.getTableName(type), null, values);
if (id != null && id > 0) {
Uri retUri = createUri(type, id);
notifyChange(retUri);
return retUri;
}
return null;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
final Class<? extends Model> type = getModelType(uri);
final int count = Cache.openDatabase().update(Cache.getTableName(type), values, selection, selectionArgs);
notifyChange(uri);
return count;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
final Class<? extends Model> type = getModelType(uri);
final int count = Cache.openDatabase().delete(Cache.getTableName(type), selection, selectionArgs);
notifyChange(uri);
return count;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
final Class<? extends Model> type = getModelType(uri);
final Cursor cursor = Cache.openDatabase().query(
Cache.getTableName(type),
projection,
selection,
selectionArgs,
null,
null,
sortOrder);
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
//////////////////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
//////////////////////////////////////////////////////////////////////////////////////
public static Uri createUri(Class<? extends Model> type, Long id) {
final StringBuilder uri = new StringBuilder();
uri.append("content://");
uri.append(sAuthority);
uri.append("/");
uri.append(Cache.getTableName(type).toLowerCase());
if (id != null) {
uri.append("/");
uri.append(id.toString());
}
return Uri.parse(uri.toString());
}
//////////////////////////////////////////////////////////////////////////////////////
// PROTECTED METHODS
//////////////////////////////////////////////////////////////////////////////////////
protected String getAuthority() {
return getContext().getPackageName();
}
protected Configuration getConfiguration() {
return new Configuration.Builder(getContext()).create();
}
//////////////////////////////////////////////////////////////////////////////////////
// PRIVATE METHODS
//////////////////////////////////////////////////////////////////////////////////////
private Class<? extends Model> getModelType(Uri uri) {
final int code = URI_MATCHER.match(uri);
if (code != UriMatcher.NO_MATCH) {
return TYPE_CODES.get(code);
}
return null;
}
private void notifyChange(Uri uri) {
getContext().getContentResolver().notifyChange(uri, null);
}
}