/*
* Copyright (C) 2012, Katy Hilgenberg.
* Special acknowledgments to: Knowledge & Data Engineering Group, University of Kassel (http://www.kde.cs.uni-kassel.de).
* Contact: sdcf@cs.uni-kassel.de
*
* This file is part of the SDCFramework (Sensor Data Collection Framework) project.
*
* The SDCFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The SDCFramework 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the SDCFramework. If not, see <http://www.gnu.org/licenses/>.
*/
package de.unikassel.android.sdcframework.provider;
import java.util.HashMap;
import de.unikassel.android.sdcframework.provider.facade.ContentProviderData;
import de.unikassel.android.sdcframework.util.TimeInformation;
import de.unikassel.android.sdcframework.util.TimeProvider;
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.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
/**
* @author Katy Hilgenberg
*
*/
public abstract class AbstractProvider extends ContentProvider
{
/**
* The internal SQLite helper class
*
* @author Katy Hilgenberg
*
*/
private class DatabaseHelper extends SQLiteOpenHelper
{
/**
* Constructor
*
* @param context
* the context
*/
DatabaseHelper( Context context )
{
super( context, providerData.getDBName(), null,
providerData.getDBVersion() );
}
/*
* (non-Javadoc)
*
* @see
* android.database.sqlite.SQLiteOpenHelper#onCreate(android.database.sqlite
* .SQLiteDatabase)
*/
@Override
public final void onCreate( SQLiteDatabase db )
{
db.execSQL( providerData.getCreateTableStatement() );
}
/*
* (non-Javadoc)
*
* @see
* android.database.sqlite.SQLiteOpenHelper#onUpgrade(android.database.sqlite
* .SQLiteDatabase, int, int)
*/
@Override
public final void onUpgrade( SQLiteDatabase db, int oldVersion,
int newVersion )
{
// for the moment we do know just one version
}
}
/**
* Projection map for the column names
*/
private final HashMap< String, String > projectionMap;
/**
* The internal URI matcher
*/
private final UriMatcher uriMatcher;
/**
* The content provider related data
*/
private final ContentProviderData providerData;
/**
* The content resolver
*/
private ContentResolver resolver;
/**
* The item uri identifier
*/
private final static int SINGLE_ITEM = 1;
/**
* The directory uri identifier
*/
private final static int DIRECTORY = 0;
/**
* The internally used database helper
*/
private DatabaseHelper dbHelper;
/**
* Constructor
*
* @param providerData
* the provider data
*/
public AbstractProvider( ContentProviderData providerData )
{
this.providerData = providerData;
uriMatcher = new UriMatcher( UriMatcher.NO_MATCH );
uriMatcher.addURI( providerData.getAuthority(),
providerData.getContentTypeName(), DIRECTORY );
uriMatcher.addURI( providerData.getAuthority(),
providerData.getContentTypeName() + "/*", SINGLE_ITEM );
projectionMap = providerData.getProjectionMap();
}
/**
* Getter for the provider data
*
* @return the provider data
*/
public final ContentProviderData getProviderData()
{
return providerData;
}
/**
* Getter for the database helper
*
* @return the database helper
*/
public final SQLiteOpenHelper getDbHelper()
{
return dbHelper;
}
/*
* (non-Javadoc)
*
* @see android.content.ContentProvider#onCreate()
*/
@Override
public final boolean onCreate()
{
Context context = getContext();
resolver = context.getContentResolver();
dbHelper = new DatabaseHelper( context );
return true;
}
/*
* (non-Javadoc)
*
* @see android.content.ContentProvider#query(android.net.Uri,
* java.lang.String[], java.lang.String, java.lang.String[], java.lang.String)
*/
@Override
public final Cursor query( Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder )
{
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables( providerData.getDBTableName() );
qb.setProjectionMap( projectionMap );
int match = uriMatcher.match( uri );
switch ( match )
{
case DIRECTORY:
{
// just query all
break;
}
case SINGLE_ITEM:
{
String id = uri.getLastPathSegment();
qb.appendWhere( projectionMap.get( ContentProviderData._ID ) + "=" + id );
break;
}
default:
{
throw new IllegalArgumentException( "Unknown URI " + uri );
}
}
SQLiteDatabase db = dbHelper.getReadableDatabase();
Cursor c =
qb.query( db, projection, selection, selectionArgs, null, null,
sortOrder );
c.setNotificationUri( resolver, uri );
return c;
}
/*
* (non-Javadoc)
*
* @see android.content.ContentProvider#getType(android.net.Uri)
*/
@Override
public final String getType( Uri uri )
{
int match = uriMatcher.match( uri );
switch ( match )
{
case DIRECTORY:
{
return providerData.getContentType();
}
case SINGLE_ITEM:
{
return providerData.getContentItemType();
}
}
throw new IllegalArgumentException( "Unknown URI " + uri );
}
/*
* (non-Javadoc)
*
* @see android.content.ContentProvider#insert(android.net.Uri,
* android.content.ContentValues)
*/
@Override
public final Uri insert( Uri uri, ContentValues values )
{
int match = uriMatcher.match( uri );
switch ( match )
{
case DIRECTORY:
{
if ( values != null )
{
SQLiteDatabase db = dbHelper.getWritableDatabase();
if ( TimeProvider.getInstance().isSynced() )
{
// due to the new time provider feature we do override the time
// information here!
values.remove( ContentProviderData.TIMESTAMP );
TimeInformation ti =
TimeProvider.getInstance().getAccurateTimeInformation();
values.put( ContentProviderData.TIMESTAMP,
Long.toString( ti.ts ) );
values.remove( ContentProviderData.SYNCED );
values.put( ContentProviderData.SYNCED, ti.synced ? 1 : 0 );
}
long rowId =
db.insert( providerData.getDBTableName(),
ContentProviderData.TIMESTAMP,
values );
if ( rowId > 0 )
{
Uri noteUri =
ContentUris.withAppendedId( providerData.getContentUri(), rowId );
resolver.notifyChange( noteUri, null );
return noteUri;
}
}
throw new SQLException( "Failed to insert data into " + uri );
}
default:
{
// any URI but the one for the table itself is invalid
throw new IllegalArgumentException( "Invalid URI " + uri );
}
}
}
/*
* (non-Javadoc)
*
* @see android.content.ContentProvider#delete(android.net.Uri,
* java.lang.String, java.lang.String[])
*/
@Override
public final int delete( Uri uri, String selection, String[] selectionArgs )
{
SQLiteDatabase db = dbHelper.getWritableDatabase();
int count;
int match = uriMatcher.match( uri );
switch ( match )
{
case DIRECTORY:
{
if ( TextUtils.isEmpty( selection ) )
{
// we have to delete all rows in the table
selection = "1";
}
break;
}
case SINGLE_ITEM:
{
// selective deletion
String id = uri.getLastPathSegment();
String sConstraint = ContentProviderData._ID + "=" + id;
if ( TextUtils.isEmpty( selection ) )
{
selection = sConstraint;
}
else
{
selection = selection + " and " + sConstraint;
}
break;
}
default:
{
throw new IllegalArgumentException( "Unknown URI " + uri );
}
}
count = db.delete( providerData.getDBTableName(), selection, selectionArgs );
resolver.notifyChange( uri, null );
return count;
}
/*
* (non-Javadoc)
*
* @see android.content.ContentProvider#update(android.net.Uri,
* android.content.ContentValues, java.lang.String, java.lang.String[])
*/
@Override
public final int update( Uri uri, ContentValues values, String selection,
String[] selectionArgs )
{
SQLiteDatabase db = dbHelper.getWritableDatabase();
int count;
int match = uriMatcher.match( uri );
switch ( match )
{
case DIRECTORY:
{
break;
}
case SINGLE_ITEM:
{
// selective deletion
String id = uri.getLastPathSegment();
String sConstraint = ContentProviderData._ID + "=" + id;
if ( TextUtils.isEmpty( selection ) )
{
selection = sConstraint;
}
else
{
selection = selection + " and " + sConstraint;
}
break;
}
default:
{
throw new IllegalArgumentException( "Unknown URI " + uri );
}
}
count =
db.update( providerData.getDBTableName(), values, selection,
selectionArgs );
resolver.notifyChange( uri, null );
return count;
}
}