/* * Copyright 2013 Yoshihiro Miyama * * 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.kyakujin.android.autoeco.db; 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.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.text.TextUtils; import android.util.Log; import com.kyakujin.android.autoeco.Conf; import com.kyakujin.android.autoeco.Logger; import com.kyakujin.android.autoeco.db.AutoEcoContract.BatteryTbl; import com.kyakujin.android.autoeco.db.AutoEcoContract.EcoTbl; import com.kyakujin.android.autoeco.db.AutoEcoContract.ManualTbl; import com.kyakujin.android.autoeco.db.AutoEcoContract.MappingTbl; import com.kyakujin.android.autoeco.db.AutoEcoContract.SchedTbl; import com.kyakujin.android.autoeco.db.AutoEcoDBOpenHelperV1.Tables; /** * Provider that stores {@link AutoEcoContract} data. */ public class AutoEcoProvider extends ContentProvider { private final String TAG = Conf.APP_NAME + ":" + this.getClass().getSimpleName(); private AutoEcoDBOpenHelperV1 mOpenHelper; private static final int ECO = 100; private static final int ECO_ID = 101; private static final int SCHED = 200; private static final int SCHED_ID = 201; private static final int BATTERY = 300; private static final int BATTERY_ID = 301; private static final int MANUAL = 400; private static final int MANUAL_ID = 401; private static final int MAPPING = 1000; private static final int MAPPING_ID = 1001; private static final UriMatcher sUriMatcher; static { final String authority = AutoEcoContract.CONTENT_AUTHORITY; sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); sUriMatcher.addURI(authority, Tables.ECO, ECO); sUriMatcher.addURI(authority, Tables.ECO + "/#", ECO_ID); sUriMatcher.addURI(authority, Tables.SCHED, SCHED); sUriMatcher.addURI(authority, Tables.SCHED + "/#", SCHED_ID); sUriMatcher.addURI(authority, Tables.BATTERY, BATTERY); sUriMatcher.addURI(authority, Tables.BATTERY + "/#", BATTERY_ID); sUriMatcher.addURI(authority, Tables.MANUAL, MANUAL); sUriMatcher.addURI(authority, Tables.MANUAL + "/#", MANUAL_ID); sUriMatcher.addURI(authority, Tables.MAPPING, MAPPING); sUriMatcher.addURI(authority, Tables.MAPPING + "/#", MAPPING_ID); } private void setOpenHelper (boolean isTest) { if(mOpenHelper == null) { Context context = null; if(isTest) { //context = new RenamingDelegatingContext(getContext(), "test_"); Logger.d(TAG, "isTest is ON --> RenamingDeletgatingContext"); } else { context = getContext(); Logger.d(TAG, "isTest is OFF --> Original Context"); } mOpenHelper = new AutoEcoDBOpenHelperV1(context); } } @Override public boolean onCreate() { //mOpenHelper = new AutoEcoDBOpenHelperV1(getContext()); setOpenHelper(Conf.isTest); return true; } @Override public String getType(Uri uri) { switch (sUriMatcher.match(uri)) { case ECO: return EcoTbl.CONTENT_TYPE; case ECO_ID: return EcoTbl.CONTENT_ITEM_TYPE; case SCHED: return SchedTbl.CONTENT_TYPE; case SCHED_ID: return SchedTbl.CONTENT_ITEM_TYPE; case BATTERY: return BatteryTbl.CONTENT_TYPE; case BATTERY_ID: return BatteryTbl.CONTENT_ITEM_TYPE; case MANUAL: return ManualTbl.CONTENT_TYPE; case MANUAL_ID: return ManualTbl.CONTENT_ITEM_TYPE; case MAPPING: return MappingTbl.CONTENT_TYPE; case MAPPING_ID: return MappingTbl.CONTENT_ITEM_TYPE; default: throw new IllegalArgumentException("Invalid URI: " + uri); } } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { //setOpenHelper(Conf.isTest); final SQLiteDatabase db = mOpenHelper.getReadableDatabase(); final SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); switch (sUriMatcher.match(uri)) { case ECO: qb.setTables(Tables.ECO); // sortOrder = Tags.DEFAULT_SORT; break; case ECO_ID: qb.setTables(Tables.ECO); qb.appendWhere(EcoTbl._ID + "=" + uri.getLastPathSegment()); break; case SCHED: if (selection != null) { // TODO 次回改善箇所 // 無理やりここを通すための苦肉の策 // 以下の条件式を満たすためには、呼び出し元のwhere句で「WHERE」を指定する if (selection.contains("WHERE")) { String sql = "SELECT " + Tables.SCHED + "." + SchedTbl._ID + ", " + Tables.SCHED + "." + SchedTbl.ENABLED + ", " + Tables.SCHED + "." + SchedTbl.HOUR_MINUTE_STRING + ", " + Tables.ECO + "." + EcoTbl.NAME + " FROM " + Tables.SCHED + " JOIN " + Tables.MAPPING + " ON " + Tables.MAPPING + "." + MappingTbl.SCHED_ID + " = " + Tables.SCHED + "." + SchedTbl._ID + " JOIN " + Tables.ECO + " ON " + Tables.MAPPING + "." + MappingTbl.ECO_ID + " = " + Tables.ECO + "." + EcoTbl._ID + " " + selection + ";"; Cursor c = db.rawQuery(sql, selectionArgs); c.setNotificationUri(getContext().getContentResolver(), uri); return c; } } else { sortOrder = SchedTbl.DEFAULT_SORT; qb.setTables(Tables.SCHED); } break; case SCHED_ID: qb.setTables(Tables.SCHED); qb.appendWhere(SchedTbl._ID + "=" + uri.getLastPathSegment()); break; case BATTERY: qb.setTables(Tables.BATTERY); // sortOrder = Tags.DEFAULT_SORT; break; case BATTERY_ID: qb.setTables(Tables.BATTERY); qb.appendWhere(BatteryTbl._ID + "=" + uri.getLastPathSegment()); break; case MANUAL: qb.setTables(Tables.MANUAL); // sortOrder = Tags.DEFAULT_SORT; break; case MANUAL_ID: qb.setTables(Tables.MANUAL); qb.appendWhere(ManualTbl._ID + "=" + uri.getLastPathSegment()); break; case MAPPING: qb.setTables(Tables.MAPPING); // sortOrder = Tags.DEFAULT_SORT; break; case MAPPING_ID: qb.setTables(Tables.MAPPING); qb.appendWhere(MappingTbl._ID + "=" + uri.getLastPathSegment()); break; default: throw new IllegalArgumentException("Invalid URI: " + uri); } Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder); c.setNotificationUri(getContext().getContentResolver(), uri); return c; } @Override public Uri insert(Uri uri, ContentValues initialValues) { ContentValues values; if (initialValues != null) { values = new ContentValues(initialValues); } else { values = new ContentValues(); } //setOpenHelper(Conf.isTest); final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); String tableName; String hackString; Uri contentUri; switch (sUriMatcher.match(uri)) { case ECO: tableName = Tables.ECO; hackString = EcoTbl.NAME; contentUri = EcoTbl.CONTENT_URI; break; case SCHED: tableName = Tables.SCHED; hackString = SchedTbl.HOUR; contentUri = SchedTbl.CONTENT_URI; break; case BATTERY: tableName = Tables.BATTERY; hackString = BatteryTbl.THRESHOLD; contentUri = BatteryTbl.CONTENT_URI; break; case MANUAL: tableName = Tables.MANUAL; hackString = ManualTbl.NAME; contentUri = ManualTbl.CONTENT_URI; break; case MAPPING: tableName = Tables.MAPPING; hackString = MappingTbl.ECO_ID; contentUri = MappingTbl.CONTENT_URI; break; default: throw new IllegalArgumentException("Invalid URI: " + uri); } // SDKバージョンが異なると、insertWithOnConflict()でCONFLICT_IGNOREを指定した場合の // 一意性違反発生時の戻り値が以下のように異なる。 // [SDKバージョン → rowId] // Android 2.3.4以下 → 0 // Android 3.1以上 → -1 // したがって以下のような処理を記述した。 long rowId = 0; try { rowId = db.insertWithOnConflict(tableName, hackString, values, SQLiteDatabase.CONFLICT_IGNORE); Logger.d(TAG, "rowId=" + rowId); } catch (SQLException e) { Log.e(TAG, "Failed to insert: " + rowId, e); return null; } if (rowId > 0) { Uri insertUri = ContentUris.withAppendedId(contentUri, rowId); getContext().getContentResolver().notifyChange(insertUri, null); return insertUri; } return null; } @Override public int update(Uri uri, ContentValues values, String where, String[] whereArgs) { //setOpenHelper(Conf.isTest); SQLiteDatabase db = mOpenHelper.getWritableDatabase(); String tableName; String whereClause = where; switch (sUriMatcher.match(uri)) { case ECO: tableName = Tables.ECO; break; case ECO_ID: tableName = Tables.ECO; whereClause = EcoTbl._ID + " == " + uri.getLastPathSegment() + (!TextUtils.isEmpty(where) ? "AND (" + where + ')' : ""); break; case SCHED: tableName = Tables.SCHED; break; case SCHED_ID: tableName = Tables.SCHED; whereClause = SchedTbl._ID + " == " + uri.getLastPathSegment() + (!TextUtils.isEmpty(where) ? "AND (" + where + ')' : ""); break; case BATTERY: tableName = Tables.BATTERY; break; case BATTERY_ID: tableName = Tables.BATTERY; whereClause = BatteryTbl._ID + " == " + uri.getLastPathSegment() + (!TextUtils.isEmpty(where) ? "AND (" + where + ')' : ""); break; case MANUAL: tableName = Tables.MANUAL; break; case MANUAL_ID: tableName = Tables.MANUAL; whereClause = ManualTbl._ID + " == " + uri.getLastPathSegment() + (!TextUtils.isEmpty(where) ? "AND (" + where + ')' : ""); break; case MAPPING: tableName = Tables.MAPPING; break; case MAPPING_ID: tableName = Tables.MAPPING; whereClause = MappingTbl._ID + " == " + uri.getLastPathSegment() + (!TextUtils.isEmpty(where) ? "AND (" + where + ')' : ""); break; default: throw new IllegalArgumentException("Invalid URI: " + uri); } int count = db.updateWithOnConflict(tableName, values, whereClause, whereArgs, SQLiteDatabase.CONFLICT_REPLACE); getContext().getContentResolver().notifyChange(uri, null); return count; } @Override public int delete(Uri uri, String where, String[] whereArgs) { //setOpenHelper(Conf.isTest); SQLiteDatabase db = mOpenHelper.getWritableDatabase(); String tableName; String whereClause = where; switch (sUriMatcher.match(uri)) { case ECO: tableName = Tables.ECO; break; case ECO_ID: tableName = Tables.ECO; whereClause = EcoTbl._ID + " == " + uri.getLastPathSegment() + (!TextUtils.isEmpty(where) ? "AND (" + where + ')' : ""); break; case SCHED: tableName = Tables.SCHED; break; case SCHED_ID: tableName = Tables.SCHED; whereClause = SchedTbl._ID + " == " + uri.getLastPathSegment() + (!TextUtils.isEmpty(where) ? "AND (" + where + ')' : ""); break; case BATTERY: tableName = Tables.BATTERY; break; case BATTERY_ID: tableName = Tables.BATTERY; whereClause = BatteryTbl._ID + " == " + uri.getLastPathSegment() + (!TextUtils.isEmpty(where) ? "AND (" + where + ')' : ""); break; case MANUAL: tableName = Tables.MANUAL; break; case MANUAL_ID: tableName = Tables.MANUAL; whereClause = BatteryTbl._ID + " == " + uri.getLastPathSegment() + (!TextUtils.isEmpty(where) ? "AND (" + where + ')' : ""); break; case MAPPING: tableName = Tables.MAPPING; break; case MAPPING_ID: tableName = Tables.MAPPING; whereClause = MappingTbl._ID + " == " + uri.getLastPathSegment() + (!TextUtils.isEmpty(where) ? "AND (" + where + ')' : ""); break; default: throw new IllegalArgumentException("Invalid URI: " + uri); } int count = db.delete(tableName, whereClause, whereArgs); getContext().getContentResolver().notifyChange(uri, null); return count; } // public void deleteDatabase() { // mOpenHelper.close(); // Context context = getContext(); // AutoEcoDBOpenHelperV1.deleteDatabase(context); // mOpenHelper = new AutoEcoDBOpenHelperV1(getContext()); // } }