/*
* Copyright (C) 2011 Alex Kuiper
*
* This file is part of PageTurner
*
* PageTurner is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PageTurner 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 General Public License
* along with PageTurner. If not, see <http://www.gnu.org/licenses/>.*
*/
package net.nightwhistler.pageturner.library;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import com.google.inject.Inject;
import roboguice.inject.ContextSingleton;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@ContextSingleton
public class LibraryDatabaseHelper extends SQLiteOpenHelper {
private static final String LIB_BOOKS_TABLE = "lib_books";
public enum Field {
file_name("text primary key"), title("text"), a_first_name("text"),
a_last_name("text"), date_added("integer"), date_last_read("integer"),
description("text"), cover_image("blob"), progress("integer");
private String fieldDef;
private Field(String fieldDef) { this.fieldDef = fieldDef; }
}
public enum Order { ASC , DESC }
private static final String DB_NAME = "PageTurnerLibrary";
private static final int VERSION = 4;
private static String getCreateTableString() {
String create = "create table " + LIB_BOOKS_TABLE + " ( ";
boolean first = true;
for ( Field f: Field.values() ) {
if ( first ) {
first = false;
} else {
create += ",";
}
create += (" " + f.name() + " " + f.fieldDef);
}
create += " );";
return create;
}
@Inject
public LibraryDatabaseHelper(Context context) {
super(context, DB_NAME, null, VERSION);
}
private synchronized SQLiteDatabase getDataBase() {
return getWritableDatabase();
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(getCreateTableString());
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if ( oldVersion == 3 ) {
db.execSQL("ALTER TABLE " + LIB_BOOKS_TABLE + " ADD COLUMN progress integer" );
}
}
public void delete( String fileName ) {
String[] args = { fileName };
getDataBase().delete(LIB_BOOKS_TABLE, Field.file_name + " = ?", args );
}
public void updateLastRead( String fileName, int progress ) {
String whereClause = Field.file_name.toString() + " like ?";
String[] args = { "%" + fileName };
ContentValues content = new ContentValues();
content.put( Field.date_last_read.toString(), new Date().getTime() );
if ( progress != -1 ) {
content.put(Field.progress.toString(), progress );
}
getDataBase().update(LIB_BOOKS_TABLE, content, whereClause, args);
}
public void storeNewBook(String fileName, String authorFirstName,
String authorLastName, String title, String description,
byte[] coverImage, boolean setLastRead) {
ContentValues content = new ContentValues();
content.put(Field.title.toString(), title );
content.put(Field.a_first_name.toString(), authorFirstName );
content.put(Field.a_last_name.toString(), authorLastName );
content.put(Field.cover_image.toString(), coverImage );
content.put(Field.description.toString(), description );
if ( setLastRead ) {
content.put(Field.date_last_read.toString(), new Date().getTime() );
}
content.put(Field.file_name.toString(), fileName );
content.put(Field.date_added.toString(), new Date().getTime() );
getDataBase().insert(LIB_BOOKS_TABLE, null, content);
}
public boolean hasBook( String fileName ) {
Field[] fields = { Field.file_name };
String[] args = { "%" + fileName };
String whereClause = Field.file_name.toString() + " like ?";
Cursor findBook = getDataBase().query( LIB_BOOKS_TABLE, fieldsAsString(fields), whereClause,
args, null, null, null );
boolean result = findBook.getCount() != 0;
findBook.close();
return result;
}
private static String getFilterClause(String filter, String existingClause ) {
if ( filter == null || filter.length() == 0 ) {
return existingClause;
}
String whereClause = "(" + Field.a_first_name + " like ? "
+ " or " + Field.a_last_name + " like ? "
+ " or " + Field.title + " like ? )";
if ( existingClause != null ) {
whereClause = whereClause + " and " + existingClause;
}
return whereClause;
}
private static String[] getFilterArgs( String[] existingArgs, String filter ) {
if ( filter == null || filter.length() == 0 ) {
return existingArgs;
}
String searchString = "%" + filter + "%";
String[] newArgs;
if ( existingArgs != null ) {
newArgs = new String[existingArgs.length + 3];
//Move original arguments 3 positions to the right
System.arraycopy(existingArgs, 0,newArgs, 3, existingArgs.length );
} else {
newArgs = new String[3];
}
//And fill the first 3 with the filter-string.
for ( int i=0; i < 3; i++ ) {
newArgs[i] = searchString;
}
return newArgs;
}
public synchronized KeyedQueryResult<LibraryBook> findByField( Field fieldName, String fieldValue,
Field orderField, Order ordering, String filter) {
String[] args = { fieldValue };
String whereClause;
if ( fieldValue == null ) {
whereClause = fieldName.toString() + " is null";
args = null;
} else {
whereClause = fieldName.toString() + " = ?";
}
if ( filter != null ) {
whereClause = getFilterClause(filter, whereClause);
args = getFilterArgs(args, filter);
}
Cursor cursor = getDataBase().query(LIB_BOOKS_TABLE,
fieldsAsString(Field.values()),
whereClause, args, null, null,
"LOWER(" + orderField + ") " + ordering );
List<String> keys = getKeys(orderField, ordering);
return new KeyedBookResult( cursor, keys );
}
public synchronized QueryResult<LibraryBook> findAllOrderedBy( Field fieldName, Order order, String filter ) {
String whereClause = fieldName != null ? fieldName.toString() + " is not null" : null;
String[] args = new String[0];
if ( filter != null ) {
whereClause = getFilterClause(filter, whereClause);
args = getFilterArgs(args, filter);
}
Cursor cursor = getDataBase().query(LIB_BOOKS_TABLE,
fieldsAsString(Field.values()),
whereClause,args, null, null,
fieldName != null ? "LOWER(" + fieldName.toString() + ") " + order.toString() : null );
return new LibraryBookResult(cursor);
}
private List<String> getKeys( Field fieldName, Order order ) {
String[] keyField = { fieldName.toString() };
Cursor fieldCursor = getDataBase().query(LIB_BOOKS_TABLE,
keyField, null, new String[0], null, null,
fieldName != null ? "LOWER(" + fieldName.toString() + ") " + order.toString() : null);
List<String> keys = new ArrayList<String>();
fieldCursor.moveToFirst();
fieldCursor.moveToFirst();
while( !fieldCursor.isAfterLast()) {
keys.add(fieldCursor.getString(0));
fieldCursor.moveToNext();
}
fieldCursor.close();
return keys;
}
public synchronized KeyedQueryResult<LibraryBook> findAllKeyedBy(Field fieldName, Order order, String filter ) {
List<String> keys = getKeys(fieldName, order);
String whereClause = fieldName != null ? fieldName.toString() + " is not null" : null;
String[] args = new String[0];
if ( filter != null ) {
whereClause = getFilterClause(filter, whereClause);
args = getFilterArgs(args, filter);
}
Cursor cursor = getDataBase().query(LIB_BOOKS_TABLE,
fieldsAsString(Field.values()),
whereClause, args, null, null,
fieldName != null ? "LOWER(" + fieldName.toString() + ") "
+ order.toString() : null );
return new KeyedBookResult(cursor, keys);
}
private class KeyedBookResult extends KeyedQueryResult<LibraryBook> {
public KeyedBookResult(Cursor cursor, List<String> keys) {
super(cursor, keys);
}
@Override
public LibraryBook convertRow(Cursor cursor) {
return doConvertRow(cursor);
}
}
private class LibraryBookResult extends QueryResult<LibraryBook> {
public LibraryBookResult(Cursor cursor) {
super(cursor);
}
@Override
public LibraryBook convertRow(Cursor cursor) {
return doConvertRow(cursor);
}
}
private static LibraryBook doConvertRow(Cursor cursor) {
LibraryBook newBook = new LibraryBook();
newBook.setAuthor(new Author(
cursor.getString(Field.a_first_name.ordinal()),
cursor.getString(Field.a_last_name.ordinal())));
newBook.setTitle( cursor.getString(Field.title.ordinal()));
newBook.setDescription(cursor.getString(Field.description.ordinal()));
try {
newBook.setAddedToLibrary(new Date(cursor.getLong(Field.date_added.ordinal())));
} catch (RuntimeException r){}
try {
newBook.setLastRead(new Date(cursor.getLong(Field.date_last_read.ordinal())));
} catch (RuntimeException r){}
byte[] coverData = cursor.getBlob(Field.cover_image.ordinal());
newBook.setCoverImage(coverData);
newBook.setFileName( cursor.getString(Field.file_name.ordinal()));
newBook.setProgress(cursor.getInt(Field.progress.ordinal()));
return newBook;
}
private static String[] fieldsAsString(Field[] values) {
String[] fieldsAsString = new String[values.length];
for ( int i=0; i < values.length; i++ ) {
fieldsAsString[i] = values[i].toString();
}
return fieldsAsString;
}
}