package com.gueei.demos.markupDemo.contentProvider;
/**
* User: =ra=
* Date: 18.07.11
* Time: 22:04
*/
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
import java.util.HashMap;
public class mdContentProvider extends ContentProvider {
private static final String DATABASE_NAME = "markupDemo.db";
private static final int DATABASE_VERSION = 1;
private static final int MASTER_TABLE_GROUPS_COUNT = 20;
private static final int DETAIL_RECORD_COUNT_FOR_MASTER_GROUP = 2;
/**
* This class helps open, create, and upgrade the database file.
*/
private static class DatabaseHelper extends SQLiteOpenHelper {
private final Context sContext;
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
sContext = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.beginTransaction();
try {
db.execSQL("CREATE TABLE master(_ID INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE " +
"NOT " + "NULL," + "Name TEXT," +
"detailsCount INTEGER NOT NULL DEFAULT 0)");
db.execSQL("CREATE TABLE detail(_ID INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE " +
"NOT " + "NULL," + "" + "" + "Name TEXT," +
"masterID INTEGER NOT NULL)");
db.execSQL(
"CREATE TRIGGER masterReCalcDelete AFTER DELETE ON detail FOR EACH ROW " +
"BEGIN " +
"UPDATE master Set detailsCount=(select count(*) from detail where " +
"detail.masterID=OLD" + ".masterID)" + "WHERE master._ID=OLD.masterID;" +
"END");
db.execSQL(
"CREATE TRIGGER masterReCalcInsert AFTER INSERT ON detail FOR EACH ROW " +
"BEGIN " +
"UPDATE master Set detailsCount=(select count(*) from detail where " +
"detail.masterID=NEW" + ".masterID)" + "WHERE master._ID=NEW.masterID;" +
"DELETE from detail WHERE NOT EXISTS (SELECT 1 FROM master WHERE detail" +
".masterID=master" + "._ID);END");
db.execSQL(
"CREATE TRIGGER masterReCalcUpdate AFTER UPDATE ON detail FOR EACH ROW " +
"WHEN NEW" + ".masterID!=OLD.masterID " +
"BEGIN UPDATE master Set detailsCount=(select count(*) from detail " +
"where detail" + ".masterID=NEW.masterID)" +
"WHERE master._ID=NEW.masterID;" +
"UPDATE master Set detailsCount=(select count(*) from detail where " +
"detail.masterID=OLD" + ".masterID)" +
"WHERE master._ID=OLD.masterID;END");
db.execSQL("CREATE TRIGGER masterInsert AFTER INSERT ON master FOR EACH ROW " +
"BEGIN " +
"UPDATE master Set detailsCount=(select count(*) from detail where " +
"detail.masterID=NEW" + "._ID)" + "WHERE master._ID=NEW._ID;END");
fillWithData(db);
db.setTransactionSuccessful();
}
catch (Exception ex) {
ex.printStackTrace();
}
finally {
db.endTransaction();
}
}
@Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public void fillWithData(SQLiteDatabase db) {
// master
db.execSQL("delete from detail");
String master =
"insert or replace into master (Name,_ID) values ('Group [GRP]'," + "[GRP])";
String detail = "insert into detail (Name,masterID) values ('Item [GRP].[ITEM]'," +
"[GRP])";
for (int group = 1; group <= MASTER_TABLE_GROUPS_COUNT; ++group) {
String grpInsCmd = master.replace("[GRP]", ((Integer) group).toString());
db.execSQL(grpInsCmd);
for (int item = 1; item <= DETAIL_RECORD_COUNT_FOR_MASTER_GROUP; ++item) {
String itmInsCmd = detail.replace("[GRP]", ((Integer) group).toString());
itmInsCmd = itmInsCmd.replace("[ITEM]", ((Integer) item).toString());
db.execSQL(itmInsCmd);
}
}
}
}
private DatabaseHelper mOpenHelper;
@Override public boolean onCreate() {
mOpenHelper = new DatabaseHelper(getContext());
return true;
}
@Override
public Cursor query(final Uri uri, final String[] projection, final String selection,
final String[] selectionArgs, final String sortOrder) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
String orderBy = null;
String groupBy = null;
String having = null;
switch (sUriMatcher.match(uri)) {
case DETAIL_ITEM:
qb.appendWhere("detail._ID=" + uri.getPathSegments().get(1));
case DETAIL_DIR:
qb.setTables("detail");
qb.setProjectionMap(sDetailProjectionMap);
orderBy = DETAIL_SORT_ORDER;
break;
case DETAIL_MASTER_DIR:
qb.appendWhere("detail.masterID=" + uri.getPathSegments().get(2));
qb.setTables("detail");
qb.setProjectionMap(sDetailProjectionMap);
orderBy = DETAIL_SORT_ORDER;
break;
case MASTER_ITEM:
qb.appendWhere("master._ID=" + uri.getPathSegments().get(1));
case MASTER_DIR:
qb.setTables("master");
qb.setProjectionMap(sMasterProjectionMap);
orderBy = MASTER_SORT_ORDER;
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
if (!TextUtils.isEmpty(sortOrder)) {
orderBy = sortOrder;
}
// Get the database and run the query
SQLiteDatabase db = mOpenHelper.getReadableDatabase();
Cursor cursor =
qb.query(db, projection, selection, selectionArgs, groupBy, having, orderBy);
// Tell the cursor what uri to watch, so it knows when its source data changes
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
@Override public String getType(final Uri uri) {
switch (sUriMatcher.match(uri)) {
case DETAIL_ITEM:
return CONTENT_TYPE_PART_ITEM + "detail";
case DETAIL_DIR:
case DETAIL_MASTER_DIR:
return CONTENT_TYPE_PART_DIR + "detail";
case MASTER_ITEM:
return CONTENT_TYPE_PART_ITEM + "master";
case MASTER_DIR:
return CONTENT_TYPE_PART_DIR + "master";
case RESTORE_ALL:
return CONTENT_TYPE_PART_ITEM + "restore";
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
}
@Override public Uri insert(final Uri uri, final ContentValues initialValues) {
ContentValues values;
if (initialValues != null) {
values = new ContentValues(initialValues);
}
else {
values = new ContentValues();
}
if (values.containsKey("_ID") == true) {
values.remove("_ID");
}
if (values.containsKey("Name") == false) {
values.put("Name", "Wasn't set");
}
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
long rowId = 0;
switch (sUriMatcher.match(uri)) {
case DETAIL_DIR:
if (values.containsKey("masterID") == false) {
throw new SQLException(
"detail.masterID is not set. Failed to insert row into " + uri);
}
rowId = db.insert("detail", null, values);
if (rowId > 0) {
Uri xUri = Uri.parse(
"content://" + AUTHORITY + "/detail/" + ((Long) rowId).toString());
getContext().getContentResolver()
.notifyChange(Uri.parse("content://" + AUTHORITY + "/detail/#"), null);
getContext().getContentResolver()
.notifyChange(Uri.parse("content://" + AUTHORITY + "/details"), null);
getContext().getContentResolver()
.notifyChange(Uri.parse("content://" + AUTHORITY + "/details/master/#"),
null);
getContext().getContentResolver()
.notifyChange(Uri.parse("content://" + AUTHORITY + "/master/#"), null);
getContext().getContentResolver()
.notifyChange(Uri.parse("content://" + AUTHORITY + "/masters"), null);
return xUri;
}
else {
throw new SQLException("Failed to insert row into " + uri);
}
case MASTER_DIR:
if (values.containsKey("detailsCount") == true) {
values.remove("detailsCount");
}
rowId = db.insert("master", null, values);
if (rowId > 0) {
Uri xUri = Uri.parse(
"content://" + AUTHORITY + "/master/" + ((Long) rowId).toString());
getContext().getContentResolver()
.notifyChange(Uri.parse("content://" + AUTHORITY + "/master/#"), null);
getContext().getContentResolver()
.notifyChange(Uri.parse("content://" + AUTHORITY + "/masters"), null);
return xUri;
}
else {
throw new SQLException("Failed to insert row into " + uri);
}
case RESTORE_ALL:
db.beginTransaction();
try {
mOpenHelper.fillWithData(db);
db.setTransactionSuccessful();
Uri xUri = Uri.parse("content://" + AUTHORITY + "/restore/1");
getContext().getContentResolver()
.notifyChange(Uri.parse("content://" + AUTHORITY + "/detail/#"), null);
getContext().getContentResolver()
.notifyChange(Uri.parse("content://" + AUTHORITY + "/details"), null);
getContext().getContentResolver()
.notifyChange(Uri.parse("content://" + AUTHORITY + "/details/master/#"),
null);
getContext().getContentResolver()
.notifyChange(Uri.parse("content://" + AUTHORITY + "/master/#"), null);
getContext().getContentResolver()
.notifyChange(Uri.parse("content://" + AUTHORITY + "/masters"), null);
return xUri;
}
catch (Exception ex) {
ex.printStackTrace();
}
finally {
db.endTransaction();
}
default:
throw new IllegalArgumentException("Insert: Unknown URI " + uri);
}
}
@Override
public int delete(final Uri uri, final String selection, final String[] selectionArgs) {
int count = 0;
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
String where = null;
switch (sUriMatcher.match(uri)) {
case DETAIL_ITEM: {
where = "detail._ID=" + uri.getPathSegments().get(1);
}
case DETAIL_DIR:
if (null != where) {
where += (!TextUtils.isEmpty(selection) ? " AND (" + selection + ")" : "");
}
else {
where = selection;
}
count = db.delete("detail", where, selectionArgs);
break;
case DETAIL_MASTER_DIR:
where = "detail.masterID=" + uri.getPathSegments().get(2);
where += (!TextUtils.isEmpty(selection) ? " AND (" + selection + ")" : "");
count = db.delete("detail", where, selectionArgs);
break;
case MASTER_ITEM: {
where = "master._ID=" + uri.getPathSegments().get(1);
}
case MASTER_DIR:
if (null != where) {
where += (!TextUtils.isEmpty(selection) ? " AND (" + selection + ")" : "");
}
else {
where = selection;
}
count = db.delete("master", where, selectionArgs);
break;
default:
throw new IllegalArgumentException("Delete: Unknown URI " + uri);
}
if (count > 0) {
getContext().getContentResolver()
.notifyChange(Uri.parse("content://" + AUTHORITY + "/detail/#"), null);
getContext().getContentResolver()
.notifyChange(Uri.parse("content://" + AUTHORITY + "/details"), null);
getContext().getContentResolver()
.notifyChange(Uri.parse("content://" + AUTHORITY + "/details/master/#"),
null);
getContext().getContentResolver()
.notifyChange(Uri.parse("content://" + AUTHORITY + "/master/#"), null);
getContext().getContentResolver()
.notifyChange(Uri.parse("content://" + AUTHORITY + "/masters"), null);
}
return count;
}
@Override
public int update(final Uri uri, final ContentValues initialValues, final String selection,
final String[] selectionArgs) {
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
int count = 0;
ContentValues values;
if (initialValues != null) {
values = new ContentValues(initialValues);
}
else {
values = new ContentValues();
}
if (values.containsKey("_ID") == true) {
throw new SQLException(
"Value <_ID> shouldn't be changed. Failed to update row in " + uri);
}
if (values.containsKey("detailsCount") == true) {
values.remove("detailsCount");
}
String where = null;
switch (sUriMatcher.match(uri)) {
case DETAIL_ITEM: {
where = "detail._ID=" + uri.getPathSegments().get(1);
}
case DETAIL_DIR:
if (null != where) {
where += (!TextUtils.isEmpty(selection) ? " AND (" + selection + ")" : "");
}
else {
where = selection;
}
count = db.update("detail", values, where, selectionArgs);
break;
case DETAIL_MASTER_DIR:
where = "detail.masterID=" + uri.getPathSegments().get(2);
where += (!TextUtils.isEmpty(selection) ? " AND (" + selection + ")" : "");
count = db.update("detail", values, where, selectionArgs);
break;
case MASTER_ITEM: {
where = "master._ID=" + uri.getPathSegments().get(1);
}
case MASTER_DIR:
if (null != where) {
where += (!TextUtils.isEmpty(selection) ? " AND (" + selection + ")" : "");
}
else {
where = selection;
}
count = db.update("master", values, where, selectionArgs);
break;
default:
throw new IllegalArgumentException("Update: Unknown URI " + uri);
}
if (count > 0) {
getContext().getContentResolver()
.notifyChange(Uri.parse("content://" + AUTHORITY + "/detail/#"), null);
getContext().getContentResolver()
.notifyChange(Uri.parse("content://" + AUTHORITY + "/details"), null);
getContext().getContentResolver()
.notifyChange(Uri.parse("content://" + AUTHORITY + "/details/master/#"),
null);
getContext().getContentResolver()
.notifyChange(Uri.parse("content://" + AUTHORITY + "/master/#"), null);
getContext().getContentResolver()
.notifyChange(Uri.parse("content://" + AUTHORITY + "/masters"), null);
}
return count;
}
private static final String CONTENT_TYPE_PART_DIR = "vnd.android.cursor.dir/com.gueei" +
".demos.";
private static final String CONTENT_TYPE_PART_ITEM =
"vnd.android.cursor.item/com.gueei" + ".demos.";
public static final String AUTHORITY = "com.gueei.demos";
// URIs constants
private static final int DETAIL_ITEM = 0;
private static final int DETAIL_DIR = 1;
private static final int DETAIL_MASTER_DIR = 2;
private static final int MASTER_ITEM = 3;
private static final int MASTER_DIR = 4;
private static final int RESTORE_ALL = 5;
// Sort Orders
private static final String DETAIL_SORT_ORDER = "detail.masterID ASC,detail._ID ASC";
private static final String MASTER_SORT_ORDER = "master._ID ASC";
// Uri Matcher
private static final UriMatcher sUriMatcher;
// projections
private static HashMap<String, String> sDetailProjectionMap = new HashMap<String, String>();
private static HashMap<String, String> sMasterProjectionMap = new HashMap<String, String>();
static {
sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
sUriMatcher.addURI(AUTHORITY, "detail/#", DETAIL_ITEM);
sUriMatcher.addURI(AUTHORITY, "details", DETAIL_DIR);
sUriMatcher.addURI(AUTHORITY, "details/master/#", DETAIL_MASTER_DIR);
sUriMatcher.addURI(AUTHORITY, "master/#", MASTER_ITEM);
sUriMatcher.addURI(AUTHORITY, "masters", MASTER_DIR);
sUriMatcher.addURI(AUTHORITY, "restore", RESTORE_ALL);
//projection detail
sDetailProjectionMap.put("_ID", "_ID");
sDetailProjectionMap.put("Name", "Name");
sDetailProjectionMap.put("masterID", "masterID");
//projection master
sMasterProjectionMap.put("_ID", "_ID");
sMasterProjectionMap.put("Name", "Name");
sMasterProjectionMap.put("detailsCount", "detailsCount");
}
}