package de.tum.in.tumcampusapp.auxiliary;
import android.app.SearchManager;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.text.TextUtils;
import de.tum.in.tumcampusapp.managers.AbstractManager;
/**
* Slightly modified version of SearchRecentSuggestionsProvider taken from AOSP source code
*/
public abstract class EnhancedSearchRecentSuggestionsProvider extends ContentProvider {
// client-provided configuration values
private String mId;
private String mAuthority;
private int mMode;
private boolean mTwoLineDisplay;
// general database configuration and tables
private SQLiteDatabase db;
private static final String S_SUGGESTIONS = "suggestions";
private static final String ORDER_BY = "date DESC";
private static final String NULL_COLUMN = "query";
/**
* This mode bit configures the database to record recent queries. <i>required</i>
*
* @see #setupSuggestions(String, String)
*/
private static final int DATABASE_MODE_QUERIES = 1;
/**
* This mode bit configures the database to include a 2nd annotation line with each entry.
* <i>optional</i>
*
* @see #setupSuggestions(String, String)
*/
private static final int DATABASE_MODE_2LINES = 2;
// Uri and query support
private static final int URI_MATCH_SUGGEST = 1;
private Uri mSuggestionsUri;
private UriMatcher mUriMatcher;
private String mSuggestSuggestionClause;
private String[] mSuggestionProjection;
/**
* In order to use this class, you must extend it, and call this setup function from your
* constructor. In your application or activities, you must provide the same values when
* you create the {@link android.provider.SearchRecentSuggestions} helper.
*
* @param id String identifying the SuggestionProvider. Must not contain blanks or any
* other special characters
* @param authority This must match the authority that you've declared in your manifest.
* @see #DATABASE_MODE_QUERIES
* @see #DATABASE_MODE_2LINES
*/
void setupSuggestions(String id, String authority) {
if (TextUtils.isEmpty(authority)) {
throw new IllegalArgumentException();
}
// unpack mode flags
mTwoLineDisplay = 0 != (EnhancedSearchRecentSuggestionsProvider.DATABASE_MODE_QUERIES & DATABASE_MODE_2LINES);
// saved values
mId = '_' + id;
mAuthority = authority;
mMode = EnhancedSearchRecentSuggestionsProvider.DATABASE_MODE_QUERIES;
// derived values
mSuggestionsUri = Uri.parse("content://" + mAuthority + "/suggestions");
mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
mUriMatcher.addURI(mAuthority, SearchManager.SUGGEST_URI_PATH_QUERY, URI_MATCH_SUGGEST);
if (mTwoLineDisplay) {
mSuggestSuggestionClause = "display1 LIKE ? OR display2 LIKE ?";
mSuggestionProjection = new String[]{
"0 AS " + SearchManager.SUGGEST_COLUMN_FORMAT,
"'android.resource://system/"
+ android.R.drawable.ic_menu_recent_history + "' AS "
+ SearchManager.SUGGEST_COLUMN_ICON_1,
"display1 AS " + SearchManager.SUGGEST_COLUMN_TEXT_1,
"display2 AS " + SearchManager.SUGGEST_COLUMN_TEXT_2,
"query AS " + SearchManager.SUGGEST_COLUMN_QUERY,
"_id"
};
} else {
mSuggestSuggestionClause = "display1 LIKE ?";
mSuggestionProjection = new String[]{
"0 AS " + SearchManager.SUGGEST_COLUMN_FORMAT,
"'android.resource://system/"
+ android.R.drawable.ic_menu_recent_history + "' AS "
+ SearchManager.SUGGEST_COLUMN_ICON_1,
"display1 AS " + SearchManager.SUGGEST_COLUMN_TEXT_1,
"query AS " + SearchManager.SUGGEST_COLUMN_QUERY,
"_id"
};
}
}
/**
* This method is provided for use by the ContentResolver. Do not override, or directly
* call from your own code.
*/
@Override
public int delete(Uri uri, String select, String[] selectionArgs) {
final int length = uri.getPathSegments().size();
if (length != 1) {
throw new IllegalArgumentException("Unknown Uri");
}
final String base = uri.getPathSegments().get(0);
int count;
if (base.equals(S_SUGGESTIONS)) {
String selection = select.replace(S_SUGGESTIONS, S_SUGGESTIONS + mId);
count = db.delete(S_SUGGESTIONS + mId, selection, selectionArgs);
} else {
throw new IllegalArgumentException("Unknown Uri");
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
/**
* This method is provided for use by the ContentResolver. Do not override, or directly
* call from your own code.
*/
@Override
public String getType(Uri uri) {
if (mUriMatcher.match(uri) == URI_MATCH_SUGGEST) {
return SearchManager.SUGGEST_MIME_TYPE;
}
int length = uri.getPathSegments().size();
if (length >= 1) {
String base = uri.getPathSegments().get(0);
if (base.equals(S_SUGGESTIONS)) {
if (length == 1) {
return "vnd.android.cursor.dir/suggestion";
} else if (length == 2) {
return "vnd.android.cursor.item/suggestion";
}
}
}
throw new IllegalArgumentException("Unknown Uri");
}
/**
* This method is provided for use by the ContentResolver. Do not override, or directly
* call from your own code.
*/
@Override
public Uri insert(Uri uri, ContentValues values) {
int length = uri.getPathSegments().size();
if (length < 1) {
throw new IllegalArgumentException("Unknown Uri");
}
// Note: This table has on-conflict-replace semantics, so insert() may actually replace()
long rowID = -1;
String base = uri.getPathSegments().get(0);
Uri newUri = null;
if (base.equals(S_SUGGESTIONS) && length == 1) {
rowID = db.insert(S_SUGGESTIONS + mId, NULL_COLUMN, values);
if (rowID > 0) {
newUri = Uri.withAppendedPath(mSuggestionsUri, String.valueOf(rowID));
}
}
if (rowID < 0) {
throw new IllegalArgumentException("Unknown Uri");
}
getContext().getContentResolver().notifyChange(newUri, null);
return newUri;
}
/**
* This method is provided for use by the ContentResolver. Do not override, or directly
* call from your own code.
*/
@Override
public boolean onCreate() {
if (mAuthority == null || mMode == 0) {
throw new IllegalArgumentException("Provider not configured");
}
db = AbstractManager.getDb(getContext());
final String create_table = "CREATE TABLE IF NOT EXISTS suggestions" + mId + " (" +
"_id INTEGER PRIMARY KEY" +
",display1 TEXT UNIQUE ON CONFLICT REPLACE" +
",query TEXT" +
",date LONG );";
db.execSQL(create_table);
return true;
}
/**
* This method is provided for use by the ContentResolver. Do not override, or directly
* call from your own code.
*/
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
// special case for actual suggestions (from search manager)
if (mUriMatcher.match(uri) == URI_MATCH_SUGGEST) {
String suggestSelection;
String[] myArgs;
if (TextUtils.isEmpty(selectionArgs[0])) {
suggestSelection = null;
myArgs = null;
} else {
String like = "%" + selectionArgs[0] + "%";
if (mTwoLineDisplay) {
myArgs = new String[]{like, like};
} else {
myArgs = new String[]{like};
}
suggestSelection = mSuggestSuggestionClause;
}
// Suggestions are always performed with the default sort order
Cursor c = db.query(S_SUGGESTIONS + mId, mSuggestionProjection,
suggestSelection, myArgs, null, null, ORDER_BY, null);
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}
// otherwise process arguments and perform a standard query
int length = uri.getPathSegments().size();
if (length != 1 && length != 2) {
throw new IllegalArgumentException("Unknown Uri");
}
String base = uri.getPathSegments().get(0);
if (!base.equals(S_SUGGESTIONS)) {
throw new IllegalArgumentException("Unknown Uri");
}
String[] useProjection = null;
if (projection != null && projection.length > 0) {
useProjection = new String[projection.length + 1];
System.arraycopy(projection, 0, useProjection, 0, projection.length);
useProjection[projection.length] = "_id AS _id";
}
StringBuilder whereClause = new StringBuilder(256);
if (length == 2) {
whereClause.append("(_id = ").append(uri.getPathSegments().get(1)).append(')');
}
// Tack on the user's selection, if present
if (selection != null && !selection.isEmpty()) {
if (whereClause.length() > 0) {
whereClause.append(" AND ");
}
whereClause.append('(');
whereClause.append(selection);
whereClause.append(')');
}
// And perform the generic query as requested
Cursor c = db.query(base + mId, useProjection, whereClause.toString(),
selectionArgs, null, null, sortOrder,
null);
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}
/**
* This method is provided for use by the ContentResolver. Do not override, or directly
* call from your own code.
*/
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
throw new UnsupportedOperationException("Not implemented");
}
}