package sjm.xuitls.db; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteStatement; import android.os.Build; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import sjm.xuitls.DbManager; import sjm.xuitls.common.util.IOUtil; import sjm.xuitls.common.util.KeyValue; import sjm.xuitls.common.util.LogUtil; import sjm.xuitls.db.sqlite.SqlInfo; import sjm.xuitls.db.sqlite.SqlInfoBuilder; import sjm.xuitls.db.sqlite.WhereBuilder; import sjm.xuitls.db.table.ColumnEntity; import sjm.xuitls.db.table.DbBase; import sjm.xuitls.db.table.DbModel; import sjm.xuitls.db.table.TableEntity; import sjm.xuitls.ex.DbException; import sjm.xuitls.x; public final class DbManagerImpl extends DbBase { private static final HashMap<DbManager.DaoConfig, DbManagerImpl> DAO_MAP = new HashMap<>(); private boolean allowTransaction; private DbManager.DaoConfig daoConfig; private SQLiteDatabase database; private DbManagerImpl(DbManager.DaoConfig daoConfig2) throws DbException { if (daoConfig2 != null) { this.daoConfig = daoConfig2; this.allowTransaction = daoConfig2.isAllowTransaction(); try { this.database = openOrCreateDatabase(daoConfig2); DbManager.DbOpenListener dbOpenListener = daoConfig2.getDbOpenListener(); if (dbOpenListener != null) { dbOpenListener.onDbOpened(this); } } catch (DbException e) { IOUtil.closeQuietly(this.database); throw e; } catch (Throwable th) { IOUtil.closeQuietly(this.database); throw new DbException(th.getMessage(), th); } } else { throw new IllegalArgumentException("daoConfig may not be null"); } } public static synchronized DbManager getInstance(DbManager.DaoConfig daoConfig2) throws DbException { DbManagerImpl dbManagerImpl; synchronized (DbManagerImpl.class) { if (daoConfig2 == null) { daoConfig2 = new DbManager.DaoConfig(); } HashMap<DbManager.DaoConfig, DbManagerImpl> hashMap = DAO_MAP; dbManagerImpl = hashMap.get(daoConfig2); if (dbManagerImpl == null) { dbManagerImpl = new DbManagerImpl(daoConfig2); hashMap.put(daoConfig2, dbManagerImpl); } else { dbManagerImpl.daoConfig = daoConfig2; } SQLiteDatabase sQLiteDatabase = dbManagerImpl.database; int version = sQLiteDatabase.getVersion(); int dbVersion = daoConfig2.getDbVersion(); if (version != dbVersion) { if (version != 0) { DbManager.DbUpgradeListener dbUpgradeListener = daoConfig2.getDbUpgradeListener(); if (dbUpgradeListener != null) { dbUpgradeListener.onUpgrade(dbManagerImpl, version, dbVersion); } else { dbManagerImpl.dropDb(); } } sQLiteDatabase.setVersion(dbVersion); } } return dbManagerImpl; } @Override // sjm.xuitls.DbManager public SQLiteDatabase getDatabase() { return this.database; } @Override // sjm.xuitls.DbManager public DbManager.DaoConfig getDaoConfig() { return this.daoConfig; } @Override // sjm.xuitls.DbManager public void saveOrUpdate(Object obj) throws DbException { try { beginTransaction(); if (obj instanceof List) { List<Object> list = (List) obj; if (!list.isEmpty()) { TableEntity<?> table = getTable(list.get(0).getClass()); table.createTableIfNotExists(); for (Object obj2 : list) { saveOrUpdateWithoutTransaction(table, obj2); } } else { return; } } else { TableEntity<?> table2 = getTable(obj.getClass()); table2.createTableIfNotExists(); saveOrUpdateWithoutTransaction(table2, obj); } setTransactionSuccessful(); endTransaction(); } finally { endTransaction(); } } @Override // sjm.xuitls.DbManager public void replace(Object obj) throws DbException { try { beginTransaction(); if (obj instanceof List) { List<Object> list = (List) obj; if (!list.isEmpty()) { TableEntity table = getTable(list.get(0).getClass()); table.createTableIfNotExists(); for (Object obj2 : list) { execNonQuery(SqlInfoBuilder.buildReplaceSqlInfo(table, obj2)); } } else { return; } } else { TableEntity table2 = getTable(obj.getClass()); table2.createTableIfNotExists(); execNonQuery(SqlInfoBuilder.buildReplaceSqlInfo(table2, obj)); } setTransactionSuccessful(); endTransaction(); } finally { endTransaction(); } } @Override // sjm.xuitls.DbManager public void save(Object obj) throws DbException { try { beginTransaction(); if (obj instanceof List) { List<Object> list = (List) obj; if (!list.isEmpty()) { TableEntity table = getTable(list.get(0).getClass()); table.createTableIfNotExists(); for (Object obj2 : list) { execNonQuery(SqlInfoBuilder.buildInsertSqlInfo(table, obj2)); } } else { return; } } else { TableEntity table2 = getTable(obj.getClass()); table2.createTableIfNotExists(); execNonQuery(SqlInfoBuilder.buildInsertSqlInfo(table2, obj)); } setTransactionSuccessful(); endTransaction(); } finally { endTransaction(); } } @Override // sjm.xuitls.DbManager public boolean saveBindingId(Object obj) throws DbException { try { beginTransaction(); boolean z = false; if (obj instanceof List) { List<Object> list = (List) obj; if (list.isEmpty()) { return false; } TableEntity<?> table = getTable(list.get(0).getClass()); table.createTableIfNotExists(); for (Object obj2 : list) { if (!saveBindingIdWithoutTransaction(table, obj2)) { throw new DbException("saveBindingId error, transaction will not commit!"); } } } else { TableEntity<?> table2 = getTable(obj.getClass()); table2.createTableIfNotExists(); z = saveBindingIdWithoutTransaction(table2, obj); } setTransactionSuccessful(); endTransaction(); return z; } finally { endTransaction(); } } @Override // sjm.xuitls.DbManager public void deleteById(Class<?> cls, Object obj) throws DbException { TableEntity table = getTable(cls); if (table.tableIsExists()) { try { beginTransaction(); execNonQuery(SqlInfoBuilder.buildDeleteSqlInfoById(table, obj)); setTransactionSuccessful(); } finally { endTransaction(); } } } @Override // sjm.xuitls.DbManager public void delete(Object obj) throws DbException { try { beginTransaction(); if (obj instanceof List) { List<Object> list = (List) obj; if (!list.isEmpty()) { TableEntity table = getTable(list.get(0).getClass()); if (!table.tableIsExists()) { endTransaction(); return; } for (Object obj2 : list) { execNonQuery(SqlInfoBuilder.buildDeleteSqlInfo(table, obj2)); } } else { return; } } else { TableEntity table2 = getTable(obj.getClass()); if (!table2.tableIsExists()) { endTransaction(); return; } execNonQuery(SqlInfoBuilder.buildDeleteSqlInfo(table2, obj)); } setTransactionSuccessful(); endTransaction(); } finally { endTransaction(); } } @Override // sjm.xuitls.DbManager public void delete(Class<?> cls) throws DbException { delete(cls, null); } @Override // sjm.xuitls.DbManager public int delete(Class<?> cls, WhereBuilder whereBuilder) throws DbException { TableEntity table = getTable(cls); if (!table.tableIsExists()) { return 0; } try { beginTransaction(); int executeUpdateDelete = executeUpdateDelete(SqlInfoBuilder.buildDeleteSqlInfo((TableEntity<?>) table, whereBuilder)); setTransactionSuccessful(); return executeUpdateDelete; } finally { endTransaction(); } } @Override // sjm.xuitls.DbManager public void update(Object obj, String... strArr) throws DbException { try { beginTransaction(); if (obj instanceof List) { List<Object> list = (List) obj; if (!list.isEmpty()) { TableEntity table = getTable(list.get(0).getClass()); if (!table.tableIsExists()) { endTransaction(); return; } for (Object obj2 : list) { execNonQuery(SqlInfoBuilder.buildUpdateSqlInfo(table, obj2, strArr)); } } else { return; } } else { TableEntity table2 = getTable(obj.getClass()); if (!table2.tableIsExists()) { endTransaction(); return; } execNonQuery(SqlInfoBuilder.buildUpdateSqlInfo(table2, obj, strArr)); } setTransactionSuccessful(); endTransaction(); } finally { endTransaction(); } } @Override // sjm.xuitls.DbManager public int update(Class<?> cls, WhereBuilder whereBuilder, KeyValue... keyValueArr) throws DbException { TableEntity table = getTable(cls); if (!table.tableIsExists()) { return 0; } try { beginTransaction(); int executeUpdateDelete = executeUpdateDelete(SqlInfoBuilder.buildUpdateSqlInfo(table, whereBuilder, keyValueArr)); setTransactionSuccessful(); return executeUpdateDelete; } finally { endTransaction(); } } @Override // sjm.xuitls.DbManager public <T> T findById(Class<T> cls, Object obj) throws DbException { Cursor execQuery; TableEntity<T> table = getTable(cls); if (table.tableIsExists() && (execQuery = execQuery(Selector.from(table).where(table.getId().getName(), "=", obj).limit(1).toString())) != null) { try { if (execQuery.moveToNext()) { T t = (T) CursorUtils.getEntity(table, execQuery); IOUtil.closeQuietly(execQuery); return t; } IOUtil.closeQuietly(execQuery); } catch (Throwable th) { IOUtil.closeQuietly(execQuery); throw th; } } return null; } @Override // sjm.xuitls.DbManager public <T> T findFirst(Class<T> cls) throws DbException { return selector(cls).findFirst(); } @Override // sjm.xuitls.DbManager public <T> List<T> findAll(Class<T> cls) throws DbException { return selector(cls).findAll(); } @Override // sjm.xuitls.DbManager public <T> Selector<T> selector(Class<T> cls) throws DbException { return Selector.from(getTable(cls)); } @Override // sjm.xuitls.DbManager public DbModel findDbModelFirst(SqlInfo sqlInfo) throws DbException { Cursor execQuery = execQuery(sqlInfo); if (execQuery == null) { return null; } try { if (execQuery.moveToNext()) { DbModel dbModel = CursorUtils.getDbModel(execQuery); IOUtil.closeQuietly(execQuery); return dbModel; } IOUtil.closeQuietly(execQuery); return null; } catch (Throwable th) { IOUtil.closeQuietly(execQuery); throw th; } } @Override // sjm.xuitls.DbManager public List<DbModel> findDbModelAll(SqlInfo sqlInfo) throws DbException { ArrayList arrayList = new ArrayList(); Cursor execQuery = execQuery(sqlInfo); if (execQuery != null) { while (execQuery.moveToNext()) { try { arrayList.add(CursorUtils.getDbModel(execQuery)); } catch (Throwable th) { IOUtil.closeQuietly(execQuery); throw th; } } IOUtil.closeQuietly(execQuery); } return arrayList; } private SQLiteDatabase openOrCreateDatabase(DbManager.DaoConfig daoConfig2) { File dbDir = daoConfig2.getDbDir(); if (dbDir == null || (!dbDir.exists() && !dbDir.mkdirs())) { return x.app().openOrCreateDatabase(daoConfig2.getDbName(), 0, null); } return SQLiteDatabase.openOrCreateDatabase(new File(dbDir, daoConfig2.getDbName()), (SQLiteDatabase.CursorFactory) null); } private void saveOrUpdateWithoutTransaction(TableEntity<?> tableEntity, Object obj) throws DbException { ColumnEntity id = tableEntity.getId(); if (!id.isAutoId()) { execNonQuery(SqlInfoBuilder.buildReplaceSqlInfo(tableEntity, obj)); } else if (id.getColumnValue(obj) != null) { execNonQuery(SqlInfoBuilder.buildUpdateSqlInfo(tableEntity, obj, new String[0])); } else { saveBindingIdWithoutTransaction(tableEntity, obj); } } private boolean saveBindingIdWithoutTransaction(TableEntity<?> tableEntity, Object obj) throws DbException { ColumnEntity id = tableEntity.getId(); if (id.isAutoId()) { execNonQuery(SqlInfoBuilder.buildInsertSqlInfo(tableEntity, obj)); long lastAutoIncrementId = getLastAutoIncrementId(tableEntity.getName()); if (lastAutoIncrementId == -1) { return false; } id.setAutoIdValue(obj, lastAutoIncrementId); return true; } execNonQuery(SqlInfoBuilder.buildInsertSqlInfo(tableEntity, obj)); return true; } private long getLastAutoIncrementId(String str) throws DbException { Cursor execQuery = execQuery("SELECT seq FROM sqlite_sequence WHERE name='" + str + "' LIMIT 1"); long j = -1; if (execQuery != null) { try { if (execQuery.moveToNext()) { j = execQuery.getLong(0); } IOUtil.closeQuietly(execQuery); } catch (Throwable th) { IOUtil.closeQuietly(execQuery); throw th; } } return j; } @Override // java.io.Closeable, sjm.xuitls.DbManager, java.lang.AutoCloseable public void close() throws IOException { HashMap<DbManager.DaoConfig, DbManagerImpl> hashMap = DAO_MAP; if (hashMap.containsKey(this.daoConfig)) { hashMap.remove(this.daoConfig); this.database.close(); } } private void beginTransaction() { if (!this.allowTransaction) { return; } if (Build.VERSION.SDK_INT < 16 || !this.database.isWriteAheadLoggingEnabled()) { this.database.beginTransaction(); } else { this.database.beginTransactionNonExclusive(); } } private void setTransactionSuccessful() { if (this.allowTransaction) { this.database.setTransactionSuccessful(); } } private void endTransaction() { if (this.allowTransaction) { this.database.endTransaction(); } } @Override // sjm.xuitls.DbManager public int executeUpdateDelete(SqlInfo sqlInfo) throws DbException { SQLiteStatement sQLiteStatement = null; try { sQLiteStatement = sqlInfo.buildStatement(this.database); int executeUpdateDelete = sQLiteStatement.executeUpdateDelete(); if (sQLiteStatement != null) { try { sQLiteStatement.releaseReference(); } catch (Throwable th) { LogUtil.e(th.getMessage(), th); } } return executeUpdateDelete; } catch (Throwable th2) { if (sQLiteStatement != null) { try { sQLiteStatement.releaseReference(); } catch (Throwable th3) { LogUtil.e(th3.getMessage(), th3); } } throw th2; } } @Override // sjm.xuitls.DbManager public int executeUpdateDelete(String str) throws DbException { SQLiteStatement sQLiteStatement = null; try { sQLiteStatement = this.database.compileStatement(str); int executeUpdateDelete = sQLiteStatement.executeUpdateDelete(); if (sQLiteStatement != null) { try { sQLiteStatement.releaseReference(); } catch (Throwable th) { LogUtil.e(th.getMessage(), th); } } return executeUpdateDelete; } catch (Throwable th2) { if (sQLiteStatement != null) { try { sQLiteStatement.releaseReference(); } catch (Throwable th3) { LogUtil.e(th3.getMessage(), th3); } } throw th2; } } @Override // sjm.xuitls.DbManager public void execNonQuery(SqlInfo sqlInfo) throws DbException { SQLiteStatement sQLiteStatement = null; try { sQLiteStatement = sqlInfo.buildStatement(this.database); sQLiteStatement.execute(); if (sQLiteStatement != null) { try { sQLiteStatement.releaseReference(); } catch (Throwable th) { LogUtil.e(th.getMessage(), th); } } } catch (Throwable th2) { if (sQLiteStatement != null) { try { sQLiteStatement.releaseReference(); } catch (Throwable th3) { LogUtil.e(th3.getMessage(), th3); } } throw th2; } } @Override // sjm.xuitls.DbManager public void execNonQuery(String str) throws DbException { try { this.database.execSQL(str); } catch (Throwable th) { throw new DbException(th); } } @Override // sjm.xuitls.DbManager public Cursor execQuery(SqlInfo sqlInfo) throws DbException { try { return this.database.rawQuery(sqlInfo.getSql(), sqlInfo.getBindArgsAsStrArray()); } catch (Throwable th) { throw new DbException(th); } } @Override // sjm.xuitls.DbManager public Cursor execQuery(String str) throws DbException { try { return this.database.rawQuery(str, null); } catch (Throwable th) { throw new DbException(th); } } }