package com.example.wordbook.provider; import android.app.SearchManager; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.UriMatcher; import android.database.Cursor; import android.database.MatrixCursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.provider.BaseColumns; import android.text.TextUtils; /** * コンテンツプロバイダ */ public class WBProvider extends ContentProvider { /** 識別子 */ public static final String AUTHORITY = "com.example.wordbook.wbprovider"; /** コンテンツURI */ public static final Uri INFO_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + WBData.TABLE_NAME_INFO); /** コンテンツ MIME type */ public static final String INFO_CONTENT_TYPE = "vnd.android.cursor.dir/vnd.wordbook.info"; /** コンテンツアイテム MIME type */ public static final String INFO_CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.wordbook.info"; /** コンテンツ */ private static final int WBDATA_INFO = 1; /** コンテンツアイテム */ private static final int WBDATA_INFO_ITEM = 2; /** SEARCH_SUGGEST */ private static final int SEARCH_SUGGEST = 3; /** SHORTCUT_REFRESH */ private static final int SHORTCUT_REFRESH = 4; /** URIマッチャー */ private static final UriMatcher URI_MATCHER; /** URIマッチャー初期化 */ static { URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH); URI_MATCHER.addURI(AUTHORITY, WBData.TABLE_NAME_INFO, WBDATA_INFO); URI_MATCHER.addURI(AUTHORITY, WBData.TABLE_NAME_INFO + "/#", WBDATA_INFO_ITEM); URI_MATCHER.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, SEARCH_SUGGEST); URI_MATCHER.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", SEARCH_SUGGEST); URI_MATCHER.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT, SHORTCUT_REFRESH); URI_MATCHER.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", SHORTCUT_REFRESH); } /** Helper */ private WBHelper mHelper; /** * コンテンツタイプ取得処理 * * @param uri * コンテンツURI * @return コンテンツタイプ */ @Override public String getType(Uri uri) { if (uri == null) { throw new IllegalArgumentException("NULL parameter"); } switch (URI_MATCHER.match(uri)) { case WBDATA_INFO: return INFO_CONTENT_TYPE; case WBDATA_INFO_ITEM: return INFO_CONTENT_ITEM_TYPE; case SEARCH_SUGGEST: return SearchManager.SUGGEST_MIME_TYPE; case SHORTCUT_REFRESH: return SearchManager.SHORTCUT_MIME_TYPE; default: throw new IllegalArgumentException("Unknown URI:" + uri); } } /** * Helper生成処理 * * @return true */ @Override public boolean onCreate() { mHelper = WBHelper.getInstance(getContext()); return true; } /** * 挿入処理 * * @param uri * Insert対象URI * @param values * Insert値 * @return 挿入結果URI */ @Override public Uri insert(Uri uri, ContentValues values) { if (uri == null || values == null) { throw new IllegalArgumentException("NULL parameter"); } switch (URI_MATCHER.match(uri)) { case WBDATA_INFO: SQLiteDatabase db = mHelper.getWritableDatabase(); long id = db.insert(WBData.TABLE_NAME_INFO, null, values); if (id > 0) { // インサートが成功した場合はURIにIDを付加して返却 Uri retUri = ContentUris.withAppendedId(INFO_CONTENT_URI, id); // 通知 getContext().getContentResolver().notifyChange(retUri, null); return retUri; } throw new SQLException("Insert failed:" + uri); default: throw new IllegalArgumentException("Unsupported URI:" + uri); } } /** * 削除処理 * * @param uri * Delete対象URI * @param selection * Where句 * @param selectionArgs * Where句で ? を使用する際の置換値 * @return 削除件数 */ @Override public int delete(Uri uri, String selection, String[] selectionArgs) { if (uri == null) { throw new IllegalArgumentException("NULL parameter"); } int count = 0; SQLiteDatabase db = mHelper.getWritableDatabase(); switch (URI_MATCHER.match(uri)) { case WBDATA_INFO: count = db.delete(WBData.TABLE_NAME_INFO, selection, selectionArgs); break; case WBDATA_INFO_ITEM: long id = ContentUris.parseId(uri); count = db.delete(WBData.TABLE_NAME_INFO, BaseColumns._ID + "=" + id + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ")" : ""), selectionArgs); break; default: throw new IllegalArgumentException("Unsupported URI:" + uri); } // 通知 getContext().getContentResolver().notifyChange(uri, null); return count; } /** * 更新処理 * * @param uri * Update対象URI * @param values * Update値 * @param selection * Where句 * @param selectionArgs * Where句で ? を使用する際の置換値 * @return 更新件数 */ @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { if (uri == null || values == null) { throw new IllegalArgumentException("NULL parameter"); } int count = 0; SQLiteDatabase db = mHelper.getWritableDatabase(); switch (URI_MATCHER.match(uri)) { case WBDATA_INFO: count = db.update(WBData.TABLE_NAME_INFO, values, selection, selectionArgs); break; case WBDATA_INFO_ITEM: long id = ContentUris.parseId(uri); count = db.update(WBData.TABLE_NAME_INFO, values, BaseColumns._ID + "=" + id + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ")" : ""), selectionArgs); break; default: throw new IllegalArgumentException("Unsupported URI:" + uri); } // 通知 getContext().getContentResolver().notifyChange(uri, null); return count; } /** * クエリ発行処理 * * @param uri * 対象URI * @param projection * 取得列名配列 * @param selection * Where句 * @param selectionArgs * Where句で ? を使用する際の置換値 * @param sortOrder * OrderBy句 * @return クエリ結果カーソルオブジェクト */ @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { if (uri == null) { throw new IllegalArgumentException("NULL parameter"); } // ソート順序 String order = sortOrder; if (TextUtils.isEmpty(sortOrder)) { order = WBData.InfoColumns.DEFAULT_SORT_ORDER; } // 取得数制限 String limit = uri.getQueryParameter("limit"); // クエリ生成 SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); qb.setTables(WBData.TABLE_NAME_INFO); qb.setProjectionMap(WBData.PROJECTION_MAP_INFO); SQLiteDatabase db = mHelper.getReadableDatabase(); switch (URI_MATCHER.match(uri)) { case WBDATA_INFO: // 通常クエリ対応 break; case WBDATA_INFO_ITEM: // 通常クエリ対応 long id = ContentUris.parseId(uri); qb.appendWhere(BaseColumns._ID + "=" + id); break; case SEARCH_SUGGEST: // QSBクエリ対応 // selectionは未使用 // 検索欄の値が質問か解答に含まれるデータを検索 StringBuilder sb = new StringBuilder(); sb.append(WBData.InfoColumns.INFO_QUESTION); sb.append(" LIKE '%'||?||'%'"); sb.append(" OR "); sb.append(WBData.InfoColumns.INFO_ANSWER); sb.append(" LIKE '%'||?||'%'"); String[] args = { selectionArgs[0], selectionArgs[0] }; Cursor c = qb.query(db, projection, sb.toString(), args, null, null, order, limit); // QSBクエリ用カーソル Cursor qsbc = makeWordbookQBSCursor(c); c.close(); return qsbc; case SHORTCUT_REFRESH: // QSBクエリ対応 return null; default: throw new IllegalArgumentException("Unsupported URI:" + uri); } // 通常クエリ用カーソル Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, order, limit); // 通知 c.setNotificationUri(getContext().getContentResolver(), uri); return c; } /** QSBクエリ用カーソル列名 */ private static final String[] SUGGEST_COLUMNS = { BaseColumns._ID, // 必須 SearchManager.SUGGEST_COLUMN_SHORTCUT_ID, // 履歴 SearchManager.SUGGEST_COLUMN_TEXT_1, // 質問 SearchManager.SUGGEST_COLUMN_TEXT_2, // 解答 SearchManager.SUGGEST_COLUMN_INTENT_DATA, // 識別用データ }; /** * QSBクエリ用カーソル生成 * * @param c * 検索結果 * @return QSBクエリ用検索結果 */ private Cursor makeWordbookQBSCursor(Cursor c) { MatrixCursor qsb = new MatrixCursor(SUGGEST_COLUMNS); int idx_num, idx_q, idx_a; idx_num = c.getColumnIndex(WBData.InfoColumns.INFO_NUM); idx_q = c.getColumnIndex(WBData.InfoColumns.INFO_QUESTION); idx_a = c.getColumnIndex(WBData.InfoColumns.INFO_ANSWER); if (c.moveToFirst()) { do { qsb.addRow(new Object[] { c.getInt(idx_num), // INFO_NUM SearchManager.SUGGEST_NEVER_MAKE_SHORTCUT, // 履歴無効 c.getString(idx_q), // 質問 c.getString(idx_a), // 解答 c.getString(idx_q) + "," + c.getString(idx_a), // 識別用データ }); } while (c.moveToNext()); } return qsb; } }