package com.mikifus.padland; 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.DatabaseUtils; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.support.annotation.NonNull; import android.text.TextUtils; import android.util.Log; import com.mikifus.padland.Models.PadGroupModel; import com.mikifus.padland.Models.PadModel; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; /** * The content provider allows to store and read database information for the app. * * TODO: A demo app that connects here * * @author mikifus */ public class PadContentProvider extends ContentProvider { static final String PROVIDER_NAME = "com.mikifus.padland.padlandcontentprovider"; static final String TAG = "PadLandContentProvider"; public static final String AUTHORITY = "content://" + PROVIDER_NAME + "/"; public static final Uri PADLIST_CONTENT_URI = Uri.parse( AUTHORITY + "padlist" ); public static final Uri PADGROUPS_CONTENT_URI = Uri.parse( AUTHORITY + "padgroups" ); /** * Database specific constant declarations */ protected SQLiteDatabase db; public static final int DATABASE_VERSION = 8; public static final String _ID = "_id"; public static final String LOCAL_NAME = "local_name"; // Alias of the pad public static final String SERVER = "server"; // server, might contain the suffix public static final String LAST_USED_DATE = "last_used_date"; // Date the pad was accessed last time public static final String CREATE_DATE = "create_date"; // Date when the pad was added into the app public static final String ACCESS_COUNT = "access_count"; // How many times the document has been accessed in the app public static final String _ID_GROUP = "_id_group"; public static final String _ID_PAD = "_id_pad"; static final int PADLIST = 1; static final int PAD_ID = 2; static final int PADGROUP_LIST = 3; static final int PADGROUP_ID = 4; static final int PADLIST_PADGROUP_ID = 5; private static HashMap<String, String> PROJECTION_MAP; static final UriMatcher uriMatcher; static{ uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI(PROVIDER_NAME, "padlist", PADLIST); uriMatcher.addURI(PROVIDER_NAME, "padlist/#", PAD_ID); uriMatcher.addURI(PROVIDER_NAME, "padgroups", PADGROUP_LIST); uriMatcher.addURI(PROVIDER_NAME, "padgroups/#", PADGROUP_ID); uriMatcher.addURI(PROVIDER_NAME, "padlist_padgroup_id/#", PADLIST_PADGROUP_ID); } public static final String PAD_TABLE_NAME = "padlist"; static final String PAD_TABLE_CREATE_QUERY = " CREATE TABLE " + PAD_TABLE_NAME + " ("+ _ID+" INTEGER PRIMARY KEY AUTOINCREMENT, " + " "+ PadModel.NAME+" TEXT NOT NULL, " + " "+ LOCAL_NAME+" TEXT, " + " "+ SERVER+" TEXT NOT NULL, " + " "+ PadModel.URL+" TEXT NOT NULL, " + " "+ LAST_USED_DATE+ " INTEGER NOT NULL DEFAULT (strftime('%s','now')), " + " "+ CREATE_DATE+ " INTEGER NOT NULL DEFAULT (strftime('%s','now'))," + " "+ ACCESS_COUNT+ " INTEGER NOT NULL DEFAULT 0 "+ ");"; static final String PADGROUP_TABLE_NAME = "padgroups"; static final String PADGROUP_TABLE_CREATE_QUERY = " CREATE TABLE " + PADGROUP_TABLE_NAME + " ("+ _ID+" INTEGER PRIMARY KEY AUTOINCREMENT, " + " "+ PadModel.NAME+" TEXT NOT NULL, " + " "+ PadGroupModel.POSITION + " INTEGER DEFAULT 0, " + " "+ LAST_USED_DATE+ " INTEGER NOT NULL DEFAULT (strftime('%s','now')), " + " "+ CREATE_DATE+ " INTEGER NOT NULL DEFAULT (strftime('%s','now'))," + " "+ ACCESS_COUNT+ " INTEGER NOT NULL DEFAULT 0 "+ ");"; public static final String RELATION_TABLE_NAME = "padlist_padgroups"; static final String RELATION_TABLE_CREATE_QUERY = " CREATE TABLE " + RELATION_TABLE_NAME + " ("+ _ID_GROUP +" INTEGER NOT NULL, " + " " + _ID_PAD +" INTEGER NOT NULL " + ");"; /** * Gets the current time in the format that the database uses. * As it is static, it can be used by other classes. * @return */ public static long getNowDate() { return ((long) new Date().getTime()) / 1000; } /** * Deletes a document from the db * @param uri * @param selection * @param selectionArgs * @return */ @Override public int delete(Uri uri, String selection, String[] selectionArgs) { int count = 0; Log.d("DELETE_QUERY", selection + " - " + selectionArgs.toString()); String id; ArrayList<String> query; switch (uriMatcher.match(uri)){ case PADLIST: Log.d("DELETE_PADLIST", selection + " - " + selectionArgs.toString()); db.delete(RELATION_TABLE_NAME, _ID_PAD + " =?", selectionArgs); count = db.delete(PAD_TABLE_NAME, selection, selectionArgs); break; case PAD_ID: Log.d("DELETE_PAD_ID", selection + " - " + Arrays.toString(selectionArgs)); id = uri.getPathSegments().get(1); query = new ArrayList<>(Arrays.asList(selectionArgs)); query.add(0, id); db.delete(RELATION_TABLE_NAME, _ID_PAD + " = ?", new String[0]); count = db.delete(PAD_TABLE_NAME, _ID + " = ?" + (!TextUtils.isEmpty(selection) ? " AND (?)" : ""), (String[]) query.toArray()); break; case PADGROUP_LIST: Log.d(TAG, "delete_padgroup_list: " + selection + " - " + Arrays.toString(selectionArgs)); db.delete(RELATION_TABLE_NAME, _ID_GROUP + " =?", selectionArgs); count = db.delete(PADGROUP_TABLE_NAME, selection, selectionArgs); break; case PADGROUP_ID: Log.d(TAG, "delete_padgroup_id: " + selection + " - " + Arrays.toString(selectionArgs)); id = uri.getPathSegments().get(1); query = new ArrayList<>(Arrays.asList(selectionArgs)); query.add(0, id); db.delete(RELATION_TABLE_NAME, _ID_GROUP + " = ?", new String[0]); count = db.delete(PADGROUP_TABLE_NAME, _ID + " = ?" + (!TextUtils.isEmpty(selection) ? " AND (?)" : ""), (String[]) query.toArray()); break; default: throw new IllegalArgumentException("Unknown URI " + uri); } getContext().getContentResolver().notifyChange(uri, null); return count; } /** * Updates documents' info. * Returns an int parameter indicating the amount of rows modified. * @param uri * @param values * @param selection * @param selectionArgs * @return */ @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { Log.d("PAD_UPDATE", uri.toString() ); int count; String id; ArrayList<String> query; switch ( uriMatcher.match(uri) ){ case PADLIST: count = db.update(PAD_TABLE_NAME, values, selection, selectionArgs); break; case PAD_ID: id = uri.getPathSegments().get(1); query = new ArrayList<>(Arrays.asList(selectionArgs)); query.add(0, id); count = db.update(PAD_TABLE_NAME, values, _ID + " = ?" + ( !TextUtils.isEmpty(selection) ? " AND (?)" : "" ), (String[]) query.toArray()); break; default: throw new IllegalArgumentException("Unknown URI " + uri ); } getContext().getContentResolver().notifyChange(uri, null); return count; } /** * It does nothing * @param uri * @return */ @Override public String getType(Uri uri) { /* switch (uriMatcher.match(uri)){ default: throw new IllegalArgumentException("Unsupported URI: " + uri); }*/ return null; } /** * Insert into db * @param uri * @param values * @return */ @Override public Uri insert(Uri uri, ContentValues values) { /** * Add a new record */ long rowID; Uri _uri = null; switch (uriMatcher.match(uri)) { case PADLIST: rowID = db.insert(PAD_TABLE_NAME, "", values); ContentUris.withAppendedId(PADLIST_CONTENT_URI, rowID); break; case PADGROUP_LIST: rowID = db.insert(PADGROUP_TABLE_NAME, "", values); ContentUris.withAppendedId(PADGROUPS_CONTENT_URI, rowID); break; default: throw new IllegalArgumentException( "Unknown URI " + uri ); } /** * If record is added successfully */ if (rowID > 0) { // getContext().getContentResolver().notifyChange(_uri, null); return _uri; } throw new SQLException("Failed to add a record into " + uri); } /** * Query to the the db * @param uri * @param projection * @param selection * @param selectionArgs * @param sortOrder * @return */ @Override public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); switch (uriMatcher.match(uri)) { case PADLIST: qb.setTables(PAD_TABLE_NAME); qb.setProjectionMap( PROJECTION_MAP ); break; case PAD_ID: qb.setTables(PAD_TABLE_NAME); qb.appendWhere(_ID + "=" + DatabaseUtils.sqlEscapeString(uri.getPathSegments().get(1))); break; case PADGROUP_LIST: qb.setTables(PADGROUP_TABLE_NAME); qb.setProjectionMap( PROJECTION_MAP ); break; default: throw new IllegalArgumentException( "Unknown URI " + uri ); } if (sortOrder == null || sortOrder.isEmpty()){ /** * By default sort */ sortOrder = LAST_USED_DATE + " DESC "; } Cursor c = qb.query( db, projection, selection, selectionArgs, null, null, sortOrder ); /** * register to watch a content URI for changes */ c.setNotificationUri( getContext().getContentResolver(), uri ); return c; } /** * onCreate override * @return */ @Override public boolean onCreate() { Context context = getContext(); PadlandDbHelper dbHelper = new PadlandDbHelper(context); /** * Create a write able database which will trigger its * creation if it doesn't already exist. */ db = dbHelper.getWritableDatabase(); return (db != null); } public static String[] getPadFieldsList() { return new String[] { _ID, PadModel.NAME, LOCAL_NAME, SERVER, PadModel.URL, LAST_USED_DATE, CREATE_DATE, ACCESS_COUNT }; } public static String[] getPadgroupFieldsList() { return new String[] { _ID, PadModel.NAME, LAST_USED_DATE, CREATE_DATE, ACCESS_COUNT }; } }