]> git.ktnx.net Git - mobile-ledger.git/blobdiff - app/src/main/java/net/ktnx/mobileledger/async/RetrieveTransactionsTask.java
proper transaction parsing progress
[mobile-ledger.git] / app / src / main / java / net / ktnx / mobileledger / async / RetrieveTransactionsTask.java
index 5360cd006e694acef276612afed88724e56d14c6..ac9ec5093e54ece20790e6107f8fe2d593c5d9af 100644 (file)
@@ -36,14 +36,12 @@ import net.ktnx.mobileledger.model.LedgerAccount;
 import net.ktnx.mobileledger.model.LedgerTransaction;
 import net.ktnx.mobileledger.model.LedgerTransactionAccount;
 import net.ktnx.mobileledger.model.MobileLedgerProfile;
-import net.ktnx.mobileledger.ui.activity.MainActivity;
 import net.ktnx.mobileledger.utils.NetworkUtil;
 
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
-import java.lang.ref.WeakReference;
 import java.net.HttpURLConnection;
 import java.net.MalformedURLException;
 import java.net.URLDecoder;
@@ -72,15 +70,13 @@ public class RetrieveTransactionsTask
     private static final Pattern reEnd = Pattern.compile("\\bid=\"addmodal\"");
     private static final Pattern reDecimalPoint = Pattern.compile("\\.\\d\\d?$");
     private static final Pattern reDecimalComma = Pattern.compile(",\\d\\d?$");
-    private WeakReference<MainActivity> contextRef;
     // %3A is '='
     private Pattern reAccountName = Pattern.compile("/register\\?q=inacct%3A([a-zA-Z0-9%]+)\"");
     private Pattern reAccountValue = Pattern.compile(
             "<span class=\"[^\"]*\\bamount\\b[^\"]*\">\\s*([-+]?[\\d.,]+)(?:\\s+(\\S+))?</span>");
     private MobileLedgerProfile profile;
-    public RetrieveTransactionsTask(WeakReference<MainActivity> contextRef,
-                                    @NonNull MobileLedgerProfile profile) {
-        this.contextRef = contextRef;
+    private int expectedPostingsCount = -1;
+    public RetrieveTransactionsTask(@NonNull MobileLedgerProfile profile) {
         this.profile = profile;
     }
     private static void L(String msg) {
@@ -116,38 +112,28 @@ public class RetrieveTransactionsTask
     @Override
     protected void onProgressUpdate(Progress... values) {
         super.onProgressUpdate(values);
-        MainActivity context = getContext();
-        if (context == null)
-            return;
-        context.onRetrieveProgress(values[0]);
-    }
-    @Override
-    protected void onPreExecute() {
-        super.onPreExecute();
-        MainActivity context = getContext();
-        if (context == null)
-            return;
-        context.onRetrieveStart();
+        Data.backgroundTaskProgress.postValue(values[0]);
     }
     @Override
     protected void onPostExecute(String error) {
         super.onPostExecute(error);
-        MainActivity context = getContext();
-        if (context == null)
-            return;
-        context.onRetrieveDone(error);
+        Progress progress = new Progress();
+        progress.setState(ProgressState.FINISHED);
+        progress.setError(error);
+        onProgressUpdate(progress);
     }
     @Override
     protected void onCancelled() {
         super.onCancelled();
-        MainActivity context = getContext();
-        if (context == null)
-            return;
-        context.onRetrieveDone(null);
+        Progress progress = new Progress();
+        progress.setState(ProgressState.FINISHED);
+        onProgressUpdate(progress);
     }
     private String retrieveTransactionListLegacy() throws IOException, HTTPException {
-        Progress progress = new Progress();
-        int maxTransactionId = Progress.INDETERMINATE;
+        Progress progress = Progress.indeterminate();
+        progress.setState(ProgressState.RUNNING);
+        progress.setTotal(expectedPostingsCount);
+        int maxTransactionId = -1;
         ArrayList<LedgerAccount> list = new ArrayList<>();
         HashMap<String, LedgerAccount> map = new HashMap<>();
         ArrayList<LedgerAccount> displayed = new ArrayList<>();
@@ -279,7 +265,7 @@ public class RetrieveTransactionsTask
                             progress.setProgress(++processedTransactionCount);
                             if (maxTransactionId < transactionId)
                                 maxTransactionId = transactionId;
-                            if ((progress.getTotal() == Progress.INDETERMINATE) ||
+                            if ((progress.isIndeterminate()) ||
                                 (progress.getTotal() < transactionId))
                                 progress.setTotal(transactionId);
                             publishProgress(progress);
@@ -387,8 +373,6 @@ public class RetrieveTransactionsTask
         return acc;
     }
     private boolean retrieveAccountList() throws IOException, HTTPException {
-        Progress progress = new Progress();
-
         HttpURLConnection http = NetworkUtil.prepareConnection(profile, "accounts");
         http.setAllowUserInteraction(false);
         switch (http.getResponseCode()) {
@@ -399,7 +383,7 @@ public class RetrieveTransactionsTask
             default:
                 throw new HTTPException(http.getResponseCode(), http.getResponseMessage());
         }
-        publishProgress(progress);
+        publishProgress(Progress.indeterminate());
         SQLiteDatabase db = App.getDatabase();
         ArrayList<LedgerAccount> list = new ArrayList<>();
         HashMap<String, LedgerAccount> map = new HashMap<>();
@@ -411,6 +395,7 @@ public class RetrieveTransactionsTask
                 throw new IOException(String.format("HTTP error %d", http.getResponseCode()));
 
             AccountListParser parser = new AccountListParser(resp);
+            expectedPostingsCount = 0;
 
             while (true) {
                 throwIfCancelled();
@@ -418,7 +403,7 @@ public class RetrieveTransactionsTask
                 if (parsedAccount == null) {
                     break;
                 }
-
+                expectedPostingsCount += parsedAccount.getAnumpostings();
                 final String accName = parsedAccount.getAname();
                 LedgerAccount acc = map.get(accName);
                 if (acc != null)
@@ -480,6 +465,7 @@ public class RetrieveTransactionsTask
     private boolean retrieveTransactionList() throws IOException, ParseException, HTTPException {
         Progress progress = new Progress();
         int maxTransactionId = Data.transactions.size();
+        progress.setTotal(expectedPostingsCount);
 
         HttpURLConnection http = NetworkUtil.prepareConnection(profile, "transactions");
         http.setAllowUserInteraction(false);
@@ -498,7 +484,7 @@ public class RetrieveTransactionsTask
 
             TransactionListParser parser = new TransactionListParser(resp);
 
-            int processedTransactionCount = 0;
+            int processedPostings = 0;
 
             while (true) {
                 throwIfCancelled();
@@ -510,7 +496,8 @@ public class RetrieveTransactionsTask
                 LedgerTransaction transaction = parsedTransaction.asLedgerTransaction();
                 trList.add(transaction);
 
-                progress.setProgress(++processedTransactionCount);
+                progress.setProgress(processedPostings += transaction.getAccounts()
+                                                                     .size());
                 publishProgress(progress);
             }
 
@@ -554,9 +541,6 @@ public class RetrieveTransactionsTask
             Data.backgroundTaskFinished();
         }
     }
-    private MainActivity getContext() {
-        return contextRef.get();
-    }
     private void throwIfCancelled() {
         if (isCancelled())
             throw new OperationCanceledException(null);
@@ -566,28 +550,72 @@ public class RetrieveTransactionsTask
         EXPECTING_TRANSACTION_DESCRIPTION, EXPECTING_TRANSACTION_DETAILS
     }
 
+    public enum ProgressState {STARTING, RUNNING, FINISHED}
+
     public static class Progress {
-        public static final int INDETERMINATE = -1;
         private int progress;
         private int total;
+        private ProgressState state = ProgressState.RUNNING;
+        private String error = null;
+        private boolean indeterminate;
         Progress() {
-            this(INDETERMINATE, INDETERMINATE);
+            indeterminate = true;
         }
         Progress(int progress, int total) {
+            this.indeterminate = false;
             this.progress = progress;
             this.total = total;
         }
+        public static Progress indeterminate() {
+            return new Progress();
+        }
+        public static Progress finished(String error) {
+            Progress p = new Progress();
+            p.setState(ProgressState.FINISHED);
+            p.setError(error);
+            return p;
+        }
         public int getProgress() {
+            ensureState(ProgressState.RUNNING);
             return progress;
         }
         protected void setProgress(int progress) {
             this.progress = progress;
+            this.state = ProgressState.RUNNING;
         }
         public int getTotal() {
+            ensureState(ProgressState.RUNNING);
             return total;
         }
         protected void setTotal(int total) {
             this.total = total;
+            state = ProgressState.RUNNING;
+            indeterminate = total == -1;
+        }
+        private void ensureState(ProgressState wanted) {
+            if (state != wanted)
+                throw new IllegalStateException(
+                        String.format("Bad state: %s, expected %s", state, wanted));
+        }
+        public ProgressState getState() {
+            return state;
+        }
+        public void setState(ProgressState state) {
+            this.state = state;
+        }
+        public String getError() {
+            ensureState(ProgressState.FINISHED);
+            return error;
+        }
+        public void setError(String error) {
+            this.error = error;
+            state = ProgressState.FINISHED;
+        }
+        public boolean isIndeterminate() {
+            return indeterminate;
+        }
+        public void setIndeterminate(boolean indeterminate) {
+            this.indeterminate = indeterminate;
         }
     }