/*
* Funambol is a mobile platform developed by Funambol, Inc.
* Copyright (C) 2009 Funambol, Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by
* the Free Software Foundation with the addition of the following permission
* added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
* WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program; if not, see http://www.gnu.org/licenses or write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA.
*
* You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
* 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Powered by Funambol" logo. If the display of the logo is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Powered by Funambol".
*/
package com.funambol.storage;
import java.io.IOException;
import java.util.Enumeration;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import com.funambol.util.Log;
/**
* Allows a key-value pairs to be stored to a SQLite database through the
* Android APIs.
*/
public class StringKeyValueSQLiteStore implements StringKeyValueStore {
private static final String TAG_LOG = "StringKeyValueSQLiteStore";
private final static int FUNAMBOL_DATABASE_VERSION = 1;
protected String tableName;
protected final String KEY_COLUMN_NAME = "_key";
protected final String VALUE_COLUMN_NAME = "_value";
protected final String[] QUERY_KEY_COLUMN = {KEY_COLUMN_NAME};
protected final String[] QUERY_VALUE_COLUMN = {VALUE_COLUMN_NAME};
protected final String[] QUERY_KEY_VALUE_COLUMN = {KEY_COLUMN_NAME, VALUE_COLUMN_NAME};
protected SQLiteDatabase dbStore;
protected DatabaseHelper mDatabaseHelper = null;
/**
* Create a new <code>StringKeyValueSQLiteStore</code> given the
* <code>Context</code> the database file name and the table name.
*
* @param c The <code>Context</code>.
* @param dbName The database file name.
* @param tableName The table name.
*/
public StringKeyValueSQLiteStore(Context c, String dbName, String tableName) {
mDatabaseHelper = new DatabaseHelper(c, dbName, tableName);
this.tableName = tableName;
// Create the table containing the key value pairs (if it does not exist
// already)
open();
dbStore.execSQL(getCreateSQLCommand());
dbStore.close();
dbStore = null;
}
/**
* @see StringKeyValueStore#add(java.lang.String, java.lang.String)
*/
public void add(String key, String value) {
ContentValues cv = new ContentValues();
cv.put(KEY_COLUMN_NAME, key);
cv.put(VALUE_COLUMN_NAME, value);
if (dbStore == null) {
open();
}
if(dbStore.insert(tableName, null, cv) != -1) {
Log.debug(TAG_LOG, "Insert new record. Key: " + key + " value: " +
value);
} else {
Log.error(TAG_LOG, "Error while insert new record. Key: " + key +
" value: " + value);
}
}
/**
* @see StringKeyValueStore#update(java.lang.String, java.lang.String)
*/
public void update(String key, String value) {
ContentValues cv = new ContentValues();
cv.put(KEY_COLUMN_NAME, key);
cv.put(VALUE_COLUMN_NAME, value);
if (dbStore == null) {
open();
}
StringBuffer where = new StringBuffer(KEY_COLUMN_NAME);
where.append("=\"").append(key).append("\"");
if(dbStore.update(tableName, cv, where.toString(), null) != -1) {
Log.debug(TAG_LOG, "Update record. Key: " + key + " value: " + value);
} else {
Log.error(TAG_LOG, "Error while update record. Key: " + key +
" value: " + value);
}
}
/**
* Deprecated method. Throws always an Exception.
*/
public String put(String key, String value) throws Exception {
throw new Exception("Operation not allowed in StringKeyValueSQLiteStore");
}
/**
* @see StringKeyValueStore#get(java.lang.String)
*/
public String get(String key) {
String result = null;
if (dbStore == null) {
open();
}
StringBuffer where = new StringBuffer(KEY_COLUMN_NAME);
where.append("=\"").append(key).append("\"");
Cursor resultCursor = dbStore.query(true, tableName, QUERY_VALUE_COLUMN,
where.toString(), null, null, null, null, null);
if(resultCursor.getCount() > 0) {
int colIndex = resultCursor.getColumnIndexOrThrow(VALUE_COLUMN_NAME);
resultCursor.moveToFirst();
result = resultCursor.getString(colIndex);
}
resultCursor.close();
return result;
}
/**
* @see StringKeyValueStore#keys()
*/
public Enumeration keys() {
if (dbStore == null) {
open();
}
final Cursor result = dbStore.query(true, tableName, QUERY_KEY_COLUMN,
null, null, null, null, KEY_COLUMN_NAME + " ASC", null);
final int keyColumnIndex = result.getColumnIndexOrThrow(KEY_COLUMN_NAME);
// Move Cursor to the first element
result.moveToFirst();
return new Enumeration () {
boolean last = false;
boolean closed = false;
public Object nextElement() {
// Get the Current value
String value = result.getString(keyColumnIndex);
// Move Cursor to the next element
result.moveToNext();
return value;
}
public boolean hasMoreElements() {
if(last) {
return false;
}
last = result.isAfterLast();
if(last) {
result.close();
closed = true;
}
return !last;
}
public void finalize() throws Throwable {
try {
if (!closed) {
result.close();
closed = true;
}
} finally {
super.finalize();
}
}
};
}
/**
* @see StringKeyValueStore#keyValuePairs()
*/
public Enumeration keyValuePairs() {
if (dbStore == null) {
open();
}
final Cursor result = dbStore.query(true, tableName, QUERY_KEY_VALUE_COLUMN,
null, null, null, null, KEY_COLUMN_NAME + " ASC", null);
final int keyColumnIndex = result.getColumnIndexOrThrow(KEY_COLUMN_NAME);
final int valueColumnIndex = result.getColumnIndexOrThrow(VALUE_COLUMN_NAME);
// Move Cursor to the first element
result.moveToFirst();
return new Enumeration () {
boolean last = false;
boolean closed = false;
public Object nextElement() {
// Get the Current value
String key = result.getString(keyColumnIndex);
String value = result.getString(valueColumnIndex);
// Move Cursor to the next element
result.moveToNext();
return new StringKeyValuePair(key, value);
}
public boolean hasMoreElements() {
if(last) {
return false;
}
last = result.isAfterLast();
if(last) {
result.close();
closed = true;
}
return !last;
}
public void finalize() throws Throwable {
try {
if (!closed) {
result.close();
closed = true;
}
} finally {
super.finalize();
}
}
};
}
/**
* @see StringKeyValueStore#contains(java.lang.String)
*/
public boolean contains(String key) {
if (dbStore == null) {
open();
}
StringBuffer where = new StringBuffer(KEY_COLUMN_NAME);
where.append("=\"").append(key).append("\"");
Cursor result = dbStore.query(true, tableName, QUERY_VALUE_COLUMN,
where.toString(), null, null, null, null, null);
int count = result.getCount();
result.close();
return count > 0;
}
/**
* @see StringKeyValueStore#remove(java.lang.String)
*/
public String remove(String key) {
if (dbStore == null) {
open();
}
StringBuffer where = new StringBuffer(KEY_COLUMN_NAME);
where.append("=\"").append(key).append("\"");
dbStore.delete(tableName, where.toString(), null);
return null;
}
/**
* Save the current store. Ends a successfull transaction.
* @see StringKeyValueStore#save()
*/
public void save() throws IOException {
if (dbStore != null) {
dbStore.close();
dbStore = null;
}
}
/**
* @see StringKeyValueStore#load()
*/
public void load() throws IOException {
dbStore = mDatabaseHelper.getWritableDatabase();
}
/**
* @see StringKeyValueStore#reset()
*/
public void reset() throws IOException {
// Delete all the rows from the current table
if (dbStore == null) {
open();
}
dbStore.delete(tableName, null, null);
dbStore.close();
dbStore = null;
}
public void finalize() {
if (dbStore != null) {
dbStore.close();
dbStore = null;
}
}
protected String getCreateSQLCommand() {
return "CREATE TABLE IF NOT EXISTS " + tableName + " ("
+ KEY_COLUMN_NAME + " varchar[50],"
+ VALUE_COLUMN_NAME + " varchar[50]);";
}
private void open() {
dbStore = mDatabaseHelper.getWritableDatabase();
}
public void dumpToLog() {
if (dbStore == null) {
open();
}
Cursor result = dbStore.query(true, tableName, null, null, null, null, null, null, null);
if (result.moveToFirst()) {
do {
final int keyColumnIndex = result.getColumnIndexOrThrow(KEY_COLUMN_NAME);
final int valueColumnIndex = result.getColumnIndexOrThrow(VALUE_COLUMN_NAME);
String key = result.getString(keyColumnIndex);
String value = result.getString(valueColumnIndex);
Log.info(TAG_LOG, "key=" + key + ",value=" + value);
} while(result.moveToNext());
}
result.close();
dbStore.close();
dbStore = null;
}
/**
* Helps on creating and upgrading the SQLite db.
*/
public class DatabaseHelper extends SQLiteOpenHelper {
public DatabaseHelper(Context context, String dbName, String tableName) {
super(context, dbName, null, FUNAMBOL_DATABASE_VERSION);
}
public void onCreate(SQLiteDatabase db) {
}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
}