/*
* ******************************************************************************
* Copyright (c) 2013-2014 Gabriele Mariotti.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* *****************************************************************************
*/
package it.gmariotti.cardslib.demo.db;
import android.app.SearchManager;
import android.content.ContentProvider;
import android.content.ContentUris;
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 android.util.Log;
import java.util.Arrays;
/**
* @author Gabriele Mariotti (gabri.mariotti@gmail.com)
*/
public class CardCursorProvider extends ContentProvider {
private CardCursorSQLiteOpenHelper myOpenHelper;
private static final String TAG = "CardCursorProvider";
//-----------------------------------------------------------------------------------------------
//private static final String AUTHORITY = Constants.AUTHORITY_QUAKE;
//private static final String BASE_PATH = "quakes";
//public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY+ "/" + BASE_PATH);
//-----------------------------------------------------------------------------------------------
private static final int CardCursor_ALLROWS = 1;
private static final int CardCursor_SINGLE_ROW = 2;
private static final int CardCursor_SEARCH = 3;
// Creates a UriMatcher object.
private static final UriMatcher uriMatcher;
/*
* The calls to addURI() go here, for all of the content URI patterns that the provider
* should recognize. For this snippet, only the calls for messages are shown.
*/
//Populate the UriMatcher object, where a URI ending in 'messages' will
//correspond to a request for all items, and 'messages/[rowID]'
//represents a single row.
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
/*
* Sets the integer value for multiple rows in messages 3 to 1. Notice that no wildcard is used
* in the path
*/
uriMatcher.addURI(CardCursorContract.CONTENT_AUTHORITY, CardCursorContract.BASE_PATH_NAME.PATH_CardCursor, CardCursor_ALLROWS);
/*
* Sets the code for a single row to 2. In this case, the "#" wildcard is
* used. "content://com.example.mesmessage.db/messages/3" matches, but
* "content://com.example.mesmessage.db/messages doesn't.
*/
uriMatcher.addURI(CardCursorContract.CONTENT_AUTHORITY, CardCursorContract.BASE_PATH_NAME.PATH_CardCursor +"/#", CardCursor_SINGLE_ROW);
//TODO
uriMatcher.addURI(CardCursorContract.CONTENT_AUTHORITY,
SearchManager.SUGGEST_URI_PATH_QUERY, CardCursor_SEARCH);
uriMatcher.addURI(CardCursorContract.CONTENT_AUTHORITY,
SearchManager.SUGGEST_URI_PATH_QUERY + "/*", CardCursor_SEARCH);
uriMatcher.addURI(CardCursorContract.CONTENT_AUTHORITY,
SearchManager.SUGGEST_URI_PATH_SHORTCUT, CardCursor_SEARCH);
uriMatcher.addURI(CardCursorContract.CONTENT_AUTHORITY,
SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", CardCursor_SEARCH);
}
@Override
public String getType(Uri uri) {
// Return a string that identifies the MIME type
// for a Content Provider URI
switch (uriMatcher.match(uri)) {
//Type part: vnd
//Subtype part:
//If the URI pattern is for a single row: android.cursor.item/
//If the URI pattern is for more than one row: android.cursor.dir/
//Provider-specific part: vnd.<name>.<type>
//You supply the <name> and <type>. The <name> value should be globally unique,
//and the <type> value should be unique to the corresponding URI pattern.
//A good choice for <name> is your company's name or some part of your application's
//Android package name. A good choice for the <type> is a string that identifies the table associated with the URI.
case CardCursor_ALLROWS: return CardCursorContract.CardCursor.CONTENT_TYPE;
case CardCursor_SINGLE_ROW: return CardCursorContract.CardCursor.CONTENT_ITEM_TYPE;
case CardCursor_SEARCH : return SearchManager.SUGGEST_MIME_TYPE;
default: throw new IllegalArgumentException("Unsupported URI: " + uri);
}
}
//-----------------------------------------------------------------------------------------------
@Override
public boolean onCreate() {
// Construct the underlying database.
// Defer opening the database until you need to perform
// a query or transaction.
myOpenHelper = new CardCursorSQLiteOpenHelper(getContext(),
CardCursorSQLiteOpenHelper.DATABASE_NAME, null,
CardCursorSQLiteOpenHelper.DATABASE_VERSION);
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
Log.d(TAG, "query(uri=" + uri + ", proj=" + Arrays.toString(projection) + ")");
// Open a read-only database.
SQLiteDatabase db = myOpenHelper.getWritableDatabase();
// Replace these with valid SQL statements if necessary.
String groupBy = null;
String having = null;
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
String rowID="";
// If this is a row query, limit the result set to the passed in row.
switch (uriMatcher.match(uri)) {
case CardCursor_SINGLE_ROW :
queryBuilder.setTables(CardCursorSQLiteOpenHelper.Tables.CardCursor);
rowID = uri.getPathSegments().get(1);
queryBuilder.appendWhere(CardCursorContract.CardCursor.KeyColumns.KEY_ID + "=" + rowID);
break;
case CardCursor_ALLROWS :
queryBuilder.setTables(CardCursorSQLiteOpenHelper.Tables.CardCursor);
if (TextUtils.isEmpty(sortOrder)) {
sortOrder = CardCursorContract.CardCursor.DEFAULT_SORT;
}
break;
default:
throw new IllegalArgumentException(
"Unsupported URI: " + uri);
}
Cursor cursor = queryBuilder.query(db, projection, selection,
selectionArgs, groupBy, having, sortOrder);
// Make sure that potential listeners are getting notified
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
Log.d(TAG, "insert(uri=" + uri + ", values=" + values.toString() + ")");
// Open a read / write database to support the transaction.
SQLiteDatabase db = myOpenHelper.getWritableDatabase();
// To add empty rows to your database by passing in an empty Content Values
// object, you must use the null column hack parameter to specify the name of
// the column that can be set to null.
String nullColumnHack = null;
long id=-1;
if (uriMatcher.match(uri) == CardCursor_ALLROWS) {
// Insert the values into the table
id = db.insert(CardCursorSQLiteOpenHelper.Tables.CardCursor, nullColumnHack, values);
}
if (id > -1) {
// Construct and return the URI of the newly inserted row.
// Equals to Uri.parse(BASE_PATH + "/" + id);
Uri insertedId = ContentUris.withAppendedId(uri, id);
// Notify any observers of the change in the data set.
getContext().getContentResolver().notifyChange(insertedId, null);
return insertedId;
}
else
throw new SQLException(
"Problem while inserting into uri: " + uri);
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
Log.d(TAG, "delete(uri=" + uri + ")");
// Open a read / write database to support the transaction.
SQLiteDatabase db = myOpenHelper.getWritableDatabase();
String rowID="";
int deleteCount=0;
// If this is a row URI, limit the deletion to the specified row.
switch (uriMatcher.match(uri)) {
case CardCursor_ALLROWS:
deleteCount = db.delete(
CardCursorSQLiteOpenHelper.Tables.CardCursor,
selection,
selectionArgs);
break;
case CardCursor_SINGLE_ROW :
rowID = uri.getPathSegments().get(1);
selection = CardCursorContract.CardCursor.KeyColumns.KEY_ID + "=" + rowID
+ (!TextUtils.isEmpty(selection) ?
" AND (" + selection + ')' : "");
deleteCount = db.delete(CardCursorSQLiteOpenHelper.Tables.CardCursor, selection, selectionArgs);
break;
default:
throw new IllegalArgumentException("Unsupported URI: " + uri);
}
// To return the number of deleted items, you must specify a where
// clause. To delete all rows and return a value, pass in "1".
//if (selection == null)
// selection = "1";
if (deleteCount > 0) {
// Notify any observers of the change in the data set.
getContext().getContentResolver().notifyChange(uri, null);
}
return deleteCount;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
Log.d(TAG, "update(uri=" + uri + ", values=" + values.toString() + ")");
// Open a read / write database to support the transaction.
SQLiteDatabase db = myOpenHelper.getWritableDatabase();
String rowID="";
int updateCount=0;
// If this is a row URI, limit the deletion to the specified row.
switch (uriMatcher.match(uri)) {
case CardCursor_SINGLE_ROW :
rowID = uri.getPathSegments().get(1);
selection = CardCursorContract.CardCursor.KeyColumns.KEY_ID + "=" + rowID
+ (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : "");
updateCount = db.update(CardCursorSQLiteOpenHelper.Tables.CardCursor,
values, selection, selectionArgs);
break;
default:
throw new IllegalArgumentException("Unsupported URI: " + uri);
}
if (updateCount>0){
// Notify any observers of the change in the data set.
getContext().getContentResolver().notifyChange(uri, null);
}
return updateCount;
}
//---------------------------------------------------------------------------------------------------------------------
private static class CardCursorSQLiteOpenHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "cardDemoDatabase.db";
interface Tables {
String CardCursor = CardCursorContract.CardCursor.TABLE_NAME;
}
private static final int DATABASE_VERSION = 1;
//private static final String DATABASE_TABLE = CardCursorContract.CardCursor.TABLE_NAME;
public CardCursorSQLiteOpenHelper(Context context, String name,
SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
// Called when no database exists in disk and the helper class needs
// to create a new one.
@Override
public void onCreate(SQLiteDatabase database) {
CardCursorContract.CardCursor.onCreate(database);
}
// Called when there is a database version mismatch, meaning that the version
// of the database on disk needs to be upgraded to the current version.
@Override
public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) {
CardCursorContract.CardCursor.onUpgrade(database, oldVersion, newVersion);
}
}
}