/*
* Copyright (c) 2013 Menny Even-Danan
*
* 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.anysoftkeyboard.dictionaries.sqlite;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.text.TextUtils;
import com.anysoftkeyboard.dictionaries.WordsCursor;
import com.anysoftkeyboard.utils.Log;
public class WordsSQLiteConnection extends SQLiteOpenHelper {
private static final String TAG = "ASK SqliteCnnt";
private final static String TABLE_NAME = "WORDS";//was FALL_BACK_USER_DICTIONARY;
protected final Context mContext;
private final String mCurrentLocale;
//This monitor will help us control the IO access to the (very highly non-thread-safe)
//sqlite file. Hence, reducing SQL file corruption errors. Hopefully.
private final static String mDbCreationMonitor = "GLOBAL LOCK FOR IO";
private final String mDbName;
public WordsSQLiteConnection(Context context, String DbFilename, String currentLocale) {
super(context, DbFilename, null, 7);
mContext = context;
mCurrentLocale = currentLocale;
mDbName = DbFilename;
}
@Override
public void onCreate(SQLiteDatabase db) {
synchronized (mDbCreationMonitor) {
db.execSQL("CREATE TABLE " + TABLE_NAME + " (" + Words._ID + " INTEGER PRIMARY KEY," + Words.WORD + " TEXT," + Words.FREQUENCY + " INTEGER," + Words.LOCALE + " TEXT" + ");");
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
synchronized (mDbCreationMonitor) {
// Please note: don't use class level constants here, since they may
// change.
// if you upgrade from one version to another, make sure you use the
// correct names!
Log.d(TAG, "Upgrading WordsSQLiteConnection from version " + oldVersion + " to " + newVersion + "...");
if (oldVersion < 4) {
Log.d(TAG, "Upgrading WordsSQLiteConnection to version 4: Adding locale column...");
db.execSQL("ALTER TABLE FALL_BACK_USER_DICTIONARY ADD COLUMN locale TEXT;");
}
if (oldVersion < 5) {
Log.d(TAG, "Upgrading WordsSQLiteConnection to version 5: Adding _id column and populating...");
db.execSQL("ALTER TABLE FALL_BACK_USER_DICTIONARY ADD COLUMN _id INTEGER;");
db.execSQL("UPDATE FALL_BACK_USER_DICTIONARY SET _id=Id;");
}
if (oldVersion < 6) {
Log.d(TAG, "Upgrading WordsSQLiteConnection to version 6: Matching schema with Android's User-Dictionary table...");
db.execSQL("ALTER TABLE FALL_BACK_USER_DICTIONARY RENAME TO tmp_FALL_BACK_USER_DICTIONARY;");
db.execSQL("CREATE TABLE FALL_BACK_USER_DICTIONARY (" + "_id INTEGER PRIMARY KEY,word TEXT," + "frequency INTEGER,locale TEXT);");
db.execSQL("INSERT INTO FALL_BACK_USER_DICTIONARY(_id, word, frequency, locale) SELECT _id, Word, Freq, locale FROM tmp_FALL_BACK_USER_DICTIONARY;");
db.execSQL("DROP TABLE tmp_FALL_BACK_USER_DICTIONARY;");
}
if (oldVersion < 7) {
Log.d(TAG, "Renaming the table's name to a generic one...");
db.execSQL("ALTER TABLE FALL_BACK_USER_DICTIONARY RENAME TO WORDS;");
}
}
}
public synchronized void addWord(String word, int freq) {
synchronized (mDbName) {
SQLiteDatabase db = getWritableDatabase();
ContentValues values = new ContentValues();
values.put(Words._ID, word.hashCode());// ensuring that any word is inserted once
values.put(Words.WORD, word);
values.put(Words.FREQUENCY, freq);
values.put(Words.LOCALE, mCurrentLocale);
long res = db.insert(TABLE_NAME, null, values);
if (res < 0) {
Log.e(TAG, "Unable to insert '" + word + "' to SQLite storage (" + mCurrentLocale + "@" + mDbName + ")! Result:" + res);
} else {
Log.d(TAG, "Inserted '" + word + "' to SQLite storage (" + mCurrentLocale + "@" + mDbName + "). Id:" + res);
}
db.close();
}
}
public synchronized void deleteWord(String word) {
synchronized (mDbName) {
SQLiteDatabase db = getWritableDatabase();
db.delete(TABLE_NAME, Words.WORD + "=?", new String[]{word});
db.close();
}
}
public WordsCursor getWordsCursor() {
synchronized (mDbName) {
SQLiteDatabase db = getReadableDatabase();
Cursor c;
if (TextUtils.isEmpty(mCurrentLocale)) {
//some language packs will not provide locale, and Android _may_ crash here
c = db.query(TABLE_NAME, new String[]{Words._ID, Words.WORD, Words.FREQUENCY}, "(" + Words.LOCALE + " IS NULL)", null, null, null, null);
} else {
c = db.query(TABLE_NAME, new String[]{Words._ID, Words.WORD, Words.FREQUENCY}, "(" + Words.LOCALE + " IS NULL) or (" + Words.LOCALE + "=?)", new String[]{mCurrentLocale}, null, null, null);
}
return new WordsCursor.SqliteWordsCursor(db, c);
}
}
/**
* This is a compatibility function: SQLiteOpenHelper.getDatabaseName exists only in API14
*
* @return
*/
public String getDbFilename() {
return mDbName;
}
public static final class Words {
public static final java.lang.String _ID = "_id";
public static final java.lang.String WORD = "word";
public static final java.lang.String FREQUENCY = "frequency";
public static final java.lang.String LOCALE = "locale";
}
}