X-Git-Url: https://git.ktnx.net/?p=mobile-ledger.git;a=blobdiff_plain;f=app%2Fsrc%2Fmain%2Fjava%2Fnet%2Fktnx%2Fmobileledger%2Fasync%2FRetrieveTransactionsTask.java;h=6a2700f36480c870d1fedc01517107c785bf2d83;hp=8f1a764b386aa4db91a901fcde5688ec346dd6d6;hb=83cac114e375728080194fb09758b49c50a8119b;hpb=010406b05a5a4f8447af34187afef8c1e78a4552 diff --git a/app/src/main/java/net/ktnx/mobileledger/async/RetrieveTransactionsTask.java b/app/src/main/java/net/ktnx/mobileledger/async/RetrieveTransactionsTask.java index 8f1a764b..6a2700f3 100644 --- a/app/src/main/java/net/ktnx/mobileledger/async/RetrieveTransactionsTask.java +++ b/app/src/main/java/net/ktnx/mobileledger/async/RetrieveTransactionsTask.java @@ -112,7 +112,7 @@ public class RetrieveTransactionsTask int maxTransactionId = Progress.INDETERMINATE; ArrayList accountList = new ArrayList<>(); HashMap accountNames = new HashMap<>(); - LedgerAccount lastAccount = null; + LedgerAccount lastAccount = null, prevAccount = null; boolean onlyStarred = Data.optShowOnlyStarred.get(); HttpURLConnection http = NetworkUtil.prepareConnection(profile, "journal"); @@ -124,7 +124,7 @@ public class RetrieveTransactionsTask default: throw new HTTPException(http.getResponseCode(), http.getResponseMessage()); } - try (SQLiteDatabase db = MLDB.getWritableDatabase()) { + try (SQLiteDatabase db = MLDB.getDatabase()) { try (InputStream resp = http.getInputStream()) { if (http.getResponseCode() != 200) throw new IOException(String.format("HTTP error %d", http.getResponseCode())); @@ -159,7 +159,13 @@ public class RetrieveTransactionsTask if (line.equals("

General Journal

")) { state = ParserState.EXPECTING_TRANSACTION; L("→ expecting transaction"); - Data.accounts.set(accountList); + // commit the current transaction and start a new one + // the account list in the UI should reflect the (committed) + // state of the database + db.setTransactionSuccessful(); + db.endTransaction(); + Data.accounts.setList(accountList); + db.beginTransaction(); continue; } m = reAccountName.matcher(line); @@ -169,13 +175,15 @@ public class RetrieveTransactionsTask acct_name = acct_name.replace("\"", ""); L(String.format("found account: %s", acct_name)); + prevAccount = lastAccount; lastAccount = profile.tryLoadAccount(db, acct_name); if (lastAccount == null) lastAccount = new LedgerAccount(acct_name); - else - lastAccount.removeAmounts(); + else lastAccount.removeAmounts(); profile.storeAccount(db, lastAccount); + if (prevAccount != null) prevAccount + .setHasSubAccounts(prevAccount.isParentOf(lastAccount)); // make sure the parent account(s) are present, // synthesising them if necessary String parentName = lastAccount.getParentName(); @@ -191,15 +199,17 @@ public class RetrieveTransactionsTask String aName = toAppend.pop(); LedgerAccount acc = new LedgerAccount(aName); acc.setHiddenByStar(lastAccount.isHiddenByStar()); - if (!onlyStarred || !acc.isHiddenByStar()) - accountList.add(acc); + acc.setHasSubAccounts(true); + if ((!onlyStarred || !acc.isHiddenByStar()) && + acc.isVisible(accountList)) accountList.add(acc); L(String.format("gap-filling with %s", aName)); accountNames.put(aName, null); profile.storeAccount(db, acc); } } - if (!onlyStarred || !lastAccount.isHiddenByStar()) + if ((!onlyStarred || !lastAccount.isHiddenByStar()) && + lastAccount.isVisible(accountList)) accountList.add(lastAccount); accountNames.put(acct_name, null); @@ -379,44 +389,59 @@ public class RetrieveTransactionsTask throw new HTTPException(http.getResponseCode(), http.getResponseMessage()); } publishProgress(progress); - try (SQLiteDatabase db = MLDB.getWritableDatabase()) { - try (InputStream resp = http.getInputStream()) { - if (http.getResponseCode() != 200) - throw new IOException(String.format("HTTP error %d", http.getResponseCode())); + SQLiteDatabase db = MLDB.getDatabase(); + ArrayList accountList = new ArrayList<>(); + boolean listFilledOK = false; + try (InputStream resp = http.getInputStream()) { + if (http.getResponseCode() != 200) + throw new IOException(String.format("HTTP error %d", http.getResponseCode())); - db.beginTransaction(); - try { - profile.markAccountsAsNotPresent(db); + db.beginTransaction(); + try { + profile.markAccountsAsNotPresent(db); - AccountListParser parser = new AccountListParser(resp); - ArrayList accountList = new ArrayList<>(); + AccountListParser parser = new AccountListParser(resp); - while (true) { - throwIfCancelled(); - ParsedLedgerAccount parsedAccount = parser.nextAccount(); - if (parsedAccount == null) break; - - LedgerAccount acc = new LedgerAccount(parsedAccount.getAname()); - profile.storeAccount(db, acc); - for (ParsedBalance b : parsedAccount.getAebalance()) { - profile.storeAccountValue(db, acc.getName(), b.getAcommodity(), - b.getAquantity().asFloat()); - } + LedgerAccount prevAccount = null; - accountList.add(acc); - } + while (true) { throwIfCancelled(); + ParsedLedgerAccount parsedAccount = parser.nextAccount(); + if (parsedAccount == null) break; - profile.deleteNotPresentAccounts(db); - throwIfCancelled(); - db.setTransactionSuccessful(); - Data.accounts.set(accountList); - } - finally { - db.endTransaction(); + LedgerAccount acc = profile.tryLoadAccount(db, parsedAccount.getAname()); + if (acc == null) acc = new LedgerAccount(parsedAccount.getAname()); + else acc.removeAmounts(); + + profile.storeAccount(db, acc); + for (ParsedBalance b : parsedAccount.getAebalance()) { + profile.storeAccountValue(db, acc.getName(), b.getAcommodity(), + b.getAquantity().asFloat()); + } + + if (acc.isVisible(accountList)) accountList.add(acc); + + if (prevAccount != null) { + prevAccount.setHasSubAccounts( + acc.getName().startsWith(prevAccount.getName() + ":")); + } + + prevAccount = acc; } + throwIfCancelled(); + + profile.deleteNotPresentAccounts(db); + throwIfCancelled(); + db.setTransactionSuccessful(); + listFilledOK = true; + } + finally { + db.endTransaction(); } } + // should not be set in the DB transaction, because of a possible deadlock + // with the main and DbOpQueueRunner threads + if (listFilledOK) Data.accounts.setList(accountList); return true; } @@ -436,62 +461,61 @@ public class RetrieveTransactionsTask default: throw new HTTPException(http.getResponseCode(), http.getResponseMessage()); } - try (SQLiteDatabase db = MLDB.getWritableDatabase()) { - try (InputStream resp = http.getInputStream()) { - if (http.getResponseCode() != 200) - throw new IOException(String.format("HTTP error %d", http.getResponseCode())); - throwIfCancelled(); - db.beginTransaction(); - try { - profile.markTransactionsAsNotPresent(db); + SQLiteDatabase db = MLDB.getDatabase(); + try (InputStream resp = http.getInputStream()) { + if (http.getResponseCode() != 200) + throw new IOException(String.format("HTTP error %d", http.getResponseCode())); + throwIfCancelled(); + db.beginTransaction(); + try { + profile.markTransactionsAsNotPresent(db); - int matchedTransactionsCount = 0; - TransactionListParser parser = new TransactionListParser(resp); + int matchedTransactionsCount = 0; + TransactionListParser parser = new TransactionListParser(resp); - int processedTransactionCount = 0; + int processedTransactionCount = 0; - while (true) { - throwIfCancelled(); - ParsedLedgerTransaction parsedTransaction = parser.nextTransaction(); - throwIfCancelled(); - if (parsedTransaction == null) break; - LedgerTransaction transaction = parsedTransaction.asLedgerTransaction(); - if (transaction.existsInDb(db)) { - profile.markTransactionAsPresent(db, transaction); - matchedTransactionsCount++; - - if (matchedTransactionsCount == MATCHING_TRANSACTIONS_LIMIT) { - profile.markTransactionsBeforeTransactionAsPresent(db, transaction); - progress.setTotal(progress.getProgress()); - publishProgress(progress); - db.setTransactionSuccessful(); - profile.setLastUpdateStamp(); - return true; - } - } - else { - profile.storeTransaction(db, transaction); - matchedTransactionsCount = 0; - progress.setTotal(maxTransactionId); + while (true) { + throwIfCancelled(); + ParsedLedgerTransaction parsedTransaction = parser.nextTransaction(); + throwIfCancelled(); + if (parsedTransaction == null) break; + LedgerTransaction transaction = parsedTransaction.asLedgerTransaction(); + if (transaction.existsInDb(db)) { + profile.markTransactionAsPresent(db, transaction); + matchedTransactionsCount++; + + if (matchedTransactionsCount == MATCHING_TRANSACTIONS_LIMIT) { + profile.markTransactionsBeforeTransactionAsPresent(db, transaction); + progress.setTotal(progress.getProgress()); + publishProgress(progress); + db.setTransactionSuccessful(); + profile.setLastUpdateStamp(); + return true; } - - if ((progress.getTotal() == Progress.INDETERMINATE) || - (progress.getTotal() < transaction.getId())) - progress.setTotal(transaction.getId()); - - progress.setProgress(++processedTransactionCount); - publishProgress(progress); + } + else { + profile.storeTransaction(db, transaction); + matchedTransactionsCount = 0; + progress.setTotal(maxTransactionId); } - throwIfCancelled(); - profile.deleteNotPresentTransactions(db); - throwIfCancelled(); - db.setTransactionSuccessful(); - profile.setLastUpdateStamp(); - } - finally { - db.endTransaction(); + if ((progress.getTotal() == Progress.INDETERMINATE) || + (progress.getTotal() < transaction.getId())) + progress.setTotal(transaction.getId()); + + progress.setProgress(++processedTransactionCount); + publishProgress(progress); } + + throwIfCancelled(); + profile.deleteNotPresentTransactions(db); + throwIfCancelled(); + db.setTransactionSuccessful(); + profile.setLastUpdateStamp(); + } + finally { + db.endTransaction(); } }