From a87079ed41bdc3ad89fe8bd15dfba10e37b29b76 Mon Sep 17 00:00:00 2001 From: Damyan Ivanov Date: Sun, 27 Dec 2020 23:21:37 +0200 Subject: [PATCH] finish support for multiple server APIs when retrieving data this also adds support for the last JSON API change introduced in 1.19.1 (see gh#1360) exceptions from the low-level json parser are interpreted as version incompatibility and a pointer is made to profile details --- .../async/RetrieveTransactionsTask.java | 104 ++++++++++-- .../async/SendTransactionTask.java | 37 +++- .../mobileledger/json/AccountListParser.java | 82 +++------ .../json/ApiNotSupportedException.java | 20 +++ .../json/ParsedLedgerAccount.java | 78 ++++++++- .../ktnx/mobileledger/json/ParsedStyle.java | 54 ++++++ .../json/TransactionListParser.java | 43 +++++ .../json/v1_14/AccountListParser.java | 23 +-- .../json/v1_14/ParsedBalance.java | 21 +-- .../json/v1_14/ParsedLedgerAccount.java | 26 ++- .../mobileledger/json/v1_14/ParsedStyle.java | 32 +--- .../json/v1_14/TransactionListParser.java | 12 +- .../json/v1_15/AccountListParser.java | 6 + .../json/v1_15/ParsedLedgerAccount.java | 16 +- .../mobileledger/json/v1_15/ParsedStyle.java | 42 +---- .../json/v1_15/TransactionListParser.java | 12 +- .../json/v1_19_1/AccountListParser.java | 40 +++++ .../json/v1_19_1/ParsedAmount.java | 62 +++++++ .../json/v1_19_1/ParsedBalance.java | 33 ++++ .../json/v1_19_1/ParsedLedgerAccount.java | 53 ++++++ .../json/v1_19_1/ParsedLedgerTransaction.java | 160 ++++++++++++++++++ .../json/v1_19_1/ParsedPosting.java | 144 ++++++++++++++++ .../json/v1_19_1/ParsedPrecision.java | 45 +++++ .../json/v1_19_1/ParsedPrice.java | 78 +++++++++ .../json/v1_19_1/ParsedQuantity.java | 23 +++ .../json/v1_19_1/ParsedSourcePos.java | 43 +++++ .../json/v1_19_1/ParsedStyle.java | 33 ++++ .../json/v1_19_1/TransactionListParser.java | 44 +++++ .../mobileledger/model/HledgerVersion.java | 36 ++-- .../model/MobileLedgerProfile.java | 4 +- .../ui/activity/MainActivity.java | 20 ++- .../ui/profiles/ProfileDetailFragment.java | 33 ++-- app/src/main/res/layout/profile_detail.xml | 66 +++++--- app/src/main/res/menu/api_version.xml | 25 ++- app/src/main/res/values-bg/strings.xml | 16 +- app/src/main/res/values/strings.xml | 16 +- 36 files changed, 1282 insertions(+), 300 deletions(-) create mode 100644 app/src/main/java/net/ktnx/mobileledger/json/ApiNotSupportedException.java create mode 100644 app/src/main/java/net/ktnx/mobileledger/json/ParsedStyle.java create mode 100644 app/src/main/java/net/ktnx/mobileledger/json/TransactionListParser.java create mode 100644 app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/AccountListParser.java create mode 100644 app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedAmount.java create mode 100644 app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedBalance.java create mode 100644 app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedLedgerAccount.java create mode 100644 app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedLedgerTransaction.java create mode 100644 app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedPosting.java create mode 100644 app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedPrecision.java create mode 100644 app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedPrice.java create mode 100644 app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedQuantity.java create mode 100644 app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedSourcePos.java create mode 100644 app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedStyle.java create mode 100644 app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/TransactionListParser.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 85f76651..d092a1cb 100644 --- a/app/src/main/java/net/ktnx/mobileledger/async/RetrieveTransactionsTask.java +++ b/app/src/main/java/net/ktnx/mobileledger/async/RetrieveTransactionsTask.java @@ -24,17 +24,20 @@ import android.os.OperationCanceledException; import androidx.annotation.NonNull; +import com.fasterxml.jackson.databind.RuntimeJsonMappingException; + 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.ParsedLedgerTransaction; -import net.ktnx.mobileledger.json.v1_15.TransactionListParser; +import net.ktnx.mobileledger.json.AccountListParser; +import net.ktnx.mobileledger.json.ApiNotSupportedException; +import net.ktnx.mobileledger.json.TransactionListParser; import net.ktnx.mobileledger.model.Data; 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.MainModel; +import net.ktnx.mobileledger.utils.Logger; import net.ktnx.mobileledger.utils.NetworkUtil; import java.io.BufferedReader; @@ -381,7 +384,40 @@ public class RetrieveTransactionsTask extends public void addNumberOfPostings(int number) { expectedPostingsCount += number; } - private List retrieveAccountList() throws IOException, HTTPException { + private List retrieveAccountList() + throws IOException, HTTPException, ApiNotSupportedException { + final SendTransactionTask.API apiVersion = profile.getApiVersion(); + if (apiVersion.equals(SendTransactionTask.API.auto)) { + return retrieveAccountListAnyVersion(); + } + else if (apiVersion.equals(SendTransactionTask.API.html)) { + Logger.debug("json", + "Declining using JSON API for /accounts with configured legacy API version"); + return null; + } + else { + return retrieveAccountListForVersion(apiVersion); + } + } + private List retrieveAccountListAnyVersion() + throws HTTPException, ApiNotSupportedException { + for (SendTransactionTask.API ver : SendTransactionTask.API.allVersions) { + try { + return retrieveAccountListForVersion(ver); + } + catch (Exception e) { + Logger.debug("json", + String.format(Locale.US, "Error during account list retrieval using API %s", + ver.getDescription())); + } + + throw new ApiNotSupportedException(); + } + + throw new RuntimeException("This should never be reached"); + } + private List retrieveAccountListForVersion(SendTransactionTask.API version) + throws IOException, HTTPException { HttpURLConnection http = NetworkUtil.prepareConnection(profile, "accounts"); http.setAllowUserInteraction(false); switch (http.getResponseCode()) { @@ -405,12 +441,12 @@ public class RetrieveTransactionsTask extends if (http.getResponseCode() != 200) throw new IOException(String.format("HTTP error %d", http.getResponseCode())); - AccountListParser parser = new AccountListParser(resp); + AccountListParser parser = AccountListParser.forApiVersion(version, resp); expectedPostingsCount = 0; while (true) { throwIfCancelled(); - LedgerAccount acc = parser.nextLedgerAccount(this, map); + LedgerAccount acc = parser.nextAccount(this, map); if (acc == null) break; list.add(acc); @@ -430,7 +466,40 @@ public class RetrieveTransactionsTask extends return list; } private List retrieveTransactionList() - throws IOException, ParseException, HTTPException { + throws ParseException, HTTPException, IOException, ApiNotSupportedException { + final SendTransactionTask.API apiVersion = profile.getApiVersion(); + if (apiVersion.equals(SendTransactionTask.API.auto)) { + return retrieveTransactionListAnyVersion(); + } + else if (apiVersion.equals(SendTransactionTask.API.html)) { + Logger.debug("json", + "Declining using JSON API for /accounts with configured legacy API version"); + return null; + } + else { + return retrieveTransactionListForVersion(apiVersion); + } + + } + private List retrieveTransactionListAnyVersion() + throws ApiNotSupportedException { + for (SendTransactionTask.API ver : SendTransactionTask.API.allVersions) { + try { + return retrieveTransactionListForVersion(ver); + } + catch (Exception | HTTPException e) { + Logger.debug("json", + String.format(Locale.US, "Error during account list retrieval using API %s", + ver.getDescription())); + } + + throw new ApiNotSupportedException(); + } + + throw new RuntimeException("This should never be reached"); + } + private List retrieveTransactionListForVersion( + SendTransactionTask.API apiVersion) throws IOException, ParseException, HTTPException { Progress progress = new Progress(); progress.setTotal(expectedPostingsCount); @@ -449,18 +518,17 @@ public class RetrieveTransactionsTask extends try (InputStream resp = http.getInputStream()) { throwIfCancelled(); - TransactionListParser parser = new TransactionListParser(resp); + TransactionListParser parser = TransactionListParser.forApiVersion(apiVersion, resp); int processedPostings = 0; while (true) { throwIfCancelled(); - ParsedLedgerTransaction parsedTransaction = parser.nextTransaction(); + LedgerTransaction transaction = parser.nextTransaction(); throwIfCancelled(); - if (parsedTransaction == null) + if (transaction == null) break; - LedgerTransaction transaction = parsedTransaction.asLedgerTransaction(); trList.add(transaction); progress.setProgress(processedPostings += transaction.getAccounts() @@ -499,10 +567,15 @@ public class RetrieveTransactionsTask extends List transactions; try { accounts = retrieveAccountList(); + // accounts is null in API-version auto-detection and means + // requesting 'html' API version via the JSON classes + // this can't work, and the null results in the legacy code below + // being called if (accounts == null) transactions = null; else transactions = retrieveTransactionList(); + if (accounts == null || transactions == null) { accounts = new ArrayList<>(); transactions = new ArrayList<>(); @@ -525,6 +598,10 @@ public class RetrieveTransactionsTask extends e.printStackTrace(); return new Result(e.getLocalizedMessage()); } + catch (RuntimeJsonMappingException e) { + e.printStackTrace(); + return new Result(Result.ERR_JSON_PARSER_ERROR); + } catch (ParseException e) { e.printStackTrace(); return new Result("Network error"); @@ -533,6 +610,10 @@ public class RetrieveTransactionsTask extends e.printStackTrace(); return new Result("Operation cancelled"); } + catch (ApiNotSupportedException e) { + e.printStackTrace(); + return new Result("Server version not supported"); + } finally { Data.backgroundTaskFinished(); } @@ -622,6 +703,7 @@ public class RetrieveTransactionsTask extends } public static class Result { + public static String ERR_JSON_PARSER_ERROR = "err_json_parser"; public String error; public List accounts; public List transactions; diff --git a/app/src/main/java/net/ktnx/mobileledger/async/SendTransactionTask.java b/app/src/main/java/net/ktnx/mobileledger/async/SendTransactionTask.java index 1c4be5c4..9f441f9c 100644 --- a/app/src/main/java/net/ktnx/mobileledger/async/SendTransactionTask.java +++ b/app/src/main/java/net/ktnx/mobileledger/async/SendTransactionTask.java @@ -293,10 +293,10 @@ public class SendTransactionTask extends AsyncTask map = new SparseArray<>(); + public static API[] allVersions = {v1_19_1, v1_15, v1_14}; static { for (API item : API.values()) { @@ -336,7 +337,7 @@ public class SendTransactionTask extends AsyncTask iterator; + public static AccountListParser forApiVersion(SendTransactionTask.API version, + InputStream input) throws IOException { + switch (version) { + case v1_14: + return new net.ktnx.mobileledger.json.v1_14.AccountListParser(input); + case v1_15: + return new net.ktnx.mobileledger.json.v1_15.AccountListParser(input); + case v1_19_1: + return new net.ktnx.mobileledger.json.v1_19_1.AccountListParser(input); + default: + throw new RuntimeException("Unsupported version " + version.toString()); + } - public ParsedLedgerAccount nextAccount() { + } + public abstract SendTransactionTask.API getApiVersion(); + public LedgerAccount nextAccount(RetrieveTransactionsTask task, + HashMap map) { if (!iterator.hasNext()) return null; - ParsedLedgerAccount next = iterator.next(); + LedgerAccount next = iterator.next() + .toLedgerAccount(task, map); - if (next.getAname() + if (next.getName() .equalsIgnoreCase("root")) - return nextAccount(); + return nextAccount(task, map); - debug("accounts", String.format("Got account '%s' [v1.15]", next.getAname())); + debug("accounts", String.format("Got account '%s' [%s]", next.getName(), + getApiVersion().getDescription())); 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/ApiNotSupportedException.java b/app/src/main/java/net/ktnx/mobileledger/json/ApiNotSupportedException.java new file mode 100644 index 00000000..d552a684 --- /dev/null +++ b/app/src/main/java/net/ktnx/mobileledger/json/ApiNotSupportedException.java @@ -0,0 +1,20 @@ +/* + * 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; + +public class ApiNotSupportedException extends Throwable {} diff --git a/app/src/main/java/net/ktnx/mobileledger/json/ParsedLedgerAccount.java b/app/src/main/java/net/ktnx/mobileledger/json/ParsedLedgerAccount.java index aff57753..04eff28f 100644 --- a/app/src/main/java/net/ktnx/mobileledger/json/ParsedLedgerAccount.java +++ b/app/src/main/java/net/ktnx/mobileledger/json/ParsedLedgerAccount.java @@ -17,14 +17,17 @@ package net.ktnx.mobileledger.json; -import net.ktnx.mobileledger.json.ParsedBalance; +import net.ktnx.mobileledger.async.RetrieveTransactionsTask; +import net.ktnx.mobileledger.model.LedgerAccount; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; -public class ParsedLedgerAccount { +public abstract class ParsedLedgerAccount { private String aname; private int anumpostings; - private List aibalance; + public abstract List getSimpleBalance(); public String getAname() { return aname; } @@ -37,10 +40,71 @@ public class ParsedLedgerAccount { public void setAnumpostings(int anumpostings) { this.anumpostings = anumpostings; } - public List getAibalance() { - return aibalance; + public LedgerAccount toLedgerAccount(RetrieveTransactionsTask task, + HashMap map) { + task.addNumberOfPostings(getAnumpostings()); + final String accName = 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 (SimpleBalance b : getSimpleBalance()) { + task.throwIfCancelled(); + final String currency = b.getCommodity(); + final float amount = b.getAmount(); + 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; } - public void setAibalance(List aibalance) { - this.aibalance = aibalance; + + static public class SimpleBalance { + private String commodity; + private float amount; + public SimpleBalance(String commodity, float amount) { + this.commodity = commodity; + this.amount = amount; + } + public String getCommodity() { + return commodity; + } + public void setCommodity(String commodity) { + this.commodity = commodity; + } + public float getAmount() { + return amount; + } + public void setAmount(float amount) { + this.amount = amount; + } } } diff --git a/app/src/main/java/net/ktnx/mobileledger/json/ParsedStyle.java b/app/src/main/java/net/ktnx/mobileledger/json/ParsedStyle.java new file mode 100644 index 00000000..c22cd3f1 --- /dev/null +++ b/app/src/main/java/net/ktnx/mobileledger/json/ParsedStyle.java @@ -0,0 +1,54 @@ +/* + * 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 ParsedStyle { + private char asdecimalpoint; + private char ascommodityside; + private int digitgroups; + private boolean ascommodityspaced; + public ParsedStyle() { + } + public char getAsdecimalpoint() { + return asdecimalpoint; + } + public void setAsdecimalpoint(char asdecimalpoint) { + this.asdecimalpoint = asdecimalpoint; + } + public char getAscommodityside() { + return ascommodityside; + } + public void setAscommodityside(char ascommodityside) { + this.ascommodityside = ascommodityside; + } + public int getDigitgroups() { + return digitgroups; + } + public void setDigitgroups(int digitgroups) { + this.digitgroups = digitgroups; + } + public boolean isAscommodityspaced() { + return ascommodityspaced; + } + public void setAscommodityspaced(boolean ascommodityspaced) { + this.ascommodityspaced = ascommodityspaced; + } +} diff --git a/app/src/main/java/net/ktnx/mobileledger/json/TransactionListParser.java b/app/src/main/java/net/ktnx/mobileledger/json/TransactionListParser.java new file mode 100644 index 00000000..99841f84 --- /dev/null +++ b/app/src/main/java/net/ktnx/mobileledger/json/TransactionListParser.java @@ -0,0 +1,43 @@ +/* + * 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.async.SendTransactionTask; +import net.ktnx.mobileledger.model.LedgerTransaction; + +import java.io.IOException; +import java.io.InputStream; +import java.text.ParseException; + +public abstract class TransactionListParser { + public static TransactionListParser forApiVersion(SendTransactionTask.API apiVersion, + InputStream input) throws IOException { + switch (apiVersion) { + case v1_14: + return new net.ktnx.mobileledger.json.v1_14.TransactionListParser(input); + case v1_15: + return new net.ktnx.mobileledger.json.v1_15.TransactionListParser(input); + case v1_19_1: + return new net.ktnx.mobileledger.json.v1_19_1.TransactionListParser(input); + default: + throw new RuntimeException("Unsupported version " + apiVersion.toString()); + } + + } + abstract public LedgerTransaction nextTransaction() throws ParseException; +} diff --git a/app/src/main/java/net/ktnx/mobileledger/json/v1_14/AccountListParser.java b/app/src/main/java/net/ktnx/mobileledger/json/v1_14/AccountListParser.java index f3773a52..1df52924 100644 --- a/app/src/main/java/net/ktnx/mobileledger/json/v1_14/AccountListParser.java +++ b/app/src/main/java/net/ktnx/mobileledger/json/v1_14/AccountListParser.java @@ -1,5 +1,5 @@ /* - * Copyright © 2019 Damyan Ivanov. + * 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 @@ -17,18 +17,15 @@ package net.ktnx.mobileledger.json.v1_14; -import com.fasterxml.jackson.databind.MappingIterator; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; +import net.ktnx.mobileledger.async.SendTransactionTask; + 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 +33,8 @@ 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'", next.getAname())); - return next; + @Override + public SendTransactionTask.API getApiVersion() { + return SendTransactionTask.API.v1_14; } } diff --git a/app/src/main/java/net/ktnx/mobileledger/json/v1_14/ParsedBalance.java b/app/src/main/java/net/ktnx/mobileledger/json/v1_14/ParsedBalance.java index 39cd1908..cb8b5f5f 100644 --- a/app/src/main/java/net/ktnx/mobileledger/json/v1_14/ParsedBalance.java +++ b/app/src/main/java/net/ktnx/mobileledger/json/v1_14/ParsedBalance.java @@ -1,5 +1,5 @@ /* - * Copyright © 2019 Damyan Ivanov. + * 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 @@ -17,30 +17,13 @@ package net.ktnx.mobileledger.json.v1_14; -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_14/ParsedLedgerAccount.java b/app/src/main/java/net/ktnx/mobileledger/json/v1_14/ParsedLedgerAccount.java index ab982b4e..476e9cd7 100644 --- a/app/src/main/java/net/ktnx/mobileledger/json/v1_14/ParsedLedgerAccount.java +++ b/app/src/main/java/net/ktnx/mobileledger/json/v1_14/ParsedLedgerAccount.java @@ -19,22 +19,15 @@ package net.ktnx.mobileledger.json.v1_14; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import java.util.ArrayList; 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; } @@ -47,11 +40,14 @@ public class ParsedLedgerAccount { public void setAibalance(List aibalance) { this.aibalance = aibalance; } - public String getAname() { - return aname; - } - public void setAname(String aname) { - this.aname = aname; - } + @Override + public List getSimpleBalance() { + List result = new ArrayList(); + for (ParsedBalance b : getAibalance()) { + result.add(new SimpleBalance(b.getAcommodity(), b.getAquantity() + .asFloat())); + } + return result; + } } diff --git a/app/src/main/java/net/ktnx/mobileledger/json/v1_14/ParsedStyle.java b/app/src/main/java/net/ktnx/mobileledger/json/v1_14/ParsedStyle.java index 798cb81c..74b02a50 100644 --- a/app/src/main/java/net/ktnx/mobileledger/json/v1_14/ParsedStyle.java +++ b/app/src/main/java/net/ktnx/mobileledger/json/v1_14/ParsedStyle.java @@ -1,5 +1,5 @@ /* - * Copyright © 2019 Damyan Ivanov. + * 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 @@ -20,12 +20,8 @@ package net.ktnx.mobileledger.json.v1_14; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = true) -public class ParsedStyle { +public class ParsedStyle extends net.ktnx.mobileledger.json.ParsedStyle { private int asprecision; - private char asdecimalpoint; - private char ascommodityside; - private int digitgroups; - private boolean ascommodityspaced; public ParsedStyle() { } public int getAsprecision() { @@ -34,28 +30,4 @@ public class ParsedStyle { public void setAsprecision(int asprecision) { this.asprecision = asprecision; } - public char getAsdecimalpoint() { - return asdecimalpoint; - } - public void setAsdecimalpoint(char asdecimalpoint) { - this.asdecimalpoint = asdecimalpoint; - } - public char getAscommodityside() { - return ascommodityside; - } - public void setAscommodityside(char ascommodityside) { - this.ascommodityside = ascommodityside; - } - public int getDigitgroups() { - return digitgroups; - } - public void setDigitgroups(int digitgroups) { - this.digitgroups = digitgroups; - } - public boolean isAscommodityspaced() { - return ascommodityspaced; - } - public void setAscommodityspaced(boolean ascommodityspaced) { - this.ascommodityspaced = ascommodityspaced; - } } diff --git a/app/src/main/java/net/ktnx/mobileledger/json/v1_14/TransactionListParser.java b/app/src/main/java/net/ktnx/mobileledger/json/v1_14/TransactionListParser.java index 742c5957..f9be5a3a 100644 --- a/app/src/main/java/net/ktnx/mobileledger/json/v1_14/TransactionListParser.java +++ b/app/src/main/java/net/ktnx/mobileledger/json/v1_14/TransactionListParser.java @@ -1,5 +1,5 @@ /* - * Copyright © 2019 Damyan Ivanov. + * 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 @@ -21,10 +21,13 @@ import com.fasterxml.jackson.databind.MappingIterator; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; +import net.ktnx.mobileledger.model.LedgerTransaction; + import java.io.IOException; import java.io.InputStream; +import java.text.ParseException; -public class TransactionListParser { +public class TransactionListParser extends net.ktnx.mobileledger.json.TransactionListParser { private final MappingIterator iterator; @@ -34,7 +37,8 @@ public class TransactionListParser { ObjectReader reader = mapper.readerFor(ParsedLedgerTransaction.class); iterator = reader.readValues(input); } - public ParsedLedgerTransaction nextTransaction() { - return iterator.hasNext() ? iterator.next() : null; + public LedgerTransaction nextTransaction() throws ParseException { + return iterator.hasNext() ? iterator.next() + .asLedgerTransaction() : null; } } 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 33c554c8..005cd5ba 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 @@ -20,6 +20,8 @@ package net.ktnx.mobileledger.json.v1_15; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; +import net.ktnx.mobileledger.async.SendTransactionTask; + import java.io.IOException; import java.io.InputStream; @@ -31,4 +33,8 @@ public class AccountListParser extends net.ktnx.mobileledger.json.AccountListPar iterator = reader.readValues(input); } + @Override + public SendTransactionTask.API getApiVersion() { + return SendTransactionTask.API.v1_15; + } } 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 085c32b3..8e762cab 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 @@ -1,5 +1,5 @@ /* - * Copyright © 2019 Damyan Ivanov. + * 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 @@ -19,17 +19,5 @@ package net.ktnx.mobileledger.json.v1_15; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import java.util.List; - @JsonIgnoreProperties(ignoreUnknown = true) -public class ParsedLedgerAccount extends net.ktnx.mobileledger.json.ParsedLedgerAccount { - private List aebalance; - public ParsedLedgerAccount() { - } - public List getAebalance() { - return aebalance; - } - public void setAebalance(List aebalance) { - this.aebalance = aebalance; - } -} +public class ParsedLedgerAccount extends net.ktnx.mobileledger.json.v1_14.ParsedLedgerAccount {} diff --git a/app/src/main/java/net/ktnx/mobileledger/json/v1_15/ParsedStyle.java b/app/src/main/java/net/ktnx/mobileledger/json/v1_15/ParsedStyle.java index 554133c5..b2f0f742 100644 --- a/app/src/main/java/net/ktnx/mobileledger/json/v1_15/ParsedStyle.java +++ b/app/src/main/java/net/ktnx/mobileledger/json/v1_15/ParsedStyle.java @@ -1,5 +1,5 @@ /* - * Copyright © 2019 Damyan Ivanov. + * 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 @@ -20,42 +20,4 @@ package net.ktnx.mobileledger.json.v1_15; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = true) -public class ParsedStyle { - private int asprecision; - private char asdecimalpoint; - private char ascommodityside; - private int digitgroups; - private boolean ascommodityspaced; - public ParsedStyle() { - } - public int getAsprecision() { - return asprecision; - } - public void setAsprecision(int asprecision) { - this.asprecision = asprecision; - } - public char getAsdecimalpoint() { - return asdecimalpoint; - } - public void setAsdecimalpoint(char asdecimalpoint) { - this.asdecimalpoint = asdecimalpoint; - } - public char getAscommodityside() { - return ascommodityside; - } - public void setAscommodityside(char ascommodityside) { - this.ascommodityside = ascommodityside; - } - public int getDigitgroups() { - return digitgroups; - } - public void setDigitgroups(int digitgroups) { - this.digitgroups = digitgroups; - } - public boolean isAscommodityspaced() { - return ascommodityspaced; - } - public void setAscommodityspaced(boolean ascommodityspaced) { - this.ascommodityspaced = ascommodityspaced; - } -} +public class ParsedStyle extends net.ktnx.mobileledger.json.v1_14.ParsedStyle {} diff --git a/app/src/main/java/net/ktnx/mobileledger/json/v1_15/TransactionListParser.java b/app/src/main/java/net/ktnx/mobileledger/json/v1_15/TransactionListParser.java index 940deee4..aab1bc41 100644 --- a/app/src/main/java/net/ktnx/mobileledger/json/v1_15/TransactionListParser.java +++ b/app/src/main/java/net/ktnx/mobileledger/json/v1_15/TransactionListParser.java @@ -1,5 +1,5 @@ /* - * Copyright © 2019 Damyan Ivanov. + * 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 @@ -21,10 +21,13 @@ import com.fasterxml.jackson.databind.MappingIterator; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; +import net.ktnx.mobileledger.model.LedgerTransaction; + import java.io.IOException; import java.io.InputStream; +import java.text.ParseException; -public class TransactionListParser { +public class TransactionListParser extends net.ktnx.mobileledger.json.TransactionListParser { private final MappingIterator iterator; @@ -34,7 +37,8 @@ public class TransactionListParser { ObjectReader reader = mapper.readerFor(ParsedLedgerTransaction.class); iterator = reader.readValues(input); } - public ParsedLedgerTransaction nextTransaction() { - return iterator.hasNext() ? iterator.next() : null; + public LedgerTransaction nextTransaction() throws ParseException { + return iterator.hasNext() ? iterator.next() + .asLedgerTransaction() : null; } } diff --git a/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/AccountListParser.java b/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/AccountListParser.java new file mode 100644 index 00000000..9ff89eb7 --- /dev/null +++ b/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/AccountListParser.java @@ -0,0 +1,40 @@ +/* + * 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.v1_19_1; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; + +import net.ktnx.mobileledger.async.SendTransactionTask; + +import java.io.IOException; +import java.io.InputStream; + +public class AccountListParser extends net.ktnx.mobileledger.json.AccountListParser { + + public AccountListParser(InputStream input) throws IOException { + ObjectMapper mapper = new ObjectMapper(); + ObjectReader reader = mapper.readerFor(ParsedLedgerAccount.class); + + iterator = reader.readValues(input); + } + @Override + public SendTransactionTask.API getApiVersion() { + return SendTransactionTask.API.v1_19_1; + } +} diff --git a/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedAmount.java b/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedAmount.java new file mode 100644 index 00000000..12cdbace --- /dev/null +++ b/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedAmount.java @@ -0,0 +1,62 @@ +/* + * 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.v1_19_1; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ParsedAmount { + private String acommodity; + private ParsedQuantity aquantity; + private boolean aismultiplier; + private ParsedStyle astyle; + private ParsedPrice aprice; + public ParsedAmount() { + } + public ParsedPrice getAprice() { + return aprice; + } + public void setAprice(ParsedPrice aprice) { + this.aprice = aprice; + } + public String getAcommodity() { + return acommodity; + } + public void setAcommodity(String acommodity) { + this.acommodity = acommodity; + } + public ParsedQuantity getAquantity() { + return aquantity; + } + public void setAquantity(ParsedQuantity aquantity) { + this.aquantity = aquantity; + } + public boolean isAismultiplier() { + return aismultiplier; + } + public void setAismultiplier(boolean aismultiplier) { + this.aismultiplier = aismultiplier; + } + public ParsedStyle getAstyle() { + return astyle; + } + public void setAstyle(ParsedStyle astyle) { + this.astyle = astyle; + } + +} diff --git a/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedBalance.java b/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedBalance.java new file mode 100644 index 00000000..5defe08a --- /dev/null +++ b/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedBalance.java @@ -0,0 +1,33 @@ +/* + * 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.v1_19_1; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ParsedBalance extends net.ktnx.mobileledger.json.ParsedBalance { + private ParsedStyle astyle; + public ParsedBalance() { + } + public ParsedStyle getAstyle() { + return astyle; + } + public void setAstyle(ParsedStyle astyle) { + this.astyle = astyle; + } +} diff --git a/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedLedgerAccount.java b/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedLedgerAccount.java new file mode 100644 index 00000000..5fabdb5d --- /dev/null +++ b/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedLedgerAccount.java @@ -0,0 +1,53 @@ +/* + * 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.v1_19_1; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ParsedLedgerAccount extends net.ktnx.mobileledger.json.ParsedLedgerAccount { + private List aebalance; + private List aibalance; + public ParsedLedgerAccount() { + } + public List getAibalance() { + return aibalance; + } + public void setAibalance(List aibalance) { + this.aibalance = aibalance; + } + public List getAebalance() { + return aebalance; + } + public void setAebalance(List aebalance) { + this.aebalance = aebalance; + } + @Override + public List getSimpleBalance() { + List result = new ArrayList(); + for (ParsedBalance b : getAibalance()) { + result.add(new SimpleBalance(b.getAcommodity(), b.getAquantity() + .asFloat())); + } + + return result; + } +} diff --git a/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedLedgerTransaction.java b/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedLedgerTransaction.java new file mode 100644 index 00000000..74af2339 --- /dev/null +++ b/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedLedgerTransaction.java @@ -0,0 +1,160 @@ +/* + * 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.v1_19_1; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import net.ktnx.mobileledger.model.LedgerTransaction; +import net.ktnx.mobileledger.model.LedgerTransactionAccount; +import net.ktnx.mobileledger.utils.Globals; +import net.ktnx.mobileledger.utils.Misc; +import net.ktnx.mobileledger.utils.SimpleDate; + +import java.text.ParseException; +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ParsedLedgerTransaction implements net.ktnx.mobileledger.json.ParsedLedgerTransaction { + private String tdate; + private String tdate2 = null; + private String tdescription; + private String tcomment; + private String tcode = ""; + private String tstatus = "Unmarked"; + private String tprecedingcomment = ""; + private int tindex; + private List tpostings; + private List> ttags = new ArrayList<>(); + private ParsedSourcePos tsourcepos = new ParsedSourcePos(); + public ParsedLedgerTransaction() { + } + public static ParsedLedgerTransaction fromLedgerTransaction(LedgerTransaction tr) { + ParsedLedgerTransaction result = new ParsedLedgerTransaction(); + result.setTcomment(tr.getComment()); + result.setTprecedingcomment(""); + + ArrayList postings = new ArrayList<>(); + for (LedgerTransactionAccount acc : tr.getAccounts()) { + if (!acc.getAccountName() + .isEmpty()) + postings.add(ParsedPosting.fromLedgerAccount(acc)); + } + + result.setTpostings(postings); + SimpleDate transactionDate = tr.getDateIfAny(); + if (transactionDate == null) { + transactionDate = SimpleDate.today(); + } + result.setTdate(Globals.formatIsoDate(transactionDate)); + result.setTdate2(null); + result.setTindex(1); + result.setTdescription(tr.getDescription()); + return result; + } + public String getTcode() { + return tcode; + } + public void setTcode(String tcode) { + this.tcode = tcode; + } + public String getTstatus() { + return tstatus; + } + public void setTstatus(String tstatus) { + this.tstatus = tstatus; + } + public List> getTtags() { + return ttags; + } + public void setTtags(List> ttags) { + this.ttags = ttags; + } + public ParsedSourcePos getTsourcepos() { + return tsourcepos; + } + public void setTsourcepos(ParsedSourcePos tsourcepos) { + this.tsourcepos = tsourcepos; + } + public String getTprecedingcomment() { + return tprecedingcomment; + } + public void setTprecedingcomment(String tprecedingcomment) { + this.tprecedingcomment = tprecedingcomment; + } + public String getTdate() { + return tdate; + } + public void setTdate(String tdate) { + this.tdate = tdate; + } + public String getTdate2() { + return tdate2; + } + public void setTdate2(String tdate2) { + this.tdate2 = tdate2; + } + public String getTdescription() { + return tdescription; + } + public void setTdescription(String tdescription) { + this.tdescription = tdescription; + } + public String getTcomment() { + return tcomment; + } + public void setTcomment(String tcomment) { + this.tcomment = tcomment; + } + public int getTindex() { + return tindex; + } + public void setTindex(int tindex) { + this.tindex = tindex; + if (tpostings != null) + for (ParsedPosting p : tpostings) { + p.setPtransaction_(tindex); + } + } + public List getTpostings() { + return tpostings; + } + public void setTpostings(List tpostings) { + this.tpostings = tpostings; + } + public void addPosting(ParsedPosting posting) { + posting.setPtransaction_(tindex); + tpostings.add(posting); + } + public LedgerTransaction asLedgerTransaction() throws ParseException { + SimpleDate date = Globals.parseIsoDate(tdate); + LedgerTransaction tr = new LedgerTransaction(tindex, date, tdescription); + tr.setComment(Misc.trim(Misc.emptyIsNull(tcomment))); + + List postings = tpostings; + + if (postings != null) { + for (ParsedPosting p : postings) { + tr.addAccount(p.asLedgerAccount()); + } + } + + tr.markDataAsLoaded(); + return tr; + } +} diff --git a/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedPosting.java b/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedPosting.java new file mode 100644 index 00000000..e233062e --- /dev/null +++ b/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedPosting.java @@ -0,0 +1,144 @@ +/* + * 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.v1_19_1; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import net.ktnx.mobileledger.model.LedgerTransactionAccount; + +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ParsedPosting extends net.ktnx.mobileledger.json.ParsedPosting { + private Void pbalanceassertion; + private String pstatus = "Unmarked"; + private String paccount; + private List pamount; + private String pdate = null; + private String pdate2 = null; + private String ptype = "RegularPosting"; + private String pcomment = ""; + private List> ptags = new ArrayList<>(); + private String poriginal = null; + private int ptransaction_; + public ParsedPosting() { + } + public static ParsedPosting fromLedgerAccount(LedgerTransactionAccount acc) { + ParsedPosting result = new ParsedPosting(); + result.setPaccount(acc.getAccountName()); + + String comment = acc.getComment(); + if (comment == null) + comment = ""; + result.setPcomment(comment); + + ArrayList amounts = new ArrayList<>(); + ParsedAmount amt = new ParsedAmount(); + amt.setAcommodity((acc.getCurrency() == null) ? "" : acc.getCurrency()); + amt.setAismultiplier(false); + ParsedQuantity qty = new ParsedQuantity(); + qty.setDecimalPlaces(2); + qty.setDecimalMantissa(Math.round(acc.getAmount() * 100)); + amt.setAquantity(qty); + ParsedStyle style = new ParsedStyle(); + style.setAscommodityside(getCommoditySide()); + style.setAscommodityspaced(getCommoditySpaced()); + style.setAsprecision(new ParsedPrecision(2)); + style.setAsdecimalpoint('.'); + amt.setAstyle(style); + if (acc.getCurrency() != null) + amt.setAcommodity(acc.getCurrency()); + amounts.add(amt); + result.setPamount(amounts); + return result; + } + public String getPdate2() { + return pdate2; + } + public void setPdate2(String pdate2) { + this.pdate2 = pdate2; + } + public int getPtransaction_() { + return ptransaction_; + } + public void setPtransaction_(int ptransaction_) { + this.ptransaction_ = ptransaction_; + } + public String getPdate() { + return pdate; + } + public void setPdate(String pdate) { + this.pdate = pdate; + } + public String getPtype() { + return ptype; + } + public void setPtype(String ptype) { + this.ptype = ptype; + } + public String getPcomment() { + return pcomment; + } + public void setPcomment(String pcomment) { + this.pcomment = (pcomment == null) ? null : pcomment.trim(); + } + public List> getPtags() { + return ptags; + } + public void setPtags(List> ptags) { + this.ptags = ptags; + } + public String getPoriginal() { + return poriginal; + } + public void setPoriginal(String poriginal) { + this.poriginal = poriginal; + } + public String getPstatus() { + return pstatus; + } + public void setPstatus(String pstatus) { + this.pstatus = pstatus; + } + public Void getPbalanceassertion() { + return pbalanceassertion; + } + public void setPbalanceassertion(Void pbalanceassertion) { + this.pbalanceassertion = pbalanceassertion; + } + public String getPaccount() { + return paccount; + } + public void setPaccount(String paccount) { + this.paccount = paccount; + } + public List getPamount() { + return pamount; + } + public void setPamount(List pamount) { + this.pamount = pamount; + } + public LedgerTransactionAccount asLedgerAccount() { + ParsedAmount amt = pamount.get(0); + return new LedgerTransactionAccount(paccount, amt.getAquantity() + .asFloat(), amt.getAcommodity(), + getPcomment()); + } + +} diff --git a/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedPrecision.java b/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedPrecision.java new file mode 100644 index 00000000..4472cf41 --- /dev/null +++ b/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedPrecision.java @@ -0,0 +1,45 @@ +/* + * 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.v1_19_1; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +class ParsedPrecision { + private int contents; + private String tag; + ParsedPrecision() { + tag = "NaturalPrecision"; + } + ParsedPrecision(int contents) { + this.contents = contents; + tag = "Precision"; + } + public int getContents() { + return contents; + } + public void setContents(int contents) { + this.contents = contents; + } + public String getTag() { + return tag; + } + public void setTag(String tag) { + this.tag = tag; + } +} diff --git a/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedPrice.java b/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedPrice.java new file mode 100644 index 00000000..0e1ea547 --- /dev/null +++ b/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedPrice.java @@ -0,0 +1,78 @@ +/* + * 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.v1_19_1; + +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 ParsedQuantity aquantity; + private String acommodity; + private boolean aismultiplier; + private ParsedStyle astyle; + public Contents() { + acommodity = ""; + } + public ParsedPrice getAprice() { + return aprice; + } + public void setAprice(ParsedPrice aprice) { + this.aprice = aprice; + } + public 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 ParsedStyle getAstyle() { + return astyle; + } + public void setAstyle(ParsedStyle astyle) { + this.astyle = astyle; + } + } +} diff --git a/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedQuantity.java b/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedQuantity.java new file mode 100644 index 00000000..951bb56f --- /dev/null +++ b/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedQuantity.java @@ -0,0 +1,23 @@ +/* + * 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.v1_19_1; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ParsedQuantity extends net.ktnx.mobileledger.json.ParsedQuantity {} diff --git a/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedSourcePos.java b/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedSourcePos.java new file mode 100644 index 00000000..650f97c1 --- /dev/null +++ b/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedSourcePos.java @@ -0,0 +1,43 @@ +/* + * 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.v1_19_1; + +import java.util.ArrayList; +import java.util.List; + +class ParsedSourcePos { + private String tag = "JournalSourcePos"; + private List contents; + public ParsedSourcePos() { + contents = new ArrayList<>(); + contents.add(""); + contents.add(new Integer[]{1, 1}); + } + public String getTag() { + return tag; + } + public void setTag(String tag) { + this.tag = tag; + } + public List getContents() { + return contents; + } + public void setContents(List contents) { + this.contents = contents; + } +} diff --git a/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedStyle.java b/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedStyle.java new file mode 100644 index 00000000..b0398a17 --- /dev/null +++ b/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/ParsedStyle.java @@ -0,0 +1,33 @@ +/* + * 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.v1_19_1; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ParsedStyle extends net.ktnx.mobileledger.json.ParsedStyle { + private ParsedPrecision asprecision; + public ParsedStyle() { + } + public ParsedPrecision getAsprecision() { + return asprecision; + } + public void setAsprecision(ParsedPrecision asprecision) { + this.asprecision = asprecision; + } +} diff --git a/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/TransactionListParser.java b/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/TransactionListParser.java new file mode 100644 index 00000000..12564a22 --- /dev/null +++ b/app/src/main/java/net/ktnx/mobileledger/json/v1_19_1/TransactionListParser.java @@ -0,0 +1,44 @@ +/* + * 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.v1_19_1; + +import com.fasterxml.jackson.databind.MappingIterator; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; + +import net.ktnx.mobileledger.model.LedgerTransaction; + +import java.io.IOException; +import java.io.InputStream; +import java.text.ParseException; + +public class TransactionListParser extends net.ktnx.mobileledger.json.TransactionListParser { + + private final MappingIterator iterator; + + public TransactionListParser(InputStream input) throws IOException { + + ObjectMapper mapper = new ObjectMapper(); + ObjectReader reader = mapper.readerFor(ParsedLedgerTransaction.class); + iterator = reader.readValues(input); + } + public LedgerTransaction nextTransaction() throws ParseException { + return iterator.hasNext() ? iterator.next() + .asLedgerTransaction() : null; + } +} diff --git a/app/src/main/java/net/ktnx/mobileledger/model/HledgerVersion.java b/app/src/main/java/net/ktnx/mobileledger/model/HledgerVersion.java index ae9e77c8..835c5c1a 100644 --- a/app/src/main/java/net/ktnx/mobileledger/model/HledgerVersion.java +++ b/app/src/main/java/net/ktnx/mobileledger/model/HledgerVersion.java @@ -20,39 +20,41 @@ package net.ktnx.mobileledger.model; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import net.ktnx.mobileledger.async.SendTransactionTask; + import java.util.Locale; public class HledgerVersion { private final int major; private final int minor; private final int patch; - private final boolean isPre_1_20; + private final boolean isPre_1_20_1; private final boolean hasPatch; public HledgerVersion(int major, int minor) { this.major = major; this.minor = minor; this.patch = 0; - this.isPre_1_20 = false; + this.isPre_1_20_1 = false; this.hasPatch = false; } public HledgerVersion(int major, int minor, int patch) { this.major = major; this.minor = minor; this.patch = patch; - this.isPre_1_20 = false; + this.isPre_1_20_1 = false; this.hasPatch = true; } - public HledgerVersion(boolean pre_1_20) { - if (!pre_1_20) - throw new IllegalArgumentException("pre_1_20 argument must be true"); + public HledgerVersion(boolean pre_1_20_1) { + if (!pre_1_20_1) + throw new IllegalArgumentException("pre_1_20_1 argument must be true"); this.major = this.minor = this.patch = 0; - this.isPre_1_20 = true; + this.isPre_1_20_1 = true; this.hasPatch = false; } public HledgerVersion(HledgerVersion origin) { this.major = origin.major; this.minor = origin.minor; - this.isPre_1_20 = origin.isPre_1_20; + this.isPre_1_20_1 = origin.isPre_1_20_1; this.patch = origin.patch; this.hasPatch = origin.hasPatch; } @@ -64,12 +66,12 @@ public class HledgerVersion { return false; HledgerVersion that = (HledgerVersion) obj; - return (this.isPre_1_20 == that.isPre_1_20 && this.major == that.major && + return (this.isPre_1_20_1 == that.isPre_1_20_1 && this.major == that.major && this.minor == that.minor && this.patch == that.patch && this.hasPatch == that.hasPatch); } - public boolean isPre_1_20() { - return isPre_1_20; + public boolean isPre_1_20_1() { + return isPre_1_20_1; } public int getMajor() { return major; @@ -83,9 +85,19 @@ public class HledgerVersion { @NonNull @Override public String toString() { - if (isPre_1_20) + if (isPre_1_20_1) return "(before 1.20)"; return hasPatch ? String.format(Locale.ROOT, "%d.%d.%d", major, minor, patch) : String.format(Locale.ROOT, "%d.%d", major, minor); } + public boolean atLeast(int major, int minor) { + return ((this.major == major) && (this.minor >= minor)) || (this.major > major); + } + @org.jetbrains.annotations.Nullable + public SendTransactionTask.API getSuitableApiVersion() { + if (isPre_1_20_1) + return null; + + return SendTransactionTask.API.v1_19_1; + } } diff --git a/app/src/main/java/net/ktnx/mobileledger/model/MobileLedgerProfile.java b/app/src/main/java/net/ktnx/mobileledger/model/MobileLedgerProfile.java index 55746ddd..fcbd9203 100644 --- a/app/src/main/java/net/ktnx/mobileledger/model/MobileLedgerProfile.java +++ b/app/src/main/java/net/ktnx/mobileledger/model/MobileLedgerProfile.java @@ -330,7 +330,7 @@ public final class MobileLedgerProfile { authEnabled ? authPassword : null, themeHue, orderNo, preferredAccountsFilter, futureDates.toInt(), apiVersion.toInt(), showCommodityByDefault, defaultCommodity, showCommentsByDefault, - (detectedVersion != null) && detectedVersion.isPre_1_20(), + (detectedVersion != null) && detectedVersion.isPre_1_20_1(), (detectedVersion == null) ? 0 : detectedVersion.getMajor(), (detectedVersion == null) ? 0 : detectedVersion.getMinor() }); @@ -625,7 +625,7 @@ public final class MobileLedgerProfile { } } - private int value; + private final int value; FutureDates(int value) { this.value = value; } diff --git a/app/src/main/java/net/ktnx/mobileledger/ui/activity/MainActivity.java b/app/src/main/java/net/ktnx/mobileledger/ui/activity/MainActivity.java index 94c21bf3..9cb68cb8 100644 --- a/app/src/main/java/net/ktnx/mobileledger/ui/activity/MainActivity.java +++ b/app/src/main/java/net/ktnx/mobileledger/ui/activity/MainActivity.java @@ -36,6 +36,7 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.appcompat.app.ActionBarDrawerToggle; +import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.Toolbar; import androidx.core.view.GravityCompat; import androidx.drawerlayout.widget.DrawerLayout; @@ -237,7 +238,8 @@ public class MainActivity extends ProfileThemedActivity { findViewById(R.id.nav_new_profile_button).setOnClickListener( v -> startEditProfileActivity(null)); - findViewById(R.id.transaction_list_cancel_download).setOnClickListener(this::onStopTransactionRefreshClick); + findViewById(R.id.transaction_list_cancel_download).setOnClickListener( + this::onStopTransactionRefreshClick); RecyclerView root = findViewById(R.id.nav_profile_list); if (root == null) @@ -619,9 +621,19 @@ public class MainActivity extends ProfileThemedActivity { mainModel.transactionRetrievalDone(); - if (progress.getError() != null) { - Snackbar.make(mViewPager, progress.getError(), Snackbar.LENGTH_LONG) - .show(); + String error = progress.getError(); + if (error != null) { + if (error.equals(RetrieveTransactionsTask.Result.ERR_JSON_PARSER_ERROR)) + error = getResources().getString(R.string.err_json_parser_error); + + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setMessage(error); + builder.setPositiveButton(R.string.btn_profile_options, (dialog, which) -> { + Logger.debug("error", "will start profile editor"); + startEditProfileActivity(profile); + }); + builder.create() + .show(); return; } diff --git a/app/src/main/java/net/ktnx/mobileledger/ui/profiles/ProfileDetailFragment.java b/app/src/main/java/net/ktnx/mobileledger/ui/profiles/ProfileDetailFragment.java index 672acf0e..10f43667 100644 --- a/app/src/main/java/net/ktnx/mobileledger/ui/profiles/ProfileDetailFragment.java +++ b/app/src/main/java/net/ktnx/mobileledger/ui/profiles/ProfileDetailFragment.java @@ -287,19 +287,23 @@ public class ProfileDetailFragment extends Fragment { context.findViewById(R.id.api_version_text) .setOnClickListener(this::chooseAPIVersion); - TextView detectedApiVersion = context.findViewById(R.id.detected_version_text); + context.findViewById(R.id.server_version_label) + .setOnClickListener(v -> model.triggerVersionDetection()); + TextView detectedServerVersion = context.findViewById(R.id.detected_server_version_text); model.observeDetectedVersion(viewLifecycleOwner, ver -> { if (ver == null) - detectedApiVersion.setText(context.getResources() - .getString(R.string.api_version_unknown_label)); - else if (ver.isPre_1_20()) - detectedApiVersion.setText(context.getResources() - .getString(R.string.api_pre_1_19)); + detectedServerVersion.setText(context.getResources() + .getString( + R.string.server_version_unknown_label)); + else if (ver.isPre_1_20_1()) + detectedServerVersion.setText(context.getResources() + .getString( + R.string.detected_server_pre_1_20_1)); else - detectedApiVersion.setText(ver.toString()); + detectedServerVersion.setText(ver.toString()); }); - detectedApiVersion.setOnClickListener(v -> model.triggerVersionDetection()); - final View detectButton = context.findViewById(R.id.api_version_detect_button); + detectedServerVersion.setOnClickListener(v -> model.triggerVersionDetection()); + final View detectButton = context.findViewById(R.id.server_version_detect_button); detectButton.setOnClickListener(v -> model.triggerVersionDetection()); model.observeDetectingHledgerVersion(viewLifecycleOwner, running -> { detectButton.setVisibility(running ? View.VISIBLE : View.INVISIBLE); @@ -394,11 +398,14 @@ public class ProfileDetailFragment extends Fragment { case R.id.api_version_menu_html: apiVer = SendTransactionTask.API.html; break; - case R.id.api_version_menu_post_1_14: - apiVer = SendTransactionTask.API.post_1_14; + case R.id.api_version_menu_1_19_1: + apiVer = SendTransactionTask.API.v1_19_1; break; - case R.id.api_version_menu_pre_1_15: - apiVer = SendTransactionTask.API.pre_1_15; + case R.id.api_version_menu_1_15: + apiVer = SendTransactionTask.API.v1_15; + break; + case R.id.api_version_menu_1_14: + apiVer = SendTransactionTask.API.v1_14; break; case R.id.api_version_menu_auto: default: diff --git a/app/src/main/res/layout/profile_detail.xml b/app/src/main/res/layout/profile_detail.xml index 83c4f228..46222f62 100644 --- a/app/src/main/res/layout/profile_detail.xml +++ b/app/src/main/res/layout/profile_detail.xml @@ -144,60 +144,82 @@ - + + + + + + + -