From bcf517d0eae491de46b71a1e0f288852ca3d64df Mon Sep 17 00:00:00 2001 From: Damyan Ivanov Date: Sun, 20 Dec 2020 14:32:31 +0000 Subject: [PATCH] a step towards API-independent JSON parsing of accounts --- .../async/RetrieveTransactionsTask.java | 63 +++--------- .../mobileledger/json/AccountListParser.java | 98 +++++++++++++++++++ .../ktnx/mobileledger/json/ParsedBalance.java | 42 ++++++++ .../json/ParsedLedgerAccount.java | 46 +++++++++ .../ktnx/mobileledger/json/ParsedPrice.java | 81 +++++++++++++++ .../mobileledger/json/ParsedQuantity.java | 58 +++++++++++ .../json/v1_15/AccountListParser.java | 17 +--- .../json/v1_15/ParsedBalance.java | 19 +--- .../json/v1_15/ParsedLedgerAccount.java | 24 +---- .../json/v1_15/ParsedQuantity.java | 36 +------ 10 files changed, 341 insertions(+), 143 deletions(-) create mode 100644 app/src/main/java/net/ktnx/mobileledger/json/AccountListParser.java create mode 100644 app/src/main/java/net/ktnx/mobileledger/json/ParsedBalance.java create mode 100644 app/src/main/java/net/ktnx/mobileledger/json/ParsedLedgerAccount.java create mode 100644 app/src/main/java/net/ktnx/mobileledger/json/ParsedPrice.java create mode 100644 app/src/main/java/net/ktnx/mobileledger/json/ParsedQuantity.java 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 1d69fa29..85f76651 100644 --- a/app/src/main/java/net/ktnx/mobileledger/async/RetrieveTransactionsTask.java +++ b/app/src/main/java/net/ktnx/mobileledger/async/RetrieveTransactionsTask.java @@ -27,8 +27,6 @@ import androidx.annotation.NonNull; import net.ktnx.mobileledger.App; import net.ktnx.mobileledger.err.HTTPException; import net.ktnx.mobileledger.json.v1_15.AccountListParser; -import net.ktnx.mobileledger.json.v1_15.ParsedBalance; -import net.ktnx.mobileledger.json.v1_15.ParsedLedgerAccount; import net.ktnx.mobileledger.json.v1_15.ParsedLedgerTransaction; import net.ktnx.mobileledger.json.v1_15.TransactionListParser; import net.ktnx.mobileledger.model.Data; @@ -119,6 +117,9 @@ public class RetrieveTransactionsTask extends return null; } } + public MobileLedgerProfile getProfile() { + return profile; + } @Override protected void onProgressUpdate(Progress... values) { super.onProgressUpdate(values); @@ -356,9 +357,9 @@ public class RetrieveTransactionsTask extends throwIfCancelled(); } } - private @NonNull - LedgerAccount ensureAccountExists(String accountName, HashMap map, - ArrayList createdAccounts) { + @NonNull + public LedgerAccount ensureAccountExists(String accountName, HashMap map, + ArrayList createdAccounts) { LedgerAccount acc = map.get(accountName); if (acc != null) @@ -377,6 +378,9 @@ public class RetrieveTransactionsTask extends createdAccounts.add(acc); return acc; } + public void addNumberOfPostings(int number) { + expectedPostingsCount += number; + } private List retrieveAccountList() throws IOException, HTTPException { HttpURLConnection http = NetworkUtil.prepareConnection(profile, "accounts"); http.setAllowUserInteraction(false); @@ -406,53 +410,10 @@ public class RetrieveTransactionsTask extends while (true) { throwIfCancelled(); - ParsedLedgerAccount parsedAccount = parser.nextAccount(); - if (parsedAccount == null) { + LedgerAccount acc = parser.nextLedgerAccount(this, map); + if (acc == null) break; - } - expectedPostingsCount += parsedAccount.getAnumpostings(); - final String accName = parsedAccount.getAname(); - LedgerAccount acc = map.get(accName); - if (acc != null) - throw new RuntimeException( - String.format("Account '%s' already present", acc.getName())); - String parentName = LedgerAccount.extractParentName(accName); - ArrayList createdParents = new ArrayList<>(); - LedgerAccount parent; - if (parentName == null) { - parent = null; - } - else { - parent = ensureAccountExists(parentName, map, createdParents); - parent.setHasSubAccounts(true); - } - acc = new LedgerAccount(profile, accName, parent); list.add(acc); - map.put(accName, acc); - - String lastCurrency = null; - float lastCurrencyAmount = 0; - for (ParsedBalance b : parsedAccount.getAibalance()) { - throwIfCancelled(); - final String currency = b.getAcommodity(); - final float amount = b.getAquantity() - .asFloat(); - if (currency.equals(lastCurrency)) { - lastCurrencyAmount += amount; - } - else { - if (lastCurrency != null) { - acc.addAmount(lastCurrencyAmount, lastCurrency); - } - lastCurrency = currency; - lastCurrencyAmount = amount; - } - } - if (lastCurrency != null) { - acc.addAmount(lastCurrencyAmount, lastCurrency); - } - for (LedgerAccount p : createdParents) - acc.propagateAmountsTo(p); } throwIfCancelled(); } @@ -576,7 +537,7 @@ public class RetrieveTransactionsTask extends Data.backgroundTaskFinished(); } } - private void throwIfCancelled() { + public void throwIfCancelled() { if (isCancelled()) throw new OperationCanceledException(null); } diff --git a/app/src/main/java/net/ktnx/mobileledger/json/AccountListParser.java b/app/src/main/java/net/ktnx/mobileledger/json/AccountListParser.java new file mode 100644 index 00000000..053b1e90 --- /dev/null +++ b/app/src/main/java/net/ktnx/mobileledger/json/AccountListParser.java @@ -0,0 +1,98 @@ +/* + * Copyright © 2020 Damyan Ivanov. + * This file is part of MoLe. + * MoLe is free software: you can distribute it and/or modify it + * under the term of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your opinion), any later version. + * + * MoLe is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License terms for details. + * + * You should have received a copy of the GNU General Public License + * along with MoLe. If not, see . + */ + +package net.ktnx.mobileledger.json; + +import com.fasterxml.jackson.databind.MappingIterator; + +import net.ktnx.mobileledger.async.RetrieveTransactionsTask; +import net.ktnx.mobileledger.model.LedgerAccount; + +import java.util.ArrayList; +import java.util.HashMap; + +import static net.ktnx.mobileledger.utils.Logger.debug; + +abstract public class AccountListParser { + protected MappingIterator iterator; + + public ParsedLedgerAccount nextAccount() { + if (!iterator.hasNext()) + return null; + + ParsedLedgerAccount next = iterator.next(); + + if (next.getAname() + .equalsIgnoreCase("root")) + return nextAccount(); + + debug("accounts", String.format("Got account '%s' [v1.15]", next.getAname())); + return next; + } + public LedgerAccount nextLedgerAccount(RetrieveTransactionsTask task, + HashMap map) { + ParsedLedgerAccount parsedAccount = nextAccount(); + if (parsedAccount == null) + return null; + + task.addNumberOfPostings(parsedAccount.getAnumpostings()); + final String accName = parsedAccount.getAname(); + LedgerAccount acc = map.get(accName); + if (acc != null) + throw new RuntimeException( + String.format("Account '%s' already present", acc.getName())); + String parentName = LedgerAccount.extractParentName(accName); + ArrayList createdParents = new ArrayList<>(); + LedgerAccount parent; + if (parentName == null) { + parent = null; + } + else { + parent = task.ensureAccountExists(parentName, map, createdParents); + parent.setHasSubAccounts(true); + } + acc = new LedgerAccount(task.getProfile(), accName, parent); + map.put(accName, acc); + + String lastCurrency = null; + float lastCurrencyAmount = 0; + for (ParsedBalance b : parsedAccount.getAibalance()) { + task.throwIfCancelled(); + final String currency = b.getAcommodity(); + final float amount = b.getAquantity() + .asFloat(); + if (currency.equals(lastCurrency)) { + lastCurrencyAmount += amount; + } + else { + if (lastCurrency != null) { + acc.addAmount(lastCurrencyAmount, lastCurrency); + } + lastCurrency = currency; + lastCurrencyAmount = amount; + } + } + if (lastCurrency != null) { + acc.addAmount(lastCurrencyAmount, lastCurrency); + } + for (LedgerAccount p : createdParents) + acc.propagateAmountsTo(p); + + return acc; + } + +} diff --git a/app/src/main/java/net/ktnx/mobileledger/json/ParsedBalance.java b/app/src/main/java/net/ktnx/mobileledger/json/ParsedBalance.java new file mode 100644 index 00000000..49ee26d8 --- /dev/null +++ b/app/src/main/java/net/ktnx/mobileledger/json/ParsedBalance.java @@ -0,0 +1,42 @@ +/* + * Copyright © 2020 Damyan Ivanov. + * This file is part of MoLe. + * MoLe is free software: you can distribute it and/or modify it + * under the term of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your opinion), any later version. + * + * MoLe is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License terms for details. + * + * You should have received a copy of the GNU General Public License + * along with MoLe. If not, see . + */ + +package net.ktnx.mobileledger.json; + +import androidx.annotation.NonNull; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ParsedBalance { + private ParsedQuantity aquantity; + private String acommodity; + public ParsedQuantity getAquantity() { + return aquantity; + } + public void setAquantity(ParsedQuantity aquantity) { + this.aquantity = aquantity; + } + @NonNull + public String getAcommodity() { + return (acommodity == null) ? "" : acommodity; + } + public void setAcommodity(String acommodity) { + this.acommodity = acommodity; + } + +} diff --git a/app/src/main/java/net/ktnx/mobileledger/json/ParsedLedgerAccount.java b/app/src/main/java/net/ktnx/mobileledger/json/ParsedLedgerAccount.java new file mode 100644 index 00000000..aff57753 --- /dev/null +++ b/app/src/main/java/net/ktnx/mobileledger/json/ParsedLedgerAccount.java @@ -0,0 +1,46 @@ +/* + * Copyright © 2020 Damyan Ivanov. + * This file is part of MoLe. + * MoLe is free software: you can distribute it and/or modify it + * under the term of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your opinion), any later version. + * + * MoLe is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License terms for details. + * + * You should have received a copy of the GNU General Public License + * along with MoLe. If not, see . + */ + +package net.ktnx.mobileledger.json; + +import net.ktnx.mobileledger.json.ParsedBalance; + +import java.util.List; + +public class ParsedLedgerAccount { + private String aname; + private int anumpostings; + private List aibalance; + public String getAname() { + return aname; + } + public void setAname(String aname) { + this.aname = aname; + } + public int getAnumpostings() { + return anumpostings; + } + public void setAnumpostings(int anumpostings) { + this.anumpostings = anumpostings; + } + public List getAibalance() { + return aibalance; + } + public void setAibalance(List aibalance) { + this.aibalance = aibalance; + } +} diff --git a/app/src/main/java/net/ktnx/mobileledger/json/ParsedPrice.java b/app/src/main/java/net/ktnx/mobileledger/json/ParsedPrice.java new file mode 100644 index 00000000..3959d145 --- /dev/null +++ b/app/src/main/java/net/ktnx/mobileledger/json/ParsedPrice.java @@ -0,0 +1,81 @@ +/* + * Copyright © 2020 Damyan Ivanov. + * This file is part of MoLe. + * MoLe is free software: you can distribute it and/or modify it + * under the term of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your opinion), any later version. + * + * MoLe is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License terms for details. + * + * You should have received a copy of the GNU General Public License + * along with MoLe. If not, see . + */ + +package net.ktnx.mobileledger.json; + +import net.ktnx.mobileledger.json.v1_15.ParsedQuantity; +import net.ktnx.mobileledger.json.v1_15.ParsedStyle; + +public class ParsedPrice { + private String tag; + private Contents contents; + public ParsedPrice() { + tag = "NoPrice"; + } + public Contents getContents() { + return contents; + } + public void setContents(Contents contents) { + this.contents = contents; + } + public String getTag() { + return tag; + } + public void setTag(String tag) { + this.tag = tag; + } + private static class Contents { + private ParsedPrice aprice; + private net.ktnx.mobileledger.json.v1_15.ParsedQuantity aquantity; + private String acommodity; + private boolean aismultiplier; + private net.ktnx.mobileledger.json.v1_15.ParsedStyle astyle; + public Contents() { + acommodity = ""; + } + public ParsedPrice getAprice() { + return aprice; + } + public void setAprice(ParsedPrice aprice) { + this.aprice = aprice; + } + public net.ktnx.mobileledger.json.v1_15.ParsedQuantity getAquantity() { + return aquantity; + } + public void setAquantity(ParsedQuantity aquantity) { + this.aquantity = aquantity; + } + public String getAcommodity() { + return acommodity; + } + public void setAcommodity(String acommodity) { + this.acommodity = acommodity; + } + public boolean isAismultiplier() { + return aismultiplier; + } + public void setAismultiplier(boolean aismultiplier) { + this.aismultiplier = aismultiplier; + } + public net.ktnx.mobileledger.json.v1_15.ParsedStyle getAstyle() { + return astyle; + } + public void setAstyle(ParsedStyle astyle) { + this.astyle = astyle; + } + } +} diff --git a/app/src/main/java/net/ktnx/mobileledger/json/ParsedQuantity.java b/app/src/main/java/net/ktnx/mobileledger/json/ParsedQuantity.java new file mode 100644 index 00000000..20684795 --- /dev/null +++ b/app/src/main/java/net/ktnx/mobileledger/json/ParsedQuantity.java @@ -0,0 +1,58 @@ +/* + * Copyright © 2020 Damyan Ivanov. + * This file is part of MoLe. + * MoLe is free software: you can distribute it and/or modify it + * under the term of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your opinion), any later version. + * + * MoLe is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License terms for details. + * + * You should have received a copy of the GNU General Public License + * along with MoLe. If not, see . + */ + +package net.ktnx.mobileledger.json; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ParsedQuantity { + private long decimalMantissa; + private int decimalPlaces; + public ParsedQuantity() { + } + public ParsedQuantity(String input) { + parseString(input); + } + public long getDecimalMantissa() { + return decimalMantissa; + } + public void setDecimalMantissa(long decimalMantissa) { + this.decimalMantissa = decimalMantissa; + } + public int getDecimalPlaces() { + return decimalPlaces; + } + public void setDecimalPlaces(int decimalPlaces) { + this.decimalPlaces = decimalPlaces; + } + public float asFloat() { + return (float) (decimalMantissa * Math.pow(10, -decimalPlaces)); + } + public void parseString(String input) { + int pointPos = input.indexOf('.'); + if (pointPos >= 0) { + String integral = input.replace(".", ""); + decimalMantissa = Long.parseLong(integral); + decimalPlaces = input.length() - pointPos - 1; + } + else { + decimalMantissa = Long.parseLong(input); + decimalPlaces = 0; + } + } +} diff --git a/app/src/main/java/net/ktnx/mobileledger/json/v1_15/AccountListParser.java b/app/src/main/java/net/ktnx/mobileledger/json/v1_15/AccountListParser.java index d999b457..33c554c8 100644 --- a/app/src/main/java/net/ktnx/mobileledger/json/v1_15/AccountListParser.java +++ b/app/src/main/java/net/ktnx/mobileledger/json/v1_15/AccountListParser.java @@ -17,18 +17,13 @@ package net.ktnx.mobileledger.json.v1_15; -import com.fasterxml.jackson.databind.MappingIterator; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; import java.io.IOException; import java.io.InputStream; -import static net.ktnx.mobileledger.utils.Logger.debug; - -public class AccountListParser { - - private final MappingIterator iterator; +public class AccountListParser extends net.ktnx.mobileledger.json.AccountListParser { public AccountListParser(InputStream input) throws IOException { ObjectMapper mapper = new ObjectMapper(); @@ -36,14 +31,4 @@ public class AccountListParser { iterator = reader.readValues(input); } - public ParsedLedgerAccount nextAccount() { - if (!iterator.hasNext()) return null; - - ParsedLedgerAccount next = iterator.next(); - - if (next.getAname().equalsIgnoreCase("root")) return nextAccount(); - - debug("accounts", String.format("Got account '%s' [v1.15]", next.getAname())); - return next; - } } diff --git a/app/src/main/java/net/ktnx/mobileledger/json/v1_15/ParsedBalance.java b/app/src/main/java/net/ktnx/mobileledger/json/v1_15/ParsedBalance.java index 24e9ccb0..371c1221 100644 --- a/app/src/main/java/net/ktnx/mobileledger/json/v1_15/ParsedBalance.java +++ b/app/src/main/java/net/ktnx/mobileledger/json/v1_15/ParsedBalance.java @@ -17,30 +17,13 @@ package net.ktnx.mobileledger.json.v1_15; -import androidx.annotation.NonNull; - import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = true) -public class ParsedBalance { - private ParsedQuantity aquantity; - private String acommodity; +public class ParsedBalance extends net.ktnx.mobileledger.json.ParsedBalance { private ParsedStyle astyle; public ParsedBalance() { } - public ParsedQuantity getAquantity() { - return aquantity; - } - public void setAquantity(ParsedQuantity aquantity) { - this.aquantity = aquantity; - } - @NonNull - public String getAcommodity() { - return (acommodity == null) ? "" : acommodity; - } - public void setAcommodity(String acommodity) { - this.acommodity = acommodity; - } public ParsedStyle getAstyle() { return astyle; } diff --git a/app/src/main/java/net/ktnx/mobileledger/json/v1_15/ParsedLedgerAccount.java b/app/src/main/java/net/ktnx/mobileledger/json/v1_15/ParsedLedgerAccount.java index 5ec1464b..085c32b3 100644 --- a/app/src/main/java/net/ktnx/mobileledger/json/v1_15/ParsedLedgerAccount.java +++ b/app/src/main/java/net/ktnx/mobileledger/json/v1_15/ParsedLedgerAccount.java @@ -22,36 +22,14 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import java.util.List; @JsonIgnoreProperties(ignoreUnknown = true) -public class ParsedLedgerAccount { +public class ParsedLedgerAccount extends net.ktnx.mobileledger.json.ParsedLedgerAccount { private List aebalance; - private List aibalance; - private String aname; - private int anumpostings; public ParsedLedgerAccount() { } - public int getAnumpostings() { - return anumpostings; - } - public void setAnumpostings(int anumpostings) { - this.anumpostings = anumpostings; - } public List getAebalance() { return aebalance; } public void setAebalance(List aebalance) { this.aebalance = aebalance; } - public List getAibalance() { - return aibalance; - } - public void setAibalance(List aibalance) { - this.aibalance = aibalance; - } - public String getAname() { - return aname; - } - public void setAname(String aname) { - this.aname = aname; - } - } diff --git a/app/src/main/java/net/ktnx/mobileledger/json/v1_15/ParsedQuantity.java b/app/src/main/java/net/ktnx/mobileledger/json/v1_15/ParsedQuantity.java index f4096830..9a81fcc7 100644 --- a/app/src/main/java/net/ktnx/mobileledger/json/v1_15/ParsedQuantity.java +++ b/app/src/main/java/net/ktnx/mobileledger/json/v1_15/ParsedQuantity.java @@ -20,39 +20,5 @@ package net.ktnx.mobileledger.json.v1_15; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = true) -public class ParsedQuantity { - private long decimalMantissa; - private int decimalPlaces; - public ParsedQuantity() { - } - public ParsedQuantity(String input) { - parseString(input); - } - public long getDecimalMantissa() { - return decimalMantissa; - } - public void setDecimalMantissa(long decimalMantissa) { - this.decimalMantissa = decimalMantissa; - } - public int getDecimalPlaces() { - return decimalPlaces; - } - public void setDecimalPlaces(int decimalPlaces) { - this.decimalPlaces = decimalPlaces; - } - public float asFloat() { - return (float) (decimalMantissa * Math.pow(10, -decimalPlaces)); - } - public void parseString(String input) { - int pointPos = input.indexOf('.'); - if (pointPos >= 0) { - String integral = input.replace(".", ""); - decimalMantissa = Long.parseLong(integral); - decimalPlaces = input.length() - pointPos - 1; - } - else { - decimalMantissa = Long.parseLong(input); - decimalPlaces = 0; - } - } +public class ParsedQuantity extends net.ktnx.mobileledger.json.ParsedQuantity { } -- 2.39.5