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;
public void addNumberOfPostings(int number) {
expectedPostingsCount += number;
}
- private List<LedgerAccount> retrieveAccountList() throws IOException, HTTPException {
+ private List<LedgerAccount> 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<LedgerAccount> 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<LedgerAccount> retrieveAccountListForVersion(SendTransactionTask.API version)
+ throws IOException, HTTPException {
HttpURLConnection http = NetworkUtil.prepareConnection(profile, "accounts");
http.setAllowUserInteraction(false);
switch (http.getResponseCode()) {
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);
return list;
}
private List<LedgerTransaction> 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<LedgerTransaction> 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<LedgerTransaction> retrieveTransactionListForVersion(
+ SendTransactionTask.API apiVersion) throws IOException, ParseException, HTTPException {
Progress progress = new Progress();
progress.setTotal(expectedPostingsCount);
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()
List<LedgerTransaction> 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<>();
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");
e.printStackTrace();
return new Result("Operation cancelled");
}
+ catch (ApiNotSupportedException e) {
+ e.printStackTrace();
+ return new Result("Server version not supported");
+ }
finally {
Data.backgroundTaskFinished();
}
}
public static class Result {
+ public static String ERR_JSON_PARSER_ERROR = "err_json_parser";
public String error;
public List<LedgerAccount> accounts;
public List<LedgerTransaction> transactions;
case html:
legacySendOkWithRetry();
break;
- case pre_1_15:
+ case v1_14:
send_1_14_OK();
break;
- case post_1_14:
+ case v1_15:
send_1_15_OK();
break;
default:
}
public enum API {
- auto(0), html(-1), pre_1_15(-2), post_1_14(-3);
+ auto(0), html(-1), v1_14(-2), v1_15(-3), v1_19_1(-4);
private static final SparseArray<API> map = new SparseArray<>();
+ public static API[] allVersions = {v1_19_1, v1_15, v1_14};
static {
for (API item : API.values()) {
}
}
- private int value;
+ private final int value;
API(int value) {
this.value = value;
return resources.getString(R.string.api_auto);
case html:
return resources.getString(R.string.api_html);
- case pre_1_15:
- return resources.getString(R.string.api_pre_1_15);
- case post_1_14:
- return resources.getString(R.string.api_post_1_14);
+ case v1_14:
+ return resources.getString(R.string.api_1_14);
+ case v1_15:
+ return resources.getString(R.string.api_1_15);
+ case v1_19_1:
+ return resources.getString(R.string.api_1_19_1);
default:
throw new IllegalStateException("Unexpected value: " + value);
}
}
+ public String getDescription() {
+ switch (this) {
+ case auto:
+ return "(automatic)";
+ case html:
+ return "(HTML)";
+ case v1_14:
+ return "1.14";
+ case v1_15:
+ return "1.15";
+ case v1_19_1:
+ return "1.19.1";
+ default:
+ throw new IllegalStateException("Unexpected value: " + this);
+ }
+ }
}
-}
+}
\ No newline at end of file
import com.fasterxml.jackson.databind.MappingIterator;
import net.ktnx.mobileledger.async.RetrieveTransactionsTask;
+import net.ktnx.mobileledger.async.SendTransactionTask;
import net.ktnx.mobileledger.model.LedgerAccount;
-import java.util.ArrayList;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.HashMap;
import static net.ktnx.mobileledger.utils.Logger.debug;
abstract public class AccountListParser {
protected MappingIterator<net.ktnx.mobileledger.json.ParsedLedgerAccount> 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<String, LedgerAccount> 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<String, LedgerAccount> 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<LedgerAccount> 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;
- }
}
--- /dev/null
+/*
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+package net.ktnx.mobileledger.json;
+
+public class ApiNotSupportedException extends Throwable {}
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<ParsedBalance> aibalance;
+ public abstract List<SimpleBalance> getSimpleBalance();
public String getAname() {
return aname;
}
public void setAnumpostings(int anumpostings) {
this.anumpostings = anumpostings;
}
- public List<ParsedBalance> getAibalance() {
- return aibalance;
+ public LedgerAccount toLedgerAccount(RetrieveTransactionsTask task,
+ HashMap<String, LedgerAccount> 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<LedgerAccount> 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<ParsedBalance> 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;
+ }
}
}
--- /dev/null
+/*
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+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;
+ }
+}
--- /dev/null
+/*
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+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;
+}
/*
- * 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
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<ParsedLedgerAccount> iterator;
+public class AccountListParser extends net.ktnx.mobileledger.json.AccountListParser {
public AccountListParser(InputStream input) throws IOException {
ObjectMapper mapper = new ObjectMapper();
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;
}
}
/*
- * 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
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;
}
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<ParsedBalance> aebalance;
private List<ParsedBalance> aibalance;
- private String aname;
- private int anumpostings;
public ParsedLedgerAccount() {
}
- public int getAnumpostings() {
- return anumpostings;
- }
- public void setAnumpostings(int anumpostings) {
- this.anumpostings = anumpostings;
- }
public List<ParsedBalance> getAebalance() {
return aebalance;
}
public void setAibalance(List<ParsedBalance> aibalance) {
this.aibalance = aibalance;
}
- public String getAname() {
- return aname;
- }
- public void setAname(String aname) {
- this.aname = aname;
- }
+ @Override
+ public List<SimpleBalance> getSimpleBalance() {
+ List<SimpleBalance> result = new ArrayList<SimpleBalance>();
+ for (ParsedBalance b : getAibalance()) {
+ result.add(new SimpleBalance(b.getAcommodity(), b.getAquantity()
+ .asFloat()));
+ }
+ return result;
+ }
}
/*
- * 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
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() {
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;
- }
}
/*
- * 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
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<ParsedLedgerTransaction> iterator;
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;
}
}
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;
iterator = reader.readValues(input);
}
+ @Override
+ public SendTransactionTask.API getApiVersion() {
+ return SendTransactionTask.API.v1_15;
+ }
}
/*
- * 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
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import java.util.List;
-
@JsonIgnoreProperties(ignoreUnknown = true)
-public class ParsedLedgerAccount extends net.ktnx.mobileledger.json.ParsedLedgerAccount {
- private List<ParsedBalance> aebalance;
- public ParsedLedgerAccount() {
- }
- public List<ParsedBalance> getAebalance() {
- return aebalance;
- }
- public void setAebalance(List<ParsedBalance> aebalance) {
- this.aebalance = aebalance;
- }
-}
+public class ParsedLedgerAccount extends net.ktnx.mobileledger.json.v1_14.ParsedLedgerAccount {}
/*
- * 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
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 {}
/*
- * 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
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<ParsedLedgerTransaction> iterator;
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;
}
}
--- /dev/null
+/*
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+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;
+ }
+}
--- /dev/null
+/*
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+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;
+ }
+
+}
--- /dev/null
+/*
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+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;
+ }
+}
--- /dev/null
+/*
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+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<ParsedBalance> aebalance;
+ private List<ParsedBalance> aibalance;
+ public ParsedLedgerAccount() {
+ }
+ public List<ParsedBalance> getAibalance() {
+ return aibalance;
+ }
+ public void setAibalance(List<ParsedBalance> aibalance) {
+ this.aibalance = aibalance;
+ }
+ public List<ParsedBalance> getAebalance() {
+ return aebalance;
+ }
+ public void setAebalance(List<ParsedBalance> aebalance) {
+ this.aebalance = aebalance;
+ }
+ @Override
+ public List<SimpleBalance> getSimpleBalance() {
+ List<SimpleBalance> result = new ArrayList<SimpleBalance>();
+ for (ParsedBalance b : getAibalance()) {
+ result.add(new SimpleBalance(b.getAcommodity(), b.getAquantity()
+ .asFloat()));
+ }
+
+ return result;
+ }
+}
--- /dev/null
+/*
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+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<ParsedPosting> tpostings;
+ private List<List<String>> 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<ParsedPosting> 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<List<String>> getTtags() {
+ return ttags;
+ }
+ public void setTtags(List<List<String>> 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<ParsedPosting> getTpostings() {
+ return tpostings;
+ }
+ public void setTpostings(List<ParsedPosting> 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<ParsedPosting> postings = tpostings;
+
+ if (postings != null) {
+ for (ParsedPosting p : postings) {
+ tr.addAccount(p.asLedgerAccount());
+ }
+ }
+
+ tr.markDataAsLoaded();
+ return tr;
+ }
+}
--- /dev/null
+/*
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+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<ParsedAmount> pamount;
+ private String pdate = null;
+ private String pdate2 = null;
+ private String ptype = "RegularPosting";
+ private String pcomment = "";
+ private List<List<String>> 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<ParsedAmount> 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<List<String>> getPtags() {
+ return ptags;
+ }
+ public void setPtags(List<List<String>> 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<ParsedAmount> getPamount() {
+ return pamount;
+ }
+ public void setPamount(List<ParsedAmount> pamount) {
+ this.pamount = pamount;
+ }
+ public LedgerTransactionAccount asLedgerAccount() {
+ ParsedAmount amt = pamount.get(0);
+ return new LedgerTransactionAccount(paccount, amt.getAquantity()
+ .asFloat(), amt.getAcommodity(),
+ getPcomment());
+ }
+
+}
--- /dev/null
+/*
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+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;
+ }
+}
--- /dev/null
+/*
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+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;
+ }
+ }
+}
--- /dev/null
+/*
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+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 {}
--- /dev/null
+/*
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+package net.ktnx.mobileledger.json.v1_19_1;
+
+import java.util.ArrayList;
+import java.util.List;
+
+class ParsedSourcePos {
+ private String tag = "JournalSourcePos";
+ private List<Object> 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<Object> getContents() {
+ return contents;
+ }
+ public void setContents(List<Object> contents) {
+ this.contents = contents;
+ }
+}
--- /dev/null
+/*
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+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;
+ }
+}
--- /dev/null
+/*
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+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<ParsedLedgerTransaction> 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;
+ }
+}
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;
}
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;
@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;
+ }
}
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()
});
}
}
- private int value;
+ private final int value;
FutureDates(int value) {
this.value = value;
}
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;
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)
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;
}
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);
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:
</LinearLayout>
<androidx.constraintlayout.widget.ConstraintLayout
- android:id="@+id/api_version_layout"
+ android:id="@+id/server_version_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
>
<TextView
- android:id="@+id/api_version_label"
+ android:id="@+id/server_version_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
- android:text="@string/profile_api_version_title"
+ android:text="@string/profile_server_version_title"
android:textAppearance="?android:textAppearanceListItem"
- android:layout_marginEnd="24dp"
- app:layout_constraintEnd_toStartOf="@id/detected_version_text"
+ app:layout_constraintEnd_toStartOf="@id/server_version_detect_button"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView
- android:id="@+id/api_version_text"
+ android:id="@+id/detected_server_version_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
- android:textAppearance="?android:textAppearanceListItemSecondary"
- android:textColor="?attr/textColor"
- app:layout_constraintEnd_toStartOf="@id/detected_version_text"
- android:layout_marginEnd="24dp"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@id/api_version_label"
- />
- <TextView
- android:id="@+id/detected_version_text"
- android:layout_width="wrap_content"
- android:layout_height="0dp"
android:layout_marginEnd="8dp"
- android:text="@string/api_version_unknown_label"
+ android:gravity="start"
android:textAppearance="?android:textAppearanceListItemSecondary"
android:textColor="?attr/textColor"
- app:layout_constraintEnd_toStartOf="@id/api_version_detect_button"
- android:gravity="bottom"
+ android:text="@string/server_version_unknown_label"
+ app:layout_constraintEnd_toStartOf="@id/server_version_detect_button"
app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/server_version_label"
/>
<ProgressBar
android:layout_height="24dp"
- android:id="@+id/api_version_detect_button"
+ android:id="@+id/server_version_detect_button"
android:layout_width="24dp"
android:indeterminate="true"
android:foregroundGravity="bottom"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toEndOf="@id/detected_server_version_text"
android:visibility="invisible"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/api_version_layout"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="16dp"
+ >
+
+ <TextView
+ android:id="@+id/api_version_label"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="24dp"
+ android:text="@string/profile_api_version_title"
+ android:textAppearance="?android:textAppearanceListItem"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ />
+
+ <TextView
+ android:id="@+id/api_version_text"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="24dp"
+ android:textAppearance="?android:textAppearanceListItemSecondary"
+ android:textColor="?attr/textColor"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/api_version_label"
+ />
+ </androidx.constraintlayout.widget.ConstraintLayout>
+
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/profile_permit_posting"
android:layout_width="match_parent"
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright © 2019 Damyan Ivanov.
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ 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
<item
android:id="@+id/api_version_menu_auto"
- android:title="@string/api_auto" />
+ android:title="@string/api_auto"
+ />
<item
- android:id="@+id/api_version_menu_post_1_14"
- android:title="@string/api_post_1_14" />
+ android:id="@+id/api_version_menu_1_19_1"
+ android:title="@string/api_1_19_1"
+ />
<item
- android:id="@+id/api_version_menu_pre_1_15"
- android:title="@string/api_pre_1_15" />
+ android:id="@+id/api_version_menu_1_15"
+ android:title="@string/api_1_15"
+ />
+ <item
+ android:id="@+id/api_version_menu_1_14"
+ android:title="@string/api_1_14"
+ />
<item
android:id="@+id/api_version_menu_html"
- android:title="@string/api_html" />
+ android:title="@string/api_html"
+ />
</menu>
\ No newline at end of file
<string name="future_dates_all">Без ограничения</string>
<string name="future_dates_none">Без въвеждане на бъдещи дати</string>
<string name="profile_future_dates_label">Въвеждане на дати в бъдещето</string>
- <string name="api_auto">Ð\90вÑ\82омаÑ\82иÑ\87но оÑ\82кÑ\80иване</string>
+ <string name="api_auto">Ð\90вÑ\82омаÑ\82иÑ\87на</string>
<string name="api_html">Версия преди 1.14</string>
- <string name="api_post_1_14">Версия 1.15 или по-нова</string>
- <string name="api_pre_1_15">Версия 1.14.x</string>
- <string name="profile_api_version_title">Версия на сървъра</string>
+ <string name="api_1_15">Версия 1.15</string>
+ <string name="api_1_14">Версия 1.14</string>
+ <string name="profile_api_version_title">Версия на протокола</string>
<string name="add_button">Добавяне…</string>
<string name="close_button">Затваряне</string>
<string name="transaction_account_comment_hint">бележка</string>
<string name="nav_header_desc">Заглавна част на страничния панел</string>
<string name="transaction_count_summary">%,d движения към %s</string>
<string name="account_count_summary">%,d сметки към %s</string>
- <string name="api_version_unknown_label">Неизвестна</string>
- <string name="api_pre_1_19">Преди 1.20.?</string>
+ <string name="server_version_unknown_label">Неизвестна</string>
+ <string name="detected_server_pre_1_20_1">Преди 1.20.1</string>
<string name="detected_version_label">Открита версия</string>
<string name="new_transaction_fab_description">Знак плюс</string>
+ <string name="api_1_19_1">Версия 1.19.1</string>
+ <string name="profile_server_version_title">Версия на сървъра</string>
+ <string name="err_json_parser_error">Грешка при разчитане на отговора от сървъра. Вероятно настроената врсия на протокола е грешна.</string>
+ <string name="btn_profile_options">Настройка на профила</string>
</resources>
<string name="future_dates_365">Up to a year</string>
<string name="future_dates_all">Without restrictions</string>
<string name="api_html">Version before 1.14</string>
- <string name="api_pre_1_15">Version 1.14.x</string>
- <string name="api_post_1_14">Version 1.15 and above</string>
- <string name="api_auto">Detect automatically</string>
- <string name="profile_api_version_title">Backend server version</string>
+ <string name="api_1_14">Version 1.14</string>
+ <string name="api_1_15">Version 1.15</string>
+ <string name="api_auto">Automatic</string>
+ <string name="profile_api_version_title">Protocol version</string>
<string name="currency_symbol" translatable="false">¤</string>
<string name="add_button">Add…</string>
<string name="close_button">Close</string>
<string name="sub_accounts_expand_collapse_trigger_description">Sub-accounts expand/collapse trigger</string>
<string name="transaction_count_summary">%,d transactions as of %s</string>
<string name="account_count_summary">%,d accounts as of %s</string>
- <string name="api_version_unknown_label">Unknown</string>
- <string name="api_pre_1_19">Before 1.20.?</string>
+ <string name="server_version_unknown_label">Unknown</string>
+ <string name="detected_server_pre_1_20_1">Before 1.20.1</string>
<string name="detected_version_label">Detected version</string>
<string name="new_transaction_fab_description">Plus icon</string>
+ <string name="api_1_19_1">Version 1.19.1</string>
+ <string name="profile_server_version_title">Server version</string>
+ <string name="err_json_parser_error">Error parsing packend JSON response. Perhaps the configured API version doesn\'t match</string>
+ <string name="btn_profile_options">Configure profile</string>
</resources>