package zlc.season.rxdownload2.db;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import zlc.season.rxdownload2.entity.DownloadBean;
import zlc.season.rxdownload2.entity.DownloadFlag;
import zlc.season.rxdownload2.entity.DownloadRecord;
import zlc.season.rxdownload2.entity.DownloadStatus;
import static zlc.season.rxdownload2.db.Db.RecordTable.COLUMN_DATE;
import static zlc.season.rxdownload2.db.Db.RecordTable.COLUMN_DOWNLOAD_FLAG;
import static zlc.season.rxdownload2.db.Db.RecordTable.COLUMN_DOWNLOAD_SIZE;
import static zlc.season.rxdownload2.db.Db.RecordTable.COLUMN_EXTRA1;
import static zlc.season.rxdownload2.db.Db.RecordTable.COLUMN_EXTRA2;
import static zlc.season.rxdownload2.db.Db.RecordTable.COLUMN_EXTRA3;
import static zlc.season.rxdownload2.db.Db.RecordTable.COLUMN_EXTRA4;
import static zlc.season.rxdownload2.db.Db.RecordTable.COLUMN_EXTRA5;
import static zlc.season.rxdownload2.db.Db.RecordTable.COLUMN_ID;
import static zlc.season.rxdownload2.db.Db.RecordTable.COLUMN_IS_CHUNKED;
import static zlc.season.rxdownload2.db.Db.RecordTable.COLUMN_MISSION_ID;
import static zlc.season.rxdownload2.db.Db.RecordTable.COLUMN_SAVE_NAME;
import static zlc.season.rxdownload2.db.Db.RecordTable.COLUMN_SAVE_PATH;
import static zlc.season.rxdownload2.db.Db.RecordTable.COLUMN_TOTAL_SIZE;
import static zlc.season.rxdownload2.db.Db.RecordTable.COLUMN_URL;
import static zlc.season.rxdownload2.db.Db.RecordTable.TABLE_NAME;
import static zlc.season.rxdownload2.db.Db.RecordTable.insert;
import static zlc.season.rxdownload2.db.Db.RecordTable.read;
import static zlc.season.rxdownload2.db.Db.RecordTable.update;
import static zlc.season.rxdownload2.entity.DownloadFlag.PAUSED;
/**
* Author: Season(ssseasonnn@gmail.com)
* Date: 2016/11/14
* Time: 10:02
* FIXME
*/
public class DataBaseHelper {
private volatile static DataBaseHelper singleton;
private final Object databaseLock = new Object();
private DbOpenHelper mDbOpenHelper;
private volatile SQLiteDatabase readableDatabase;
private volatile SQLiteDatabase writableDatabase;
private DataBaseHelper(Context context) {
mDbOpenHelper = new DbOpenHelper(context);
}
public static DataBaseHelper getSingleton(Context context) {
if (singleton == null) {
synchronized (DataBaseHelper.class) {
if (singleton == null) {
singleton = new DataBaseHelper(context);
}
}
}
return singleton;
}
/**
* Judge the url's record exists.
*
* @param url url
* @return true if not exists
*/
public boolean recordNotExists(String url) {
Cursor cursor = null;
try {
cursor = getReadableDatabase().query(TABLE_NAME, new String[]{COLUMN_ID},
COLUMN_URL + "=?", new String[]{url}, null, null, null);
cursor.moveToFirst();
return cursor.getCount() == 0;
} finally {
if (cursor != null) {
cursor.close();
}
}
}
public long insertRecord(DownloadBean downloadBean, int flag) {
return getWritableDatabase().insert(TABLE_NAME, null, insert(downloadBean, flag, null));
}
public long insertRecord(DownloadBean downloadBean, int flag, String missionId) {
return getWritableDatabase().insert(TABLE_NAME, null, insert(downloadBean, flag, missionId));
}
public long updateStatus(String url, DownloadStatus status) {
return getWritableDatabase().update(TABLE_NAME, update(status),
COLUMN_URL + "=?", new String[]{url});
}
public long updateRecord(String url, int flag) {
return getWritableDatabase().update(TABLE_NAME, update(flag),
COLUMN_URL + "=?", new String[]{url});
}
public long updateRecord(String url, int flag, String missionId) {
return getWritableDatabase().update(TABLE_NAME, update(flag, missionId),
COLUMN_URL + "=?", new String[]{url});
}
public long updateRecord(String url, String saveName, String savePath, int flag) {
return getWritableDatabase().update(TABLE_NAME, update(saveName, savePath, flag),
COLUMN_URL + "=?", new String[]{url});
}
public int deleteRecord(String url) {
return getWritableDatabase().delete(TABLE_NAME, COLUMN_URL + "=?", new String[]{url});
}
public long repairErrorFlag() {
return getWritableDatabase().update(TABLE_NAME, update(PAUSED),
COLUMN_DOWNLOAD_FLAG + "=? or " + COLUMN_DOWNLOAD_FLAG + "=?",
new String[]{DownloadFlag.WAITING + "", DownloadFlag.STARTED + ""});
}
/**
* Read single Record.
*
* @param url url
* @return Record
*/
@Nullable
public DownloadRecord readSingleRecord(String url) {
Cursor cursor = null;
try {
cursor = getReadableDatabase().query(TABLE_NAME,
new String[]{COLUMN_ID, COLUMN_URL, COLUMN_SAVE_NAME, COLUMN_SAVE_PATH,
COLUMN_DOWNLOAD_SIZE, COLUMN_TOTAL_SIZE, COLUMN_IS_CHUNKED,
COLUMN_EXTRA1, COLUMN_EXTRA2, COLUMN_EXTRA3, COLUMN_EXTRA4,
COLUMN_EXTRA5, COLUMN_DOWNLOAD_FLAG, COLUMN_DATE, COLUMN_MISSION_ID},
COLUMN_URL + "=?", new String[]{url}, null, null, null);
cursor.moveToFirst();
if (cursor.getCount() == 0) {
return null;
} else {
return read(cursor);
}
} finally {
if (cursor != null) {
cursor.close();
}
}
}
/**
* Read missionId all records.
*
* @param missionId missionId
* @return Records
*/
public List<DownloadRecord> readMissionsRecord(String missionId) {
Cursor cursor = null;
try {
cursor = getReadableDatabase().query(TABLE_NAME,
new String[]{COLUMN_ID, COLUMN_URL, COLUMN_SAVE_NAME, COLUMN_SAVE_PATH,
COLUMN_DOWNLOAD_SIZE, COLUMN_TOTAL_SIZE, COLUMN_IS_CHUNKED,
COLUMN_EXTRA1, COLUMN_EXTRA2, COLUMN_EXTRA3, COLUMN_EXTRA4,
COLUMN_EXTRA5, COLUMN_DOWNLOAD_FLAG, COLUMN_DATE, COLUMN_MISSION_ID},
COLUMN_MISSION_ID + "=?", new String[]{missionId}, null, null, null);
List<DownloadRecord> result = new ArrayList<>();
cursor.moveToFirst();
if (cursor.getCount() > 0) {
do {
result.add(read(cursor));
} while (cursor.moveToNext());
}
return result;
} finally {
if (cursor != null) {
cursor.close();
}
}
}
/**
* Read the url's download status.
*
* @param url url
* @return download status
*/
public DownloadStatus readStatus(String url) {
Cursor cursor = null;
try {
cursor = getReadableDatabase().query(
TABLE_NAME,
new String[]{COLUMN_DOWNLOAD_SIZE, COLUMN_TOTAL_SIZE, COLUMN_IS_CHUNKED},
COLUMN_URL + "=?", new String[]{url}, null, null, null);
cursor.moveToFirst();
if (cursor.getCount() == 0) {
return new DownloadStatus();
} else {
return Db.RecordTable.readStatus(cursor);
}
} finally {
if (cursor != null) {
cursor.close();
}
}
}
/**
* Read all records from database.
*
* @return All records.
*/
public Observable<List<DownloadRecord>> readAllRecords() {
return Observable
.create(new ObservableOnSubscribe<List<DownloadRecord>>() {
@Override
public void subscribe(ObservableEmitter<List<DownloadRecord>> emitter)
throws Exception {
Cursor cursor = null;
try {
cursor = getReadableDatabase().query(TABLE_NAME,
new String[]{COLUMN_ID, COLUMN_URL, COLUMN_SAVE_NAME, COLUMN_SAVE_PATH,
COLUMN_DOWNLOAD_SIZE, COLUMN_TOTAL_SIZE, COLUMN_IS_CHUNKED,
COLUMN_EXTRA1, COLUMN_EXTRA2, COLUMN_EXTRA3, COLUMN_EXTRA4,
COLUMN_EXTRA5, COLUMN_DOWNLOAD_FLAG, COLUMN_DATE, COLUMN_MISSION_ID},
null, null, null, null, null);
List<DownloadRecord> result = new ArrayList<>();
cursor.moveToFirst();
if (cursor.getCount() > 0) {
do {
result.add(read(cursor));
} while (cursor.moveToNext());
}
emitter.onNext(result);
emitter.onComplete();
} finally {
if (cursor != null) {
cursor.close();
}
}
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
/**
* Read the url's record.
* <p>
* If record not exists, return an empty record.
*
* @param url url
* @return record
*/
public Observable<DownloadRecord> readRecord(final String url) {
return Observable
.create(new ObservableOnSubscribe<DownloadRecord>() {
@Override
public void subscribe(ObservableEmitter<DownloadRecord> emitter) throws Exception {
Cursor cursor = null;
try {
cursor = getReadableDatabase().query(TABLE_NAME,
new String[]{COLUMN_ID, COLUMN_URL, COLUMN_SAVE_NAME, COLUMN_SAVE_PATH,
COLUMN_DOWNLOAD_SIZE, COLUMN_TOTAL_SIZE, COLUMN_IS_CHUNKED,
COLUMN_EXTRA1, COLUMN_EXTRA2, COLUMN_EXTRA3, COLUMN_EXTRA4,
COLUMN_EXTRA5, COLUMN_DOWNLOAD_FLAG, COLUMN_DATE, COLUMN_MISSION_ID},
COLUMN_URL + "=?", new String[]{url}, null, null, null);
cursor.moveToFirst();
if (cursor.getCount() == 0) {
emitter.onNext(new DownloadRecord());
} else {
emitter.onNext(read(cursor));
}
emitter.onComplete();
} finally {
if (cursor != null) {
cursor.close();
}
}
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
public void closeDataBase() {
synchronized (databaseLock) {
readableDatabase = null;
writableDatabase = null;
mDbOpenHelper.close();
}
}
private SQLiteDatabase getWritableDatabase() {
SQLiteDatabase db = writableDatabase;
if (db == null) {
synchronized (databaseLock) {
db = writableDatabase;
if (db == null) {
db = writableDatabase = mDbOpenHelper.getWritableDatabase();
}
}
}
return db;
}
private SQLiteDatabase getReadableDatabase() {
SQLiteDatabase db = readableDatabase;
if (db == null) {
synchronized (databaseLock) {
db = readableDatabase;
if (db == null) {
db = readableDatabase = mDbOpenHelper.getReadableDatabase();
}
}
}
return db;
}
}