package com.aptoide.amethyst.database.provider; import android.content.ContentProvider; import android.content.ContentValues; import android.content.UriMatcher; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.text.TextUtils; import com.aptoide.amethyst.BuildConfig; import com.aptoide.amethyst.database.SQLiteDatabaseHelper; import com.aptoide.amethyst.database.schema.Schema; import java.util.HashMap; /** * Created by hsousa on 17-06-2015. */ public class DatabaseProvider extends ContentProvider { /** * Aptoide database helper */ private SQLiteDatabaseHelper database; /** * A projection map used to select columns from the database */ private static HashMap<String, String> sReposProjectionMap; /* * Constants used by the Uri matcher to choose an action based on the pattern * of the incoming URI */ private static final int REPOS = 1; private static final int REPO_ID = 2; // private static final int ROLLBACKS = 2; // private static final int UPDATES = 3; /** * Build and return a {@link UriMatcher} that catches all {@link Uri}variations supported by this {@link ContentProvider}. */ private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); static { sUriMatcher.addURI(ProviderConstants.AUTHORITY, ProviderConstants.PATH_REPO, REPOS); sUriMatcher.addURI(ProviderConstants.AUTHORITY, ProviderConstants.PATH_REPO_ID + "/#", REPO_ID); /* * Creates and initializes a projection map that returns all columns */ // Creates a new projection map instance. The map returns a column name // given a string. The two are usually equal. sReposProjectionMap = new HashMap<>(); // Maps the string to the column names sReposProjectionMap.put(Schema.Repo.COLUMN_ID, Schema.Repo.COLUMN_ID); sReposProjectionMap.put(Schema.Repo.COLUMN_URL, Schema.Repo.COLUMN_URL); sReposProjectionMap.put(Schema.Repo.COLUMN_APK_PATH, Schema.Repo.COLUMN_APK_PATH); sReposProjectionMap.put(Schema.Repo.COLUMN_ICONS_PATH, Schema.Repo.COLUMN_ICONS_PATH); sReposProjectionMap.put(Schema.Repo.COLUMN_WEBSERVICES_PATH, Schema.Repo.COLUMN_WEBSERVICES_PATH); sReposProjectionMap.put(Schema.Repo.COLUMN_HASH, Schema.Repo.COLUMN_HASH); sReposProjectionMap.put(Schema.Repo.COLUMN_THEME, Schema.Repo.COLUMN_THEME); sReposProjectionMap.put(Schema.Repo.COLUMN_AVATAR, Schema.Repo.COLUMN_AVATAR); sReposProjectionMap.put(Schema.Repo.COLUMN_DOWNLOADS, Schema.Repo.COLUMN_DOWNLOADS); sReposProjectionMap.put(Schema.Repo.COLUMN_DESCRIPTION, Schema.Repo.COLUMN_DESCRIPTION); sReposProjectionMap.put(Schema.Repo.COLUMN_VIEW, Schema.Repo.COLUMN_VIEW); sReposProjectionMap.put(Schema.Repo.COLUMN_ITEMS, Schema.Repo.COLUMN_ITEMS); sReposProjectionMap.put(Schema.Repo.COLUMN_LATEST_TIMESTAMP, Schema.Repo.COLUMN_LATEST_TIMESTAMP); sReposProjectionMap.put(Schema.Repo.COLUMN_TOP_TIMESTAMP, Schema.Repo.COLUMN_TOP_TIMESTAMP); sReposProjectionMap.put(Schema.Repo.COLUMN_IS_USER, Schema.Repo.COLUMN_IS_USER); sReposProjectionMap.put(Schema.Repo.COLUMN_FAILED, Schema.Repo.COLUMN_FAILED); sReposProjectionMap.put(Schema.Repo.COLUMN_NAME, Schema.Repo.COLUMN_NAME); sReposProjectionMap.put(Schema.Repo.COLUMN_USERNAME, Schema.Repo.COLUMN_USERNAME); sReposProjectionMap.put(Schema.Repo.COLUMN_PASSWORD, Schema.Repo.COLUMN_PASSWORD); } @Override public boolean onCreate() { database = SQLiteDatabaseHelper.getInstance(getContext()); // Assumes that any failures will be reported by a thrown exception. return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // Constructs a new query builder and sets its table name SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); qb.setTables(ProviderConstants.REPO_TABLE_NAME); /** * Choose the projection and adjust the "where" clause based on URI pattern-matching. */ switch (sUriMatcher.match(uri)) { // If the incoming URI is for repos, chooses the Notes projection case REPOS: qb.setProjectionMap(sReposProjectionMap); break; /* If the incoming URI is for a single note identified by its ID, chooses the * note ID projection, and appends "_ID = <noteID>" to the where clause, so that * it selects that single note */ case REPO_ID: qb.setProjectionMap(sReposProjectionMap); qb.appendWhere( Schema.Repo.COLUMN_ID + // the name of the ID column "=" + // the position of the note ID itself in the incoming URI uri.getPathSegments().get(ProviderConstants.REPO_ID_PATH_POSITION)); break; default: // If the URI doesn't match any of the known patterns, throw an exception. throw new IllegalArgumentException("Unknown URI " + uri); } String orderBy; // If no sort order is specified, uses the default if (TextUtils.isEmpty(sortOrder)) { orderBy = ProviderConstants.DEFAULT_SORT_ORDER; } else { // otherwise, uses the incoming sort order orderBy = sortOrder; } // Opens the database object in "read" mode, since no writes need to be done. SQLiteDatabase db = database.getReadableDatabase(); /* * Performs the query. If no problems occur trying to read the database, then a Cursor * object is returned; otherwise, the cursor variable contains null. If no records were * selected, then the Cursor object is empty, and Cursor.getCount() returns 0. */ Cursor c = qb.query( db, // The database to query projection, // The columns to return from the query selection, // The columns for the where clause selectionArgs, // The values for the where clause null, // don't group the rows null, // don't filter by row groups orderBy // The sort order ); // Tells the Cursor what URI to watch, so it knows when its source data changes c.setNotificationUri(getContext().getContentResolver(), uri); return c; } /* @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // Using SQLiteQueryBuilder instead of query() method SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); // check if the caller has requested a column which does not exists // checkColumns(projection); // Set the table queryBuilder.setTables(Schema.Repo.REPO_TABLE_NAME); switch (sUriMatcher.match(uri)) { case REPOS: break; case REPO_ID: // adding the ID to the original query queryBuilder.appendWhere(Schema.Repo.COLUMN_ID + "=" + uri.getLastPathSegment()); break; default: throw new IllegalArgumentException("Unknown URI: " + uri); } Cursor cursor = queryBuilder.query(database.getReadableDatabase(), projection, selection, selectionArgs, null, null, sortOrder); // make sure that potential listeners are getting notified cursor.setNotificationUri(getContext().getContentResolver(), uri); return cursor; } */ @Override public String getType(Uri uri) { return null; } @Override public Uri insert(Uri uri, ContentValues values) { int uriType = sUriMatcher.match(uri); long id; switch (uriType) { case REPOS: id = database.getWritableDatabase().insert(ProviderConstants.REPO_TABLE_NAME, null, values); break; default: throw new IllegalArgumentException("Unknown URI: " + uri); } getContext().getContentResolver().notifyChange(uri, null); return Uri.parse(ProviderConstants.PATH_REPO_ID + "/" + id); } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { // Opens the database object in "write" mode. SQLiteDatabase db = database.getWritableDatabase(); int uriType = sUriMatcher.match(uri); int rowsDeleted; switch (uriType) { case REPOS: rowsDeleted = db.delete(ProviderConstants.REPO_TABLE_NAME, selection, selectionArgs); break; case REPO_ID: String id = uri.getLastPathSegment(); if (TextUtils.isEmpty(selection)) { rowsDeleted = db.delete( ProviderConstants.REPO_TABLE_NAME, Schema.Repo.COLUMN_ID + "=" + id, null); } else { rowsDeleted = db.delete( ProviderConstants.REPO_TABLE_NAME, Schema.Repo.COLUMN_ID + "=" + id + " and " + selection, selectionArgs); } break; default: throw new IllegalArgumentException("Unknown URI: " + uri); } getContext().getContentResolver().notifyChange(uri, null); return rowsDeleted; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { // Opens the database object in "write" mode. SQLiteDatabase db = database.getWritableDatabase(); int uriType = sUriMatcher.match(uri); int rowsUpdated; switch (uriType) { case REPOS: rowsUpdated = db.update(ProviderConstants.REPO_TABLE_NAME, values, selection, selectionArgs); break; case REPO_ID: String id = uri.getLastPathSegment(); if (TextUtils.isEmpty(selection)) { rowsUpdated = db.update(ProviderConstants.REPO_TABLE_NAME, values, Schema.Repo.COLUMN_ID + "=" + id, null); } else { rowsUpdated = db.update(ProviderConstants.REPO_TABLE_NAME, values, Schema.Repo.COLUMN_ID + "=" + id + " and " + selection, selectionArgs); } break; default: throw new IllegalArgumentException("Unknown URI: " + uri); } getContext().getContentResolver().notifyChange(uri, null); return rowsUpdated; } public static class ProviderConstants { /** * Repo database name */ public static final String REPO_TABLE_NAME = "repo"; public static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".DatabaseProvider"; /* * URI definitions */ /** * The scheme part for this provider's URI */ private static final String SCHEME = "content://"; /** * Path part for the Repo URI */ public static final String PATH_REPO = "/repos"; /** * Path part for the Repo ID URI */ public static final String PATH_REPO_ID = "/repos/"; /** * 0-relative position of a note ID segment in the path part of a note ID URI */ public static final int REPO_ID_PATH_POSITION = 1; /** * The content:// style URL for this table */ public static final Uri CONTENT_URI = Uri.parse(SCHEME + AUTHORITY + PATH_REPO); /** * The content URI base for a single note. Callers must * append a numeric note id to this Uri to retrieve a note */ public static final Uri CONTENT_ID_URI_BASE = Uri.parse(SCHEME + AUTHORITY + PATH_REPO_ID); /** * The content URI match pattern for a single note, specified by its ID. Use this to match * incoming URIs or to construct an Intent. */ public static final Uri CONTENT_ID_URI_PATTERN = Uri.parse(SCHEME + AUTHORITY + PATH_REPO_ID + "/#"); /** * The default sort order for this table */ public static final String DEFAULT_SORT_ORDER = "modified DESC"; } }