com.weebly.opus1269.copyeverywhere.model.ClipContentProvider.java Source code

Java tutorial

Introduction

Here is the source code for com.weebly.opus1269.copyeverywhere.model.ClipContentProvider.java

Source

/*
 * Copyright 2016 Michael A Updike
 *
 *  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 com.weebly.opus1269.copyeverywhere.model;

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.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;

import com.weebly.opus1269.copyeverywhere.BuildConfig;
import com.weebly.opus1269.copyeverywhere.helpers.App;
import com.weebly.opus1269.copyeverywhere.ui.settings.Prefs;

import org.joda.time.DateTime;

/**
 * App private {@link ContentProvider} for the saved {@link ClipItem}
 */
@SuppressWarnings({ "ConstantConditions", "resource" })
public class ClipContentProvider extends ContentProvider {
    private static final String TAG = "ClipContentProvider";

    private static final String UNKNOWN_URI = "Unknown URI: ";

    // used for the UriMatcher
    private static final int CLIP = 10;
    private static final int CLIP_ID = 20;
    private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);

    static {
        URI_MATCHER.addURI(ClipContract.AUTHORITY, "clip", CLIP);
        URI_MATCHER.addURI(ClipContract.AUTHORITY, "clip/#", CLIP_ID);
    }

    /**
     * Add the contents of the ClipItem to the clipboard, optionally only if item text is new
     *
     * @param context   a {@link Context}
     * @param clipItem the {@link ClipItem} to insert
     * @param onNewOnly only insert if item text is not in database if true
     * @return boolean true if inserted
     */
    public static boolean insert(Context context, ClipItem clipItem, Boolean onNewOnly) {
        if ((clipItem == null) || TextUtils.isEmpty(clipItem.getText())) {
            return false;
        }

        if (onNewOnly) {
            // query for existence and skip insert if it does
            final String[] projection = { ClipContract.Clip.COL_TEXT };
            final String selection = "(" + ClipContract.Clip.COL_TEXT + " == ? )";
            final String[] selectionArgs = { clipItem.getText() };

            final Cursor cursor = context.getContentResolver().query(ClipContract.Clip.CONTENT_URI, projection,
                    selection, selectionArgs, null);
            if (cursor.getCount() != 0) {
                // already in database, we are done
                cursor.close();
                return false;

            }
            cursor.close();
        }

        // do it
        insert(context, clipItem);

        return true;
    }

    public static Uri insert(Context context, ClipItem item) {
        return context.getContentResolver().insert(ClipContract.Clip.CONTENT_URI, item.getContentValues());
    }

    public static int insert(Context context, ContentValues[] items) {
        return context.getContentResolver().bulkInsert(ClipContract.Clip.CONTENT_URI, items);
    }

    /**
     * Get the non-favorite and optionally favorite rows in the database
     *
     * @param context     our {@link Context}
     * @param includeFavs flag to indicate if favorites should be retrieved too
     * @return Array of {@link ContentValues}
     */
    public static ContentValues[] getAll(Context context, Boolean includeFavs) {
        final String[] projection = ClipContract.Clip.FULL_PROJECTION;

        // Select all non-favorites
        String selection = "(" + ClipContract.Clip.COL_FAV + " == 0 " + ")";

        if (includeFavs) {
            // select all favorites too
            selection = selection + " OR (" + ClipContract.Clip.COL_FAV + " == 1 )";
        }

        final Cursor cursor = context.getContentResolver().query(ClipContract.Clip.CONTENT_URI, projection,
                selection, null, null);
        final ContentValues[] array = new ContentValues[cursor.getCount()];
        int count = 0;
        while (cursor.moveToNext()) {
            //noinspection ObjectAllocationInLoop
            final ContentValues cv = new ContentValues();
            cv.put(ClipContract.Clip.COL_TEXT, cursor.getString(cursor.getColumnIndex(ClipContract.Clip.COL_TEXT)));
            cv.put(ClipContract.Clip.COL_DATE, cursor.getLong(cursor.getColumnIndex(ClipContract.Clip.COL_DATE)));
            cv.put(ClipContract.Clip.COL_FAV, cursor.getLong(cursor.getColumnIndex(ClipContract.Clip.COL_FAV)));
            cv.put(ClipContract.Clip.COL_REMOTE,
                    cursor.getLong(cursor.getColumnIndex(ClipContract.Clip.COL_REMOTE)));
            cv.put(ClipContract.Clip.COL_DEVICE,
                    cursor.getString(cursor.getColumnIndex(ClipContract.Clip.COL_DEVICE)));
            array[count] = cv;
            count++;
        }
        cursor.close();

        return array;
    }

    /**
     * Delete all non-favorite and optionally favorite rows
     *
     * @param context    a context
     * @param deleteFavs flag to indicate if favorites should be deleted
     * @return Number of rows deleted
     */
    public static int deleteAll(Context context, Boolean deleteFavs) {
        // Select all non-favorites
        String selection = "(" + ClipContract.Clip.COL_FAV + " == 0 " + ")";

        if (deleteFavs) {
            // select all favorites too
            selection = selection + " OR (" + ClipContract.Clip.COL_FAV + " == 1 )";
        }

        return context.getContentResolver().delete(ClipContract.Clip.CONTENT_URI, selection, null);
    }

    /**
     * Delete rows older than the storage duration
     *
     * @return Number of rows deleted
     */
    @SuppressWarnings("CallToStringEquals")
    public static int deleteOldItems() {
        final String value = Prefs.getDuration();
        if (value.equals(Prefs.DEFAULT_DURATION)) {
            return 0;
        }

        final Context context = App.getContext();
        DateTime today = DateTime.now();
        today = today.withTimeAtStartOfDay();
        DateTime deleteDate = today;
        switch (value) {
        case "day":
            deleteDate = deleteDate.minusDays(1);
            break;
        case "week":
            deleteDate = deleteDate.minusWeeks(1);
            break;
        case "month":
            deleteDate = deleteDate.minusMonths(1);
            break;
        case "year":
            deleteDate = deleteDate.minusYears(1);
            break;
        default:
            return 0;
        }

        final long deleteTime = deleteDate.getMillis();

        // Select all non-favorites older than the calculated time
        final String selection = "(" + ClipContract.Clip.COL_FAV + " == 0 " + ")" + " AND ("
                + ClipContract.Clip.COL_DATE + " < " + deleteTime + ")";

        return context.getContentResolver().delete(ClipContract.Clip.CONTENT_URI, selection, null);
    }

    @Override
    public boolean onCreate() {
        return true;
    }

    @Override
    public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs,
            String sortOrder) {

        String newSelection = selection;
        String newSortOrder = sortOrder;
        final SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();

        final int uriType = URI_MATCHER.match(uri);
        switch (uriType) {
        case CLIP:
            queryBuilder.setTables(ClipContract.Clip.TABLE_NAME);
            if (TextUtils.isEmpty(sortOrder)) {
                newSortOrder = ClipContract.Clip.DEFAULT_SORT_ORDER;
            }
            break;
        case CLIP_ID:
            queryBuilder.setTables(ClipContract.Clip.TABLE_NAME);
            if (TextUtils.isEmpty(sortOrder)) {
                newSortOrder = ClipContract.Clip.DEFAULT_SORT_ORDER;
            }
            /*
             * Because this URI was for a single row, the _ID value part is
             * present. Get the last path segment from the URI; this is the _ID value.
             * Then, append the value to the WHERE clause for the query
             */
            newSelection = newSelection + "and _ID = " + uri.getLastPathSegment();
            break;
        default:
            throw new IllegalArgumentException(UNKNOWN_URI + uri);
        }

        // Do the query
        final SQLiteDatabase db = App.getDbHelper().getReadableDatabase();
        final Cursor cursor = queryBuilder.query(db, projection, newSelection, selectionArgs, null, null,
                newSortOrder);

        // set notifier
        cursor.setNotificationUri(getContext().getContentResolver(), uri);

        return cursor;
    }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        throw new UnsupportedOperationException("Unimplemented method: " + TAG);
    }

    @Override
    public Uri insert(@NonNull Uri uri, ContentValues values) {

        Uri newUri = uri;
        final String table;

        final int uriType = URI_MATCHER.match(uri);
        switch (uriType) {
        case CLIP:
            table = ClipContract.Clip.TABLE_NAME;
            break;
        case CLIP_ID:
            throw new IllegalArgumentException("Unsupported URI: " + uri);
        default:
            throw new IllegalArgumentException(UNKNOWN_URI + uri);
        }

        // this will insert or update as needed.
        // If it updates, it will be a new PRIMARY_KEY
        final SQLiteDatabase db = App.getDbHelper().getWritableDatabase();
        final long row = db.replace(table, null, values);

        if (row != -1) {
            newUri = ContentUris.withAppendedId(uri, row);

            if (BuildConfig.DEBUG) {
                Log.d(TAG, "Added row from insert: " + row);
            }

            getContext().getContentResolver().notifyChange(newUri, null);
        }

        return newUri;
    }

    @Override
    public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] values) {
        int insertCount = 0;
        final int uriType = URI_MATCHER.match(uri);
        final SQLiteDatabase db = App.getDbHelper().getWritableDatabase();

        switch (uriType) {
        case CLIP:
            db.beginTransaction();
            for (final ContentValues value : values) {
                final long id = db.insert(ClipContract.Clip.TABLE_NAME, null, value);
                if (id > 0) {
                    insertCount++;
                }
            }
            db.setTransactionSuccessful();
            db.endTransaction();
            break;
        case CLIP_ID:
            throw new IllegalArgumentException(UNKNOWN_URI + uri);
        default:
            throw new IllegalArgumentException(UNKNOWN_URI + uri);
        }

        if (BuildConfig.DEBUG) {
            Log.d(TAG, "Bulk insert rows: " + insertCount);
        }

        getContext().getContentResolver().notifyChange(uri, null);

        return insertCount;
    }

    @Override
    public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) {

        final int uriType = URI_MATCHER.match(uri);
        final String table;
        String newSelection = selection;

        switch (uriType) {
        case CLIP:
            table = ClipContract.Clip.TABLE_NAME;
            break;
        case CLIP_ID:
            table = ClipContract.Clip.TABLE_NAME;
            final String id = uri.getLastPathSegment();
            if (TextUtils.isEmpty(selection)) {
                newSelection = ClipContract.Clip._ID + "=" + id;
            } else {
                newSelection = selection + ClipContract.Clip._ID + "=" + id;
            }
            break;
        default:
            throw new IllegalArgumentException(UNKNOWN_URI + uri);
        }

        // do the delete
        final SQLiteDatabase db = App.getDbHelper().getWritableDatabase();
        final int rowsDeleted = db.delete(table, newSelection, selectionArgs);

        if (BuildConfig.DEBUG) {
            Log.d(TAG, "Deleted rows: " + rowsDeleted);
        }

        getContext().getContentResolver().notifyChange(uri, null);

        return rowsDeleted;
    }

    @Override
    public int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        final String table;
        String newSelection = selection;

        final int uriType = URI_MATCHER.match(uri);
        switch (uriType) {
        case CLIP:
            table = ClipContract.Clip.TABLE_NAME;
            break;
        case CLIP_ID:
            table = ClipContract.Clip.TABLE_NAME;
            final String id = uri.getLastPathSegment();
            if (TextUtils.isEmpty(selection)) {
                newSelection = ClipContract.Clip._ID + "=" + id;
            } else {
                newSelection = newSelection + " and " + ClipContract.Clip._ID + "=" + id;
            }
            break;
        default:
            throw new IllegalArgumentException(UNKNOWN_URI + uri);
        }

        // do the update
        final SQLiteDatabase db = App.getDbHelper().getWritableDatabase();
        final int rowsUpdated = db.update(table, values, newSelection, selectionArgs);

        getContext().getContentResolver().notifyChange(uri, null);

        if (BuildConfig.DEBUG) {
            Log.d(TAG, "Updated rows: " + rowsUpdated);
        }

        return rowsUpdated;
    }
}