import androidx.lifecycle.ViewModel;
import net.ktnx.mobileledger.BuildConfig;
+import net.ktnx.mobileledger.db.Currency;
import net.ktnx.mobileledger.db.DB;
+import net.ktnx.mobileledger.db.Profile;
import net.ktnx.mobileledger.db.TemplateAccount;
import net.ktnx.mobileledger.db.TemplateHeader;
+import net.ktnx.mobileledger.db.TransactionWithAccounts;
import net.ktnx.mobileledger.model.Data;
import net.ktnx.mobileledger.model.InertMutableLiveData;
import net.ktnx.mobileledger.model.LedgerTransaction;
import net.ktnx.mobileledger.model.LedgerTransactionAccount;
import net.ktnx.mobileledger.model.MatchedTemplate;
-import net.ktnx.mobileledger.model.MobileLedgerProfile;
import net.ktnx.mobileledger.utils.Globals;
import net.ktnx.mobileledger.utils.Logger;
import net.ktnx.mobileledger.utils.Misc;
private final MutableLiveData<Boolean> simulateSave = new InertMutableLiveData<>(false);
private final AtomicInteger busyCounter = new AtomicInteger(0);
private final MutableLiveData<Boolean> busyFlag = new InertMutableLiveData<>(false);
- private final Observer<MobileLedgerProfile> profileObserver = profile -> {
+ private final Observer<Profile> profileObserver = profile -> {
showCurrency.postValue(profile.getShowCommodityByDefault());
showComments.postValue(profile.getShowCommentsByDefault());
};
checkTransactionSubmittable(newList);
setItemsWithoutSubmittableChecks(newList);
}
+ private void replaceItems(@NonNull List<Item> newList) {
+ renumberItems();
+
+ setItems(newList);
+ }
+ /**
+ * make old items replaceable in-place. makes the new values visually blend in
+ */
+ private void renumberItems() {
+ renumberItems(items.getValue());
+ }
+ private void renumberItems(List<Item> list) {
+ if (list == null) {
+ return;
+ }
+
+ int id = 0;
+ for (Item item : list)
+ item.id = id++;
+ }
private void setItemsWithoutSubmittableChecks(@NonNull List<Item> list) {
- Logger.debug("new-trans", "model: Setting new item list");
final int cnt = list.size();
for (int i = 1; i < cnt - 1; i++) {
final TransactionAccount item = list.get(i)
list.set(cnt - 1, replacement);
}
+ if (BuildConfig.DEBUG)
+ dumpItemList("Before setValue()", list);
items.setValue(list);
}
private List<Item> copyList() {
- return copyList(null);
- }
- private List<Item> copyList(@Nullable List<Item> source) {
List<Item> copy = new ArrayList<>();
- List<Item> oldList = (source == null) ? items.getValue() : source;
+ List<Item> oldList = items.getValue();
if (oldList != null)
for (Item item : oldList) {
return copy;
}
- private List<Item> shallowCopyListWithoutItem(int position) {
+ private List<Item> copyListWithoutItem(int position) {
List<Item> copy = new ArrayList<>();
List<Item> oldList = items.getValue();
for (Item item : oldList) {
if (i++ == position)
continue;
- copy.add(item);
+ copy.add(Item.from(item));
}
}
return copy;
}
private List<Item> shallowCopyList() {
- return new ArrayList<>(items.getValue());
+ return new ArrayList<>(Objects.requireNonNull(items.getValue()));
}
LiveData<Boolean> getShowComments() {
return showComments;
return this.isSubmittable;
}
void reset() {
+ Logger.debug("new-trans", "Resetting model");
List<Item> list = new ArrayList<>();
+ Item.resetIdDispenser();
list.add(new TransactionHead(""));
- list.add(new TransactionAccount(""));
- list.add(new TransactionAccount(""));
+ final String defaultCurrency = Objects.requireNonNull(Data.getProfile())
+ .getDefaultCommodity();
+ list.add(new TransactionAccount("", defaultCurrency));
+ list.add(new TransactionAccount("", defaultCurrency));
+ noteFocusChanged(0, FocusedElement.Description);
+ renumberItems();
+ isSubmittable.setValue(false);
setItemsWithoutSubmittableChecks(list);
}
boolean accountsInInitialState() {
if (amount != null && acc.getNegateAmount() != null && acc.getNegateAmount())
amount = -amount;
- // TODO currency
TransactionAccount accRow = new TransactionAccount(accountName);
accRow.setComment(accountComment);
if (amount != null)
accRow.setAmount(amount);
+ accRow.setCurrency(
+ extractCurrencyFromMatches(matchResult, acc.getCurrencyMatchGroup(),
+ acc.getCurrencyObject()));
newItems.add(accRow);
}
- items.postValue(newItems);
+ renumberItems(newItems);
+ Misc.onMainThread(() -> replaceItems(newItems));
});
}
+ @NonNull
+ private String extractCurrencyFromMatches(MatchResult m, Integer group, Currency literal) {
+ return Misc.nullIsEmpty(
+ extractStringFromMatches(m, group, (literal == null) ? "" : literal.getName()));
+ }
private int extractIntFromMatches(MatchResult m, Integer group, Integer literal) {
if (literal != null)
return literal;
if (group != null) {
int grp = group;
- if (grp > 0 & grp <= m.groupCount())
+ if (grp > 0 && grp <= m.groupCount())
try {
return Integer.parseInt(m.group(grp));
}
return 0;
}
+ @Nullable
private String extractStringFromMatches(MatchResult m, Integer group, String literal) {
if (literal != null)
return literal;
if (group != null) {
int grp = group;
- if (grp > 0 & grp <= m.groupCount())
+ if (grp > 0 && grp <= m.groupCount())
return m.group(grp);
}
if (group != null) {
int grp = group;
- if (grp > 0 & grp <= m.groupCount())
+ if (grp > 0 && grp <= m.groupCount())
try {
return Float.valueOf(m.group(grp));
}
return null;
}
void removeItem(int pos) {
- List<Item> newList = shallowCopyListWithoutItem(pos);
+ Logger.debug("new-trans", String.format(Locale.US, "Removing item at position %d", pos));
+ List<Item> newList = copyListWithoutItem(pos);
+ final FocusInfo fi = focusInfo.getValue();
+ if ((fi != null) && (pos < fi.position))
+ noteFocusChanged(fi.position - 1, fi.element);
setItems(newList);
}
void noteFocusChanged(int position, FocusedElement element) {
List<Item> newList = shallowCopyList();
Item item = newList.remove(fromIndex);
newList.add(toIndex, item);
+
+ FocusInfo fi = focusInfo.getValue();
+ if (fi != null && fi.position == fromIndex)
+ noteFocusChanged(toIndex, fi.element);
+
items.setValue(newList); // same count, same submittable state
}
void moveItemLast(List<Item> list, int index) {
list.add(list.remove(index));
}
void toggleCurrencyVisible() {
- showCurrency.setValue(!Objects.requireNonNull(showCurrency.getValue()));
+ final boolean newValue = !Objects.requireNonNull(showCurrency.getValue());
+
+ // remove currency from all items, or reset currency to the default
+ // no need to clone the list, because the removal of the currency won't lead to
+ // visual changes -- the currency fields will be hidden or reset to default anyway
+ // still, there may be changes in the submittable state
+ final List<Item> list = Objects.requireNonNull(this.items.getValue());
+ final Profile profile = Objects.requireNonNull(Data.getProfile());
+ for (int i = 1; i < list.size(); i++) {
+ ((TransactionAccount) list.get(i)).setCurrency(
+ newValue ? profile.getDefaultCommodity() : "");
+ }
+ checkTransactionSubmittable(null);
+ showCurrency.setValue(newValue);
}
void stopObservingBusyFlag(Observer<Boolean> observer) {
busyFlag.removeObserver(observer);
List<Item> list = Objects.requireNonNull(items.getValue());
TransactionHead head = list.get(0)
.toTransactionHead();
- SimpleDate date = head.getDate();
LedgerTransaction tr = head.asLedgerTransaction();
tr.setComment(head.getComment());
return tr;
}
- void loadTransactionIntoModel(String profileUUID, int transactionId) {
+ void loadTransactionIntoModel(@NonNull TransactionWithAccounts tr) {
List<Item> newList = new ArrayList<>();
- LedgerTransaction tr;
- MobileLedgerProfile profile = Data.getProfile(profileUUID);
- if (profile == null)
- throw new RuntimeException(String.format(
- "Unable to find profile %s, which is supposed to contain transaction %d",
- profileUUID, transactionId));
+ Item.resetIdDispenser();
- tr = profile.loadTransaction(transactionId);
- TransactionHead head = new TransactionHead(tr.getDescription());
- head.setComment(tr.getComment());
+ Item currentHead = Objects.requireNonNull(items.getValue())
+ .get(0);
+ TransactionHead head = new TransactionHead(tr.transaction.getDescription());
+ head.setComment(tr.transaction.getComment());
+ if (currentHead instanceof TransactionHead)
+ head.setDate(((TransactionHead) currentHead).date);
newList.add(head);
- List<LedgerTransactionAccount> accounts = tr.getAccounts();
+ List<LedgerTransactionAccount> accounts = new ArrayList<>();
+ for (net.ktnx.mobileledger.db.TransactionAccount acc : tr.accounts) {
+ accounts.add(new LedgerTransactionAccount(acc));
+ }
TransactionAccount firstNegative = null;
TransactionAccount firstPositive = null;
int negativeCount = 0;
for (int i = 0; i < accounts.size(); i++) {
LedgerTransactionAccount acc = accounts.get(i);
- TransactionAccount item =
- new TransactionAccount(acc.getAccountName(), acc.getCurrency());
+ TransactionAccount item = new TransactionAccount(acc.getAccountName(),
+ Misc.nullIsEmpty(acc.getCurrency()));
newList.add(item);
item.setAccountName(acc.getAccountName());
moveItemLast(newList, singlePositiveIndex);
}
- setItems(newList);
-
- noteFocusChanged(1, FocusedElement.Amount);
+ Misc.onMainThread(() -> {
+ setItems(newList);
+ noteFocusChanged(1, FocusedElement.Amount);
+ });
}
/**
* A transaction is submittable if:
@SuppressLint("DefaultLocale")
void checkTransactionSubmittable(@Nullable List<Item> list) {
boolean workingWithLiveList = false;
- boolean liveListCopied = false;
if (list == null) {
- list = Objects.requireNonNull(items.getValue());
+ list = copyList();
workingWithLiveList = true;
}
if (BuildConfig.DEBUG)
- dumpItemList("Before submittable checks", list);
+ dumpItemList(String.format("Before submittable checks (%s)",
+ workingWithLiveList ? "LIVE LIST" : "custom list"), list);
int accounts = 0;
final BalanceForCurrency balance = new BalanceForCurrency();
submittable = false;
}
+ boolean hasInvalidAmount = false;
+
for (int i = 1; i < list.size(); i++) {
TransactionAccount item = list.get(i)
.toTransactionAccount();
itemsWithAccountForCurrency.add(currName, item);
}
- if (!item.isAmountValid()) {
- Logger.debug("submittable",
- String.format("Not submittable: row %d has an invalid amount", i + 1));
- submittable = false;
- }
- else if (item.isAmountSet()) {
+ if (item.isAmountSet() && item.isAmountValid()) {
itemsWithAmountForCurrency.add(currName, item);
balance.add(currName, item.getAmount());
}
else {
+ if (!item.isAmountValid()) {
+ Logger.debug("submittable",
+ String.format("Not submittable: row %d has an invalid amount", i));
+ submittable = false;
+ hasInvalidAmount = true;
+ }
+
itemsWithEmptyAmountForCurrency.add(currName, item);
if (!accName.isEmpty())
if (Misc.equalStrings(acc.getCurrency(), balCurrency)) {
if (BuildConfig.DEBUG)
Logger.debug("submittable",
- String.format("Resetting hint of '%s' [%s]",
- Misc.nullIsEmpty(acc.getAccountName()),
+ String.format(Locale.US, "Resetting hint of %d:'%s' [%s]",
+ i, Misc.nullIsEmpty(acc.getAccountName()),
balCurrency));
// skip if the amount is set, in which case the hint is not
// important/visible
if (!acc.isAmountSet() && acc.amountHintIsSet &&
!TextUtils.isEmpty(acc.getAmountHint()))
{
- if (workingWithLiveList && !liveListCopied) {
- list = copyList(list);
- liveListCopied = true;
- }
- final TransactionAccount newAcc = new TransactionAccount(acc);
- newAcc.setAmountHint(null);
- if (!liveListCopied) {
- list = copyList(list);
- liveListCopied = true;
- }
- list.set(i, newAcc);
+ acc.setAmountHint(null);
listChanged = true;
}
}
if (BuildConfig.DEBUG) {
if (balanceReceiversCount == 0)
Logger.debug("submittable", String.format(
- "Transaction not submittable [%s]: non-zero balance " +
+ "Transaction not submittable [curr:%s]: non-zero balance " +
"with no empty amounts with accounts", balCurrency));
else
Logger.debug("submittable", String.format(
- "Transaction not submittable [%s]: non-zero balance " +
+ "Transaction not submittable [curr:%s]: non-zero balance " +
"with multiple empty amounts with accounts", balCurrency));
}
submittable = false;
continue;
if (item == receiver) {
- final String hint = String.format("%1.2f", -currencyBalance);
+ final String hint = Data.formatNumber(-currencyBalance);
if (!acc.isAmountHintSet() ||
- !TextUtils.equals(acc.getAmountHint(), hint))
+ !Misc.equalStrings(acc.getAmountHint(), hint))
{
Logger.debug("submittable",
String.format("Setting amount hint of {%s} to %s [%s]",
acc.toString(), hint, balCurrency));
- if (workingWithLiveList & !liveListCopied) {
- list = copyList(list);
- liveListCopied = true;
- }
- final TransactionAccount newAcc = new TransactionAccount(acc);
- newAcc.setAmountHint(hint);
- list.set(i, newAcc);
+ acc.setAmountHint(hint);
listChanged = true;
}
}
Misc.nullIsEmpty(acc.getAccountName()),
balCurrency));
if (acc.amountHintIsSet && !TextUtils.isEmpty(acc.getAmountHint())) {
- if (workingWithLiveList && !liveListCopied) {
- list = copyList(list);
- liveListCopied = true;
- }
- final TransactionAccount newAcc = new TransactionAccount(acc);
- newAcc.setAmountHint(null);
- list.set(i, newAcc);
+ acc.setAmountHint(null);
listChanged = true;
}
}
// 5) a row with an empty account name or empty amount is guaranteed to exist for
// each commodity
- for (String balCurrency : balance.currencies()) {
- int currEmptyRows = itemsWithEmptyAccountForCurrency.size(balCurrency);
- int currRows = itemsForCurrency.size(balCurrency);
- int currAccounts = itemsWithAccountForCurrency.size(balCurrency);
- int currAmounts = itemsWithAmountForCurrency.size(balCurrency);
- if ((currEmptyRows == 0) &&
- ((currRows == currAccounts) || (currRows == currAmounts)))
- {
- // perhaps there already is an unused empty row for another currency that
- // is not used?
+ if (!hasInvalidAmount) {
+ for (String balCurrency : balance.currencies()) {
+ int currEmptyRows = itemsWithEmptyAccountForCurrency.size(balCurrency);
+ int currRows = itemsForCurrency.size(balCurrency);
+ int currAccounts = itemsWithAccountForCurrency.size(balCurrency);
+ int currAmounts = itemsWithAmountForCurrency.size(balCurrency);
+ if ((currEmptyRows == 0) &&
+ ((currRows == currAccounts) || (currRows == currAmounts)))
+ {
+ // perhaps there already is an unused empty row for another currency that
+ // is not used?
// boolean foundIt = false;
// for (Item item : emptyRows) {
// Currency itemCurrency = item.getCurrency();
// if (Misc.isZero(balance.get(itemCurrencyName))) {
// item.setCurrency(Currency.loadByName(balCurrency));
// item.setAmountHint(
-// String.format("%1.2f", -balance.get(balCurrency)));
+// Data.formatNumber(-balance.get(balCurrency)));
// foundIt = true;
// break;
// }
// }
//
// if (!foundIt)
- if (workingWithLiveList && !liveListCopied) {
- list = copyList(list);
- liveListCopied = true;
+ final TransactionAccount newAcc = new TransactionAccount("", balCurrency);
+ final float bal = balance.get(balCurrency);
+ if (!Misc.isZero(bal) && currAmounts == currRows)
+ newAcc.setAmountHint(Data.formatNumber(-bal));
+ Logger.debug("submittable",
+ String.format("Adding new item with %s for currency %s",
+ newAcc.getAmountHint(), balCurrency));
+ list.add(newAcc);
+ listChanged = true;
}
- final TransactionAccount newAcc = new TransactionAccount("", balCurrency);
- final float bal = balance.get(balCurrency);
- if (!Misc.isZero(bal) && currAmounts == currRows)
- newAcc.setAmountHint(String.format("%4.2f", -bal));
- Logger.debug("submittable",
- String.format("Adding new item with %s for currency %s",
- newAcc.getAmountHint(), balCurrency));
- list.add(newAcc);
- listChanged = true;
}
}
for (String currName : emptyRowsForCurrency.currencies()) {
List<Item> emptyItems = emptyRowsForCurrency.getList(currName);
while ((list.size() > MIN_ITEMS) && (emptyItems.size() > 1)) {
- if (workingWithLiveList && !liveListCopied) {
- list = copyList(list);
- liveListCopied = true;
- }
// the list is a copy, so the empty item is no longer present
Item itemToRemove = emptyItems.remove(1);
removeItemById(list, itemToRemove.id);
List<Item> currItems = itemsForCurrency.getList(currName);
if (currItems.size() == 1) {
- if (workingWithLiveList && !liveListCopied) {
- list = copyList(list);
- liveListCopied = true;
- }
// the list is a copy, so the empty item is no longer present
removeItemById(list, emptyItems.get(0).id);
listChanged = true;
// 6) at least two rows need to be present in the ledger
// (the list also contains header and trailer)
while (list.size() < MIN_ITEMS) {
- if (workingWithLiveList && !liveListCopied) {
- list = copyList(list);
- liveListCopied = true;
- }
list.add(new TransactionAccount(""));
listChanged = true;
}
-
Logger.debug("submittable", submittable ? "YES" : "NO");
isSubmittable.setValue(submittable);
private static int idDispenser = 0;
protected int id;
private Item() {
- synchronized (Item.class) {
- id = ++idDispenser;
- }
+ if (this instanceof TransactionHead)
+ id = 0;
+ else
+ synchronized (Item.class) {
+ id = ++idDispenser;
+ }
+ }
+ public Item(int id) {
+ this.id = id;
}
public static Item from(Item origin) {
if (origin instanceof TransactionHead)
return new TransactionAccount((TransactionAccount) origin);
throw new RuntimeException("Don't know how to handle " + origin);
}
+ private static void resetIdDispenser() {
+ idDispenser = 0;
+ }
public int getId() {
return id;
}
this.description = description;
}
public TransactionHead(TransactionHead origin) {
- id = origin.id;
+ super(origin.id);
date = origin.date;
description = origin.description;
comment = origin.comment;
if (TextUtils.isEmpty(description))
b.append(" «no description»");
else
- b.append(String.format(" descr'%s'", description));
+ b.append(String.format(" '%s'", description));
if (date != null)
b.append(String.format("@%s", date.toString()));
return ItemType.generalData;
}
public LedgerTransaction asLedgerTransaction() {
- return new LedgerTransaction(null, date, description, Data.getProfile());
+ return new LedgerTransaction(0, (date == null) ? SimpleDate.today() : date, description,
+ Objects.requireNonNull(Data.getProfile()));
}
public boolean equalContents(TransactionHead other) {
if (other == null)
return false;
return Objects.equals(date, other.date) &&
- TextUtils.equals(description, other.description) &&
- TextUtils.equals(comment, other.comment);
+ Misc.equalStrings(description, other.description) &&
+ Misc.equalStrings(comment, other.comment);
}
}
private String accountName;
private String amountHint;
private String comment;
- private String currency;
+ @NotNull
+ private String currency = "";
private float amount;
private boolean amountSet;
private boolean amountValid = true;
+ @NotNull
+ private String amountText = "";
private FocusedElement focusedElement = FocusedElement.Account;
- private boolean amountHintIsSet = true;
+ private boolean amountHintIsSet = false;
private boolean isLast = false;
+ private int accountNameCursorPosition;
public TransactionAccount(TransactionAccount origin) {
- id = origin.id;
+ super(origin.id);
accountName = origin.accountName;
amount = origin.amount;
amountSet = origin.amountSet;
amountHint = origin.amountHint;
amountHintIsSet = origin.amountHintIsSet;
+ amountText = origin.amountText;
comment = origin.comment;
currency = origin.currency;
amountValid = origin.amountValid;
focusedElement = origin.focusedElement;
isLast = origin.isLast;
- }
- public TransactionAccount(LedgerTransactionAccount account) {
- super();
- currency = account.getCurrency();
- amount = account.getAmount();
+ accountNameCursorPosition = origin.accountNameCursorPosition;
}
public TransactionAccount(String accountName) {
super();
this.accountName = accountName;
}
- public TransactionAccount(String accountName, String currency) {
+ public TransactionAccount(String accountName, @NotNull String currency) {
super();
this.accountName = accountName;
this.currency = currency;
}
+ public @NotNull String getAmountText() {
+ return amountText;
+ }
+ public void setAmountText(@NotNull String amountText) {
+ this.amountText = amountText;
+ }
+ public boolean setAndCheckAmountText(@NotNull String amountText) {
+ String amtText = amountText.trim();
+ this.amountText = amtText;
+
+ boolean significantChange = false;
+
+ if (amtText.isEmpty()) {
+ if (amountSet) {
+ significantChange = true;
+ }
+ resetAmount();
+ }
+ else {
+ try {
+ amtText = amtText.replace(Data.getDecimalSeparator(), Data.decimalDot);
+ final float parsedAmount = Float.parseFloat(amtText);
+ if (!amountSet || !amountValid || !Misc.equalFloats(parsedAmount, amount))
+ significantChange = true;
+ amount = parsedAmount;
+ amountSet = true;
+ amountValid = true;
+ }
+ catch (NumberFormatException e) {
+ Logger.debug("new-trans", String.format(
+ "assuming amount is not set due to number format exception. " +
+ "input was '%s'", amtText));
+ if (amountValid) // it was valid and now it's not
+ significantChange = true;
+ amountValid = false;
+ }
+ }
+
+ return significantChange;
+ }
public boolean isLast() {
return isLast;
}
public void setAmount(float amount) {
this.amount = amount;
amountSet = true;
+ amountValid = true;
+ amountText = Data.formatNumber(amount);
}
public void resetAmount() {
amountSet = false;
+ amountValid = true;
+ amountText = "";
}
@Override
public ItemType getType() {
public void setComment(String comment) {
this.comment = comment;
}
+ @NotNull
public String getCurrency() {
return currency;
}
- public void setCurrency(String currency) {
- this.currency = currency;
+ public void setCurrency(@org.jetbrains.annotations.Nullable String currency) {
+ this.currency = Misc.nullIsEmpty(currency);
}
public boolean isAmountValid() {
return amountValid;
}
@SuppressLint("DefaultLocale")
@Override
+ @NotNull
public String toString() {
StringBuilder b = new StringBuilder();
b.append(String.format("id:%d/%s", id, Integer.toHexString(hashCode())));
b.append(String.format(" acc'%s'", accountName));
if (amountSet)
- b.append(String.format(" %4.2f", amount));
+ b.append(amountText)
+ .append(" [")
+ .append(amountValid ? "valid" : "invalid")
+ .append("] ")
+ .append(String.format(Locale.ROOT, " {raw %4.2f}", amount));
else if (amountHintIsSet)
- b.append(String.format(" (%s)", amountHint));
+ b.append(String.format(" (hint %s)", amountHint));
if (!TextUtils.isEmpty(currency))
b.append(" ")
if (!TextUtils.isEmpty(comment))
b.append(String.format(" /%s/", comment));
+ if (isLast)
+ b.append(" last");
+
return b.toString();
}
public boolean equalContents(TransactionAccount other) {
if (other == null)
return false;
- boolean equal = TextUtils.equals(accountName, other.accountName);
- equal = equal && TextUtils.equals(comment, other.comment) &&
- (amountSet ? other.amountSet && amount == other.amount : !other.amountSet);
+ boolean equal = Misc.equalStrings(accountName, other.accountName);
+ equal = equal && Misc.equalStrings(comment, other.comment) &&
+ (amountSet ? other.amountSet && amountValid == other.amountValid &&
+ Misc.equalStrings(amountText, other.amountText)
+ : !other.amountSet);
// compare amount hint only if there is no amount
if (!amountSet)
equal = equal && (amountHintIsSet ? other.amountHintIsSet &&
- TextUtils.equals(amountHint, other.amountHint)
+ Misc.equalStrings(amountHint, other.amountHint)
: !other.amountHintIsSet);
- equal = equal && TextUtils.equals(currency, other.currency) && isLast == other.isLast;
+ equal = equal && Misc.equalStrings(currency, other.currency) && isLast == other.isLast;
Logger.debug("new-trans",
String.format("Comparing {%s} and {%s}: %s", this.toString(), other.toString(),
equal));
return equal;
}
+ public int getAccountNameCursorPosition() {
+ return accountNameCursorPosition;
+ }
+ public void setAccountNameCursorPosition(int position) {
+ this.accountNameCursorPosition = position;
+ }
}
private static class BalanceForCurrency {
}
private static class ItemsForCurrency {
- private final HashMap<String, List<Item>> hashMap = new HashMap<>();
+ private final HashMap<@NotNull String, List<Item>> hashMap = new HashMap<>();
@NonNull
- List<NewTransactionModel.Item> getList(@Nullable String currencyName) {
+ List<NewTransactionModel.Item> getList(@NotNull String currencyName) {
List<NewTransactionModel.Item> list = hashMap.get(currencyName);
if (list == null) {
list = new ArrayList<>();
}
return list;
}
- void add(@Nullable String currencyName, @NonNull NewTransactionModel.Item item) {
- getList(currencyName).add(item);
+ void add(@NotNull String currencyName, @NonNull NewTransactionModel.Item item) {
+ getList(Objects.requireNonNull(currencyName)).add(item);
}
- int size(@Nullable String currencyName) {
- return this.getList(currencyName)
+ int size(@NotNull String currencyName) {
+ return this.getList(Objects.requireNonNull(currencyName))
.size();
}
Set<String> currencies() {