package org.moca.provider;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import org.moca.db.MocaDB.DatabaseHelper;
import org.moca.provider.MetaData.Info;
import android.content.ContentProvider;
import android.content.ContentResolver;
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.SQLiteQueryBuilder;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.text.TextUtils;
import android.util.Log;
/**
* Abstract ContentProvider for handling content that is written to files.
*
* @author Eric Winkler
*
*/
public abstract class BaseContentProvider extends ContentProvider
{
protected static String TAG = "BaseContentProvider";
public static final int ITEMS = 1;
public static final int ITEM_ID = 2;
// handle interactions with the database
private static HashMap<String,String> sProjectionMap;
// Initialize these in onCreate() of extending classes
protected DatabaseHelper mOpenHelper;
protected Info content;
/** The file prefix */
protected String prefix;
protected String thumbPrefix;
/** The table name */
protected String tableName;
/** Returns the classes static UriMatcher */
abstract protected UriMatcher uriMatcher();
/** Returns the directory of the providers files */
abstract protected File getFilesDir();
/** Generates a file name and absolute path from an id */
protected String buildFilenameFromId(String id) {
return getFilesDir().getAbsolutePath()+"/"+prefix + id;
}
/** Generates a file name and absolute path from a Uri */
protected String buildFilenameFromUri(Uri uri) {
return buildFilenameFromId(uri.getPathSegments().get(1));
}
/** Deletes the file with the specified id */
protected boolean deleteFile(String id) {
String filename = buildFilenameFromId(id);
File f = new File(filename);
boolean result = f.delete();
Log.d(TAG, "Deleting file for id " + id + " : " + filename + " " +
(result ? "succeeded" : "failed"));
return result;
}
/** Deletes the file at the specified Uri */
protected boolean deleteFile(Uri uri) {
String filename = buildFilenameFromUri(uri);
File f = new File(filename);
boolean result = f.delete();
Log.d(TAG, "Deleting file for " + uri + " : " + filename + " " +
(result ? "succeeded" : "failed"));
return result;
}
/**
* {@inheritDoc}
*/
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws
FileNotFoundException
{
String filename = "";
File f;
if(uri.getScheme().equals(ContentResolver.SCHEME_FILE)){
filename = uri.getPath();
} else {
filename = buildFilenameFromUri(uri);
}
f = new File(filename);
Log.d(TAG, "openFile() for filename: " + filename);
int m = ParcelFileDescriptor.MODE_READ_ONLY;
if ("w".equals(mode)) {
m = ParcelFileDescriptor.MODE_WRITE_ONLY |
ParcelFileDescriptor.MODE_CREATE;
} else if("rw".equals(mode)) {
m = ParcelFileDescriptor.MODE_READ_WRITE |
ParcelFileDescriptor.MODE_CREATE;
} else if("rwt".equals(mode)){
m = ParcelFileDescriptor.MODE_READ_WRITE |
ParcelFileDescriptor.MODE_CREATE |
ParcelFileDescriptor.MODE_TRUNCATE;
}
return ParcelFileDescriptor.open(f,m);
}
/**
* {@inheritDoc}
*/
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
Log.d(TAG, "query() uri="+uri.toString() + " projection=" +
TextUtils.join(",",projection));
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(tableName);
switch(uriMatcher().match(uri)) {
case ITEMS:
break;
case ITEM_ID:
qb.appendWhere(ContentColumns._ID+"="+uri.getPathSegments().get(1));
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
String orderBy;
if(TextUtils.isEmpty(sortOrder)) {
orderBy = content.getData(MetaData.Flag.SORT_ORDER);
} else {
orderBy = sortOrder;
}
SQLiteDatabase db = mOpenHelper.getReadableDatabase();
Cursor c = qb.query(db, projection, selection, selectionArgs, null,
null, orderBy);
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}
/**
* {@inheritDoc}
*/
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
int count = 0;
switch(uriMatcher().match(uri)) {
case ITEMS:
count = db.update(tableName, values,selection,selectionArgs);
break;
case ITEM_ID:
String procedureId = uri.getPathSegments().get(1);
count = db.update(tableName, values, ContentColumns._ID + "="
+ procedureId +
(!TextUtils.isEmpty(selection) ?
" AND (" + selection + ")" : ""),selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
/**
* {@inheritDoc}
*/
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
int count;
switch (uriMatcher().match(uri)) {
case ITEMS:
LinkedList<String> idList = new LinkedList<String>();
Cursor c = query(content.contentUri(),
new String[] { ContentColumns._ID }, selection,
selectionArgs, null);
if(c.moveToFirst()) {
while(!c.isAfterLast()) {
String id = c.getString(c.getColumnIndex(
ContentColumns._ID));
idList.add(id);
c.moveToNext();
}
}
c.close();
for(String id : idList) {
deleteFile(id);
}
count = db.delete(tableName, selection, selectionArgs);
break;
case ITEM_ID:
String id = uri.getPathSegments().get(1);
deleteFile(uri);
count = db.delete(tableName, ContentColumns._ID + "=" +
id + (!TextUtils.isEmpty(selection) ? " AND (" +
selection + ")" : ""), selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
/**
* {@inheritDoc}
*/
@Override
public Uri insert(Uri uri, ContentValues initialValues) {
if (uriMatcher().match(uri) != ITEMS) {
throw new IllegalArgumentException("Unknown URI " + uri);
}
ContentValues values;
if(initialValues != null) {
values = new ContentValues(initialValues);
} else {
values = new ContentValues();
}
Long now = Long.valueOf(System.currentTimeMillis());
if(values.containsKey(ContentColumns.ELEMENT_ID) == false) {
values.put(ContentColumns.ELEMENT_ID, "");
}
if(values.containsKey(ContentColumns.FILE_VALID) == false) {
values.put(ContentColumns.FILE_VALID, false);
}
if(values.containsKey(ContentColumns.PROCEDURE) == false) {
values.put(ContentColumns.PROCEDURE, "");
}
if(values.containsKey(ContentColumns.UPLOAD_PROGRESS) == false) {
values.put(ContentColumns.UPLOAD_PROGRESS, 0);
}
if(values.containsKey(ContentColumns.UPLOADED) == false) {
values.put(ContentColumns.UPLOADED, false);
}
if(values.containsKey(ContentColumns.THUMB_DATA) == false) {
values.put(ContentColumns.THUMB_DATA, "");
}
// MediaStore columns
if(values.containsKey(ContentColumns.DATA) == false) {
values.put(ContentColumns.DATA, "");
}
if(values.containsKey(ContentColumns.DATE_ADDED) == false) {
values.put(ContentColumns.DATE_ADDED, now);
}
if(values.containsKey(ContentColumns.DATE_MODIFIED) == false) {
values.put(ContentColumns.DATE_MODIFIED, now);
}
if(values.containsKey(ContentColumns.DISPLAY_NAME) == false) {
values.put(ContentColumns.DISPLAY_NAME, "");
}
if(values.containsKey(ContentColumns.MIME_TYPE) == false) {
values.put(ContentColumns.MIME_TYPE, content.getData(
MetaData.Flag.MIME_TYPE));
}
if(values.containsKey(ContentColumns.SIZE) == false) {
values.put(ContentColumns.SIZE, 0);
}
if(values.containsKey(ContentColumns.TITLE) == false) {
values.put(ContentColumns.TITLE, "");
}
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
long rowId = db.insert(tableName,
ContentColumns.PROCEDURE, values);
if(rowId > 0) {
String filename = prefix + rowId;
try {
getContext().openFileOutput(filename, Context.MODE_PRIVATE)
.close();
} catch (FileNotFoundException e) {
Log.e(TAG, "Couldn't make the file: " + e);
} catch (IOException e) {
Log.e(TAG, "Couldn't make the file: " + e);
}
Uri noteUri = ContentUris.withAppendedId(content.contentUri(),
rowId);
getContext().getContentResolver().notifyChange(noteUri, null);
return noteUri;
}
throw new SQLException("Failed to insert row into " + uri);
}
/**
* Creates the File in the application's directory structure
*
* @param id
*/
protected void createFile(long id)
{
String filename = prefix + id;
try {
getContext().openFileOutput(filename, Context.MODE_PRIVATE)
.close();
} catch (FileNotFoundException e) {
Log.e(TAG, "Couldn't make the file: " + e);
} catch (IOException e) {
Log.e(TAG, "Couldn't make the file: " + e);
}
}
/**
* {@inheritDoc}
*/
@Override
public String getType(Uri uri) {
Log.d(TAG, "getType(uri="+uri.toString()+")");
switch(uriMatcher().match(uri)) {
case ITEMS:
return content.getData(MetaData.Flag.CONTENT_TYPE);
case ITEM_ID:
return content.getData(MetaData.Flag.CONTENT_ITEM_TYPE);
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
}
/**
* Utility method for generating a UriMatcher for a given authority and
* table
*
* @param authority the ContentProvider authority
* @param table the table name
* @return
*/
protected static UriMatcher createUriMatcher(String authority, String table)
{
UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
sUriMatcher.addURI(authority, table, ITEMS);
sUriMatcher.addURI(authority, table + "/#", ITEM_ID);
return sUriMatcher;
}
/**
* Creates the table in a SQLLite database
*
* @param db the database to create the table in
* @param table the table name
*/
public static void onCreateDatabase(SQLiteDatabase db, String table) {
Log.d(TAG, "Creating Table " + table);
db.execSQL("CREATE TABLE " + table + " ("
+ ContentColumns._ID + " INTEGER PRIMARY KEY,"
+ ContentColumns.ELEMENT_ID + " TEXT,"
+ ContentColumns.FILE_VALID + " INTEGER,"
+ ContentColumns.PROCEDURE + " TEXT,"
+ ContentColumns.UPLOAD_PROGRESS + " INTEGER,"
+ ContentColumns.UPLOADED + " INTEGER,"
+ ContentColumns.THUMB_DATA + " TEXT,"
+ ContentColumns.DATA + " TEXT,"
+ ContentColumns.DATE_ADDED + " INTEGER,"
+ ContentColumns.DATE_MODIFIED + " INTEGER,"
+ ContentColumns.DISPLAY_NAME + " TEXT,"
+ ContentColumns.MIME_TYPE + " TEXT,"
+ ContentColumns.SIZE + " INTEGER,"
+ ContentColumns.TITLE + " TEXT"
+ ");");
}
/**
* Drops and then creates the table in a database
*
* @param db the database to drop and create in
* @param table the table name
*/
public static void recreateDatabase(SQLiteDatabase db, String table)
{
db.execSQL("DROP TABLE IF EXISTS " + table);
onCreateDatabase(db, table);
}
}
|