/*
* RapidPro Android Channel - Relay SMS messages where MNO connections aren't practical.
* Copyright (C) 2014 Nyaruka, UNICEF
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.rapidpro.androidchannel.contentprovider;
import java.util.Arrays;
import java.util.HashSet;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
import io.rapidpro.androidchannel.data.DBCommandHelper;
public class DBCommandContentProvider extends ContentProvider {
// m_db
private DBCommandHelper m_db;
// Used for the UriMacher
private static final int CMDS = 10;
private static final int CMD_ID = 20;
private static final String AUTHORITY = "io.rapidpro.androidchannel.commands";
private static final String BASE_PATH = "cmds";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH);
public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE + "/" + BASE_PATH;
public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/" + BASE_PATH;
private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
sURIMatcher.addURI(AUTHORITY, BASE_PATH, CMDS);
sURIMatcher.addURI(AUTHORITY, BASE_PATH + "/#", CMD_ID);
}
@Override
public boolean onCreate() {
m_db = new DBCommandHelper(getContext());
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// Using SQLiteQueryBuilder instead of query() method
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
// Check if the caller has requested a column which does not exists
checkColumns(projection);
// Set the table
queryBuilder.setTables(DBCommandHelper.TABLE);
int uriType = sURIMatcher.match(uri);
switch (uriType) {
case CMDS:
break;
case CMD_ID:
// Adding the ID to the original query
queryBuilder.appendWhere(DBCommandHelper.COL_ID + "=" + uri.getLastPathSegment());
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
SQLiteDatabase db = m_db.getReadableDatabase();
Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder);
return cursor;
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
int uriType = sURIMatcher.match(uri);
SQLiteDatabase db = m_db.getWritableDatabase();
long id = 0;
try {
switch (uriType) {
case CMDS:
id = db.insert(DBCommandHelper.TABLE, null, values);
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return Uri.parse(BASE_PATH + "/" + id);
} finally {
//db.close();
}
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int uriType = sURIMatcher.match(uri);
SQLiteDatabase db = m_db.getWritableDatabase();
int rowsDeleted = 0;
try{
switch (uriType) {
case CMDS:
rowsDeleted = db.delete(DBCommandHelper.TABLE, selection, selectionArgs);
break;
case CMD_ID:
String id = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection)) {
rowsDeleted = db.delete(DBCommandHelper.TABLE, DBCommandHelper.COL_ID + "=" + id, null);
} else {
rowsDeleted = db.delete(DBCommandHelper.TABLE,
DBCommandHelper.COL_ID + "=" + id + " and " + selection, selectionArgs);
}
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return rowsDeleted;
} finally {
//db.close();
}
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
int uriType = sURIMatcher.match(uri);
SQLiteDatabase db = m_db.getWritableDatabase();
int rowsUpdated = 0;
try{
switch (uriType) {
case CMDS:
rowsUpdated = db.update(DBCommandHelper.TABLE,
values,
selection,
selectionArgs);
break;
case CMD_ID:
String id = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection)) {
rowsUpdated = db.update(DBCommandHelper.TABLE,
values,
DBCommandHelper.COL_ID + "=" + id,
null);
} else {
rowsUpdated = db.update(DBCommandHelper.TABLE,
values,
DBCommandHelper.COL_ID + "=" + id
+ " and "
+ selection,
selectionArgs);
}
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return rowsUpdated;
} finally {
//db.close();
}
}
private void checkColumns(String[] projection) {
if (projection != null) {
if (projection.length == 1 && projection[0].equals("count(*)")) {
return;
}
HashSet<String> requestedColumns = new HashSet<String>(Arrays.asList(projection));
HashSet<String> availableColumns = new HashSet<String>(Arrays.asList(DBCommandHelper.ALL_COLS));
// Check if all columns which are requested are available
if (!availableColumns.containsAll(requestedColumns)) {
throw new IllegalArgumentException("Unknown columns in projection");
}
}
}
}