/**
* Copyright (c) 2015 unfoldingWord
* http://creativecommons.org/licenses/MIT/
* See LICENSE file for details.
* Contributors:
* PJ Fechner <pj@actsmedia.com>
*/
package model;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteDatabaseLockedException;
import android.database.sqlite.SQLiteException;
import android.util.Log;
import com.google.common.io.ByteStreams;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.ListIterator;
import model.daoModels.Book;
import model.daoModels.DaoMaster;
import model.daoModels.DaoSession;
import model.daoModels.Version;
import model.parsers.MediaType;
import unfoldingword.DaoHelperMethods;
import unfoldingword.ModelNames;
import utils.FileNameHelper;
import utils.FileUtil;
import utils.UWPreferenceDataManager;
public class DatabaseOpenHelper extends DaoMaster.OpenHelper {
private static final String TAG = "DatabaseOpenHelper";
private Context context;
private SQLiteDatabase sqliteDatabase;
private static boolean needsUpgrade;
private static String DB_PATH;
private static String DB_NAME;
private static DatabaseOpenHelper sharedInstance;
public static DatabaseOpenHelper getSharedInstance(Context context, String name, CursorFactory factory) {
if(sharedInstance == null) {
sharedInstance = new DatabaseOpenHelper(context, name, factory);
}
return sharedInstance;
}
public DatabaseOpenHelper(Context context, String name, CursorFactory factory) {
super(context, name, factory);
this.context = context;
DB_NAME = name;
if(android.os.Build.VERSION.SDK_INT >= 17){
DB_PATH = context.getApplicationInfo().dataDir + "/databases/";
}
else {
DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";
}
try {
createDataBase();
} catch (Exception ioe) {
ioe.printStackTrace();
throw new Error("Unable to create database");
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if(oldVersion < ModelNames.DB_VERSION_ID){
needsUpgrade = true;
}
DaoSession session = new DaoMaster(db).newSession();
Version version = Version.getModelForUniqueSlug("bibleasulb", session);
if (version != null) {
version.deleteContent(context);
}
UWPreferenceDataManager.resetChapterSelections(context, false);
Log.i(TAG, "Upgraded DB From Version " + oldVersion + " To Version " + newVersion);
}
public void deleteDatabase() {
close();
String databasePath = DB_PATH + DB_NAME;
boolean result = new File(databasePath).delete();
Log.d(TAG, "Database Deleted Result: " + result);
}
/** Open Database for Use */
public void openDatabase() {
String databasePath = DB_PATH + DB_NAME;
sqliteDatabase = SQLiteDatabase.openDatabase(databasePath, null,
(SQLiteDatabase.OPEN_READWRITE));
}
public void openDatabaseReadable() {
String databasePath = DB_PATH + DB_NAME;
sqliteDatabase = SQLiteDatabase.openDatabase(databasePath, null,
(SQLiteDatabase.OPEN_READONLY));
}
/** Close Database after use */
@Override
public synchronized void close() {
if ((sqliteDatabase != null) && sqliteDatabase.isOpen()) {
sqliteDatabase.close();
}
super.close();
}
/** Get database instance for use */
public SQLiteDatabase getSqliteDatabase() {
return sqliteDatabase;
}
/** Create new database if not present */
synchronized public void createDataBase() {
if (!databaseExists()) {
SQLiteDatabase sqliteDatabase = this.getReadableDatabase();
/* Database does not exists create blank database */
sqliteDatabase.close();
populateWithPreload();
}
// else if(needsUpgrade()) {
// populateWithPreload();
// UWPreferenceDataManager.resetChapterSelections(context);
// SQLiteDatabase sqliteDatabase = this.getReadableDatabase();
// Log.i(TAG, "Got here");
// }
}
public void upgradeIfNeeded() {
if(needsUpgrade) {
// populateWithPreload();
// UWPreferenceDataManager.resetChapterSelections(context);
needsUpgrade = false;
}
}
private void populateWithPreload(){
copyDataBase();
saveSourceFiles();
}
public void saveDatabase(){
if(databaseExists()){
String databasePath = DB_PATH + DB_NAME;
File databaseInputFile = new File(databasePath);
byte[] bytes = FileUtil.getBytesFromFile(databaseInputFile);
FileUtil.saveFileToSdCard(context, bytes, DB_NAME);
}
}
/** Check Database if it exists */
private boolean databaseExists() {
SQLiteDatabase sqliteDatabase = null;
try {
String databasePath = DB_PATH + DB_NAME;
sqliteDatabase = SQLiteDatabase.openDatabase(databasePath, null,
SQLiteDatabase.OPEN_READONLY);
} catch (SQLiteException e) {
e.printStackTrace();
}
if (sqliteDatabase != null) {
sqliteDatabase.close();
}
return sqliteDatabase != null ? true : false;
}
private boolean needsUpgrade() {
SQLiteDatabase sqliteDatabase = null;
try {
String databasePath = DB_PATH + DB_NAME;
sqliteDatabase = SQLiteDatabase.openDatabase(databasePath, null,
SQLiteDatabase.OPEN_READONLY);
} catch (SQLiteException e) {
e.printStackTrace();
}
if (sqliteDatabase != null) {
if(sqliteDatabase.getVersion() < ModelNames.DB_VERSION_ID) {
sqliteDatabase.close();
return true;
}
sqliteDatabase.close();
}
return false;
}
/**
* Copy existing database file in system
*/
public void copyDataBase() {
int length;
byte[] buffer = new byte[1024];
String databasePath = DB_PATH + DB_NAME;
try {
InputStream databaseInputFile = this.context.getAssets().open(DB_NAME);
OutputStream databaseOutputFile = new FileOutputStream(databasePath);
while ((length = databaseInputFile.read(buffer)) > 0) {
databaseOutputFile.write(buffer, 0, length);
databaseOutputFile.flush();
}
databaseInputFile.close();
databaseOutputFile.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void saveSourceFiles(){
// openDatabaseReadable();
List<Book> books = null;
while(books == null) {
try {
books = DaoDBHelper.getDaoSession(context)
.getBookDao().queryBuilder().list();
}
catch (SQLiteDatabaseLockedException e){
e.printStackTrace();
try {
Thread.sleep(500);
} catch (InterruptedException newE) {
newE.printStackTrace();
}
// sqliteDatabase.close();
// openDatabaseReadable();
}
}
ListIterator li = books.listIterator(books.size());
// Iterate in reverse to start with the stories.
while(li.hasPrevious()) {
Book book = (Book) li.previous();
try {
String signature = loadDbFile(FileNameHelper.getSaveFileNameFromUrl(book.getSignatureUrl()));
byte[] text = loadDbFileBytes(FileNameHelper.getSaveFileNameFromUrl(book.getSourceUrl()));
DataFileManager.saveDataForBook(context, book, text, MediaType.MEDIA_TYPE_TEXT);
DataFileManager.saveSignatureForBook(context, book, signature.getBytes(), MediaType.MEDIA_TYPE_TEXT);
}
catch (IOException e){
e.printStackTrace();
}
}
}
private void saveFile(byte[] bytes, String url){
try{
FileOutputStream fos = context.openFileOutput(FileNameHelper.getSaveFileNameFromUrl(url), Context.MODE_PRIVATE);
fos.write(bytes);
fos.close();
Log.i(TAG, "File Saved");
}
catch (IOException e){
e.printStackTrace();
Log.e(TAG, "Error when saving file");
}
}
private byte[] loadDbFileBytes(String fileName) throws IOException{
// Open your local model.db as the input stream
InputStream inputStream = context.getAssets().open("preloaded_content/" + fileName);
return ByteStreams.toByteArray(inputStream);
}
private String loadDbFile(String fileName) throws IOException{
// Open your local model.db as the input stream
InputStream inputStream = context.getAssets().open("preloaded_content/" + fileName);
return new String(ByteStreams.toByteArray(inputStream));
}
}