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=8a9a8f62e8e98c4917aab9e383828c48f496771d;hp=aeb49a5f104b9ebcebda479b961fe83e855464db;hb=6c58c1072c9af6ea0d0f52baeae7f95ba7f7ee2f;hpb=6b740c280c79b0170321f533747cdbfc3e179a29 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 aeb49a5f..8a9a8f62 100644 --- a/app/src/main/java/net/ktnx/mobileledger/async/RetrieveTransactionsTask.java +++ b/app/src/main/java/net/ktnx/mobileledger/async/RetrieveTransactionsTask.java @@ -17,15 +17,18 @@ package net.ktnx.mobileledger.async; +import android.annotation.SuppressLint; import android.content.Context; import android.content.SharedPreferences; import android.database.sqlite.SQLiteDatabase; import android.os.AsyncTask; +import android.util.Log; import net.ktnx.mobileledger.R; +import net.ktnx.mobileledger.TransactionListActivity; import net.ktnx.mobileledger.model.LedgerTransaction; import net.ktnx.mobileledger.model.LedgerTransactionItem; -import net.ktnx.mobileledger.utils.MobileLedgerDatabase; +import net.ktnx.mobileledger.utils.MLDB; import net.ktnx.mobileledger.utils.NetworkUtil; import java.io.BufferedReader; @@ -40,73 +43,65 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -class RetrieveTransactionsTask extends AsyncTask { - class Params { - static final int DEFAULT_LIMIT = 100; - private SharedPreferences backendPref; - private String accountsRoot; - private int limit; - - Params(SharedPreferences backendPref) { - this.backendPref = backendPref; - this.accountsRoot = null; - this.limit = DEFAULT_LIMIT; - } - Params(SharedPreferences backendPref, String accountsRoot) { - this(backendPref, accountsRoot, DEFAULT_LIMIT); - } - Params(SharedPreferences backendPref, String accountsRoot, int limit) { - this.backendPref = backendPref; - this.accountsRoot = accountsRoot; - this.limit = limit; - } - String getAccountsRoot() { - return accountsRoot; - } - SharedPreferences getBackendPref() { - return backendPref; - } - int getLimit() { - return limit; - } - } - private static final Pattern transactionStartPattern = Pattern.compile("([\\d.-]+)"); +public class RetrieveTransactionsTask extends + AsyncTask { + private static final Pattern transactionStartPattern = Pattern.compile("([\\d.-]+)"); private static final Pattern transactionDescriptionPattern = Pattern.compile(" contextRef; + private static final Pattern endPattern = Pattern.compile("\\bid=\"addmodal\""); + protected WeakReference contextRef; protected int error; + private boolean success; + public RetrieveTransactionsTask(WeakReference contextRef) { + this.contextRef = contextRef; + } + private static final void L(String msg) { + Log.d("transaction-parser", msg); + } + @Override + protected void onProgressUpdate(Progress... values) { + super.onProgressUpdate(values); + TransactionListActivity context = getContext(); + if (context == null) return; + context.onRetrieveProgress(values[0]); + } + @Override + protected void onPreExecute() { + super.onPreExecute(); + TransactionListActivity context = getContext(); + if (context == null) return; + context.onRetrieveStart(); + } + @Override + protected void onPostExecute(Void aVoid) { + super.onPostExecute(aVoid); + TransactionListActivity context = getContext(); + if (context == null) return; + context.onRetrieveDone(success); + } + @SuppressLint("DefaultLocale") @Override protected Void doInBackground(Params... params) { + Progress progress = new Progress(); + success = false; try { HttpURLConnection http = NetworkUtil.prepare_connection(params[0].getBackendPref(), "journal"); http.setAllowUserInteraction(false); - publishProgress(0); + publishProgress(progress); Context ctx = contextRef.get(); if (ctx == null) return null; - try (MobileLedgerDatabase dbh = new MobileLedgerDatabase(ctx)) { - try (SQLiteDatabase db = dbh.getWritableDatabase()) { + try (SQLiteDatabase db = MLDB.getWritableDatabase(ctx)) { try (InputStream resp = http.getInputStream()) { if (http.getResponseCode() != 200) throw new IOException( String.format("HTTP error %d", http.getResponseCode())); db.beginTransaction(); try { - String root = params[0].getAccountsRoot(); - if (root == null) db.execSQL("DELETE FROM transaction_history;"); - else { - StringBuilder sql = new StringBuilder(); - sql.append("DELETE FROM transaction_history "); - sql.append( - "where id in (select transactions.id from transactions "); - sql.append("join transaction_accounts "); - sql.append( - "on transactions.id=transaction_accounts.transaction_id "); - sql.append("where transaction_accounts.account_name like ?||'%'"); - db.execSQL(sql.toString(), new String[]{root}); - } + db.execSQL("DELETE FROM transactions;"); + db.execSQL("DELETE FROM transaction_accounts"); int state = ParserState.EXPECTING_JOURNAL; String line; @@ -114,48 +109,76 @@ class RetrieveTransactionsTask extends AsyncTaskGeneral Journal")) + case ParserState.EXPECTING_JOURNAL: + if (line.equals("

General Journal

")) { state = ParserState.EXPECTING_TRANSACTION; - continue; - } - case ParserState.EXPECTING_TRANSACTION: { - Matcher m = transactionStartPattern.matcher(line); + L("→ expecting transaction"); + } + break; + case ParserState.EXPECTING_TRANSACTION: + m = transactionStartPattern.matcher(line); if (m.find()) { - transactionId = m.group(1); + transactionId = Integer.valueOf(m.group(1)); state = ParserState.EXPECTING_TRANSACTION_DESCRIPTION; + L(String.format("found transaction %d → expecting " + + "description", transactionId)); + progress.setProgress(++transactionCount); + if (progress.getTotal() == Progress.INDETERMINATE) + progress.setTotal(transactionId); + publishProgress(progress); + } + m = endPattern.matcher(line); + if (m.find()) { + L("--- transaction list complete ---"); + success = true; + break LINES; } - } - case ParserState.EXPECTING_TRANSACTION_DESCRIPTION: { - Matcher m = transactionDescriptionPattern.matcher(line); + break; + case ParserState.EXPECTING_TRANSACTION_DESCRIPTION: + m = transactionDescriptionPattern.matcher(line); if (m.find()) { - if (transactionId == null) + if (transactionId == 0) throw new TransactionParserException( - "Transaction Id is null while expecting description"); + "Transaction Id is 0 while expecting " + + "description"); transaction = new LedgerTransaction(transactionId, m.group(1), m.group(2)); state = ParserState.EXPECTING_TRANSACTION_DETAILS; + L(String.format("transaction %d created for %s (%s) →" + + " expecting details", transactionId, + m.group(1), m.group(2))); } - } - case ParserState.EXPECTING_TRANSACTION_DETAILS: { - if (transaction == null) - throw new TransactionParserException( - "Transaction is null while expecting details"); + break; + case ParserState.EXPECTING_TRANSACTION_DETAILS: if (line.isEmpty()) { // transaction data collected transaction.insertInto(db); state = ParserState.EXPECTING_TRANSACTION; - publishProgress(++transactionCount); + L(String.format("transaction %s saved → expecting " + + "transaction", transaction.getId())); + +// sounds like a good idea, but transaction-1 may not be the first one chronologically +// for example, when you add the initial seeding transaction after entering some others +// if (transactionId == 1) { +// L("This was the initial transaction. Terminating " + +// "parser"); +// break LINES; +// } } else { - Matcher m = transactionDetailsPattern.matcher(line); + m = transactionDetailsPattern.matcher(line); if (m.find()) { String acc_name = m.group(1); String amount = m.group(2); @@ -163,18 +186,19 @@ class RetrieveTransactionsTask extends AsyncTask getContextRef() { - return contextRef; + TransactionListActivity getContext() { + return contextRef.get(); + } + + public static class Params { + static final int DEFAULT_LIMIT = 100; + private SharedPreferences backendPref; + private String accountsRoot; + private int limit; + + public Params(SharedPreferences backendPref) { + this.backendPref = backendPref; + this.accountsRoot = null; + this.limit = DEFAULT_LIMIT; + } + Params(SharedPreferences backendPref, String accountsRoot) { + this(backendPref, accountsRoot, DEFAULT_LIMIT); + } + Params(SharedPreferences backendPref, String accountsRoot, int limit) { + this.backendPref = backendPref; + this.accountsRoot = accountsRoot; + this.limit = limit; + } + String getAccountsRoot() { + return accountsRoot; + } + SharedPreferences getBackendPref() { + return backendPref; + } + int getLimit() { + return limit; + } + } + + public class Progress { + public static final int INDETERMINATE = -1; + private int progress; + private int total; + Progress() { + this(INDETERMINATE, INDETERMINATE); + } + Progress(int progress, int total) { + this.progress = progress; + this.total = total; + } + public int getProgress() { + return progress; + } + protected void setProgress(int progress) { + this.progress = progress; + } + public int getTotal() { + return total; + } + protected void setTotal(int total) { + this.total = total; + } } private class TransactionParserException extends IllegalStateException {