X-Git-Url: https://git.ktnx.net/?a=blobdiff_plain;f=app%2Fsrc%2Fmain%2Fjava%2Fnet%2Fktnx%2Fmobileledger%2Fmodel%2FTemplateDetailsItem.java;h=f158f413196dace141b2f9f6cdb6f1e9cb1d92fe;hb=99ed62c9371fc199580720de7e72e6476413960f;hp=1f3211c4c797de00091ada0403b0a31b0bcb3c49;hpb=59ecc8c74f590acdc069f3816312c5febb62a13b;p=mobile-ledger.git diff --git a/app/src/main/java/net/ktnx/mobileledger/model/TemplateDetailsItem.java b/app/src/main/java/net/ktnx/mobileledger/model/TemplateDetailsItem.java index 1f3211c4..f158f413 100644 --- a/app/src/main/java/net/ktnx/mobileledger/model/TemplateDetailsItem.java +++ b/app/src/main/java/net/ktnx/mobileledger/model/TemplateDetailsItem.java @@ -18,6 +18,13 @@ package net.ktnx.mobileledger.model; import android.content.res.Resources; +import android.graphics.Color; +import android.graphics.Typeface; +import android.text.SpannableString; +import android.text.Spanned; +import android.text.style.ForegroundColorSpan; +import android.text.style.StyleSpan; +import android.text.style.UnderlineSpan; import androidx.annotation.NonNull; @@ -25,11 +32,14 @@ import net.ktnx.mobileledger.R; import net.ktnx.mobileledger.db.TemplateAccount; import net.ktnx.mobileledger.db.TemplateBase; import net.ktnx.mobileledger.db.TemplateHeader; +import net.ktnx.mobileledger.utils.Logger; import net.ktnx.mobileledger.utils.Misc; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; +import java.util.Locale; +import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; @@ -94,6 +104,7 @@ abstract public class TemplateDetailsItem { TemplateAccount pa = (TemplateAccount) p; AccountRow acc = createAccountRow(); acc.setId(pa.getId()); + acc.setPosition(pa.getPosition()); if (pa.getAccountNameMatchGroup() == null) acc.setAccountName(Misc.nullIsEmpty(pa.getAccountName())); @@ -217,6 +228,11 @@ abstract public class TemplateDetailsItem { result.setValue(initialValue); return result; } + public void copyFrom(@NonNull PossiblyMatchedValue origin) { + literalValue = origin.literalValue; + value = origin.value; + matchGroup = origin.matchGroup; + } public T getValue() { if (!literalValue) throw new IllegalStateException("Value is not literal"); @@ -278,8 +294,18 @@ abstract public class TemplateDetailsItem { PossiblyMatchedValue.withLiteralFloat(null); private final PossiblyMatchedValue currency = new PossiblyMatchedValue<>(); private boolean negateAmount; - private AccountRow() { + public AccountRow() { + super(Type.ACCOUNT_ITEM); + } + public AccountRow(AccountRow origin) { super(Type.ACCOUNT_ITEM); + id = origin.id; + position = origin.position; + accountName.copyFrom(origin.accountName); + accountComment.copyFrom(origin.accountComment); + amount.copyFrom(origin.amount); + currency.copyFrom(origin.currency); + negateAmount = origin.negateAmount; } public boolean isNegateAmount() { return negateAmount; @@ -352,8 +378,15 @@ abstract public class TemplateDetailsItem { return accountComment.hasLiteralValue(); } public boolean equalContents(AccountRow o) { + if (position != o.position) { + Logger.debug("cmpAcc", + String.format(Locale.US, "[%d] != [%d]: pos %d != pos %d", getId(), + o.getId(), position, o.position)); + return false; + } return amount.equals(o.amount) && accountName.equals(o.accountName) && - accountComment.equals(o.accountComment) && negateAmount == o.negateAmount; + position == o.position && accountComment.equals(o.accountComment) && + negateAmount == o.negateAmount; } public void switchToLiteralAmount() { amount.switchToLiteral(); @@ -393,9 +426,9 @@ abstract public class TemplateDetailsItem { public static class Header extends TemplateDetailsItem { private String pattern = ""; private String testText = ""; + private String name = ""; private Pattern compiledPattern; private String patternError; - private String name = ""; private PossiblyMatchedValue transactionDescription = PossiblyMatchedValue.withLiteralString(""); private PossiblyMatchedValue transactionComment = @@ -403,6 +436,7 @@ abstract public class TemplateDetailsItem { private PossiblyMatchedValue dateYear = PossiblyMatchedValue.withLiteralInt(null); private PossiblyMatchedValue dateMonth = PossiblyMatchedValue.withLiteralInt(null); private PossiblyMatchedValue dateDay = PossiblyMatchedValue.withLiteralInt(null); + private SpannableString testMatch; private Header() { super(Type.HEADER); } @@ -411,6 +445,7 @@ abstract public class TemplateDetailsItem { id = origin.id; name = origin.name; testText = origin.testText; + testMatch = origin.testMatch; setPattern(origin.pattern); transactionDescription = new PossiblyMatchedValue<>(origin.transactionDescription); @@ -420,6 +455,11 @@ abstract public class TemplateDetailsItem { dateMonth = new PossiblyMatchedValue<>(origin.dateMonth); dateDay = new PossiblyMatchedValue<>(origin.dateDay); } + private static StyleSpan capturedSpan() { return new StyleSpan(Typeface.BOLD); } + private static UnderlineSpan matchedSpan() { return new UnderlineSpan(); } + private static ForegroundColorSpan notMatchedSpan() { + return new ForegroundColorSpan(Color.GRAY); + } public String getName() { return name; } @@ -431,18 +471,17 @@ abstract public class TemplateDetailsItem { } public void setPattern(String pattern) { this.pattern = pattern; - if (pattern != null) { - try { - this.compiledPattern = Pattern.compile(pattern); - this.patternError = null; - } - catch (PatternSyntaxException e) { - this.compiledPattern = null; - this.patternError = e.getMessage(); - } + try { + this.compiledPattern = Pattern.compile(pattern); + checkPatternMatch(); } - else { - patternError = "Missing pattern"; + catch (PatternSyntaxException ex) { + patternError = ex.getDescription(); + compiledPattern = null; + + testMatch = new SpannableString(testText); + testMatch.setSpan(notMatchedSpan(), 0, testText.length() - 1, + Spanned.SPAN_INCLUSIVE_INCLUSIVE); } } @NonNull @@ -457,6 +496,8 @@ abstract public class TemplateDetailsItem { } public void setTestText(String testText) { this.testText = testText; + + checkPatternMatch(); } public String getTransactionDescription() { return transactionDescription.getValue(); @@ -551,7 +592,9 @@ abstract public class TemplateDetailsItem { return true; return Misc.equalStrings(name, o.name) && Misc.equalStrings(pattern, o.pattern) && - Misc.equalStrings(testText, o.testText); + Misc.equalStrings(testText, o.testText) && + Misc.equalStrings(patternError, o.patternError) && + Objects.equals(testMatch, o.testMatch); } public String getMatchGroupText(int group) { if (compiledPattern != null && testText != null) { @@ -623,5 +666,59 @@ abstract public class TemplateDetailsItem { return result; } + public SpannableString getTestMatch() { + return testMatch; + } + public void checkPatternMatch() { + patternError = null; + testMatch = null; + + if (pattern != null) { + try { + if (Misc.emptyIsNull(testText) != null) { + SpannableString ss = new SpannableString(testText); + Matcher m = compiledPattern.matcher(testText); + if (m.find()) { + if (m.start() > 0) + ss.setSpan(notMatchedSpan(), 0, m.start(), + Spanned.SPAN_INCLUSIVE_INCLUSIVE); + if (m.end() < testText.length() - 1) + ss.setSpan(notMatchedSpan(), m.end(), testText.length(), + Spanned.SPAN_INCLUSIVE_INCLUSIVE); + + ss.setSpan(matchedSpan(), m.start(0), m.end(0), + Spanned.SPAN_INCLUSIVE_INCLUSIVE); + + if (m.groupCount() > 0) { + for (int g = 1; g <= m.groupCount(); g++) { + ss.setSpan(capturedSpan(), m.start(g), m.end(g), + Spanned.SPAN_INCLUSIVE_INCLUSIVE); + } + } + } + else { + patternError = "Pattern does not match"; + ss.setSpan(new ForegroundColorSpan(Color.GRAY), 0, + testText.length() - 1, Spanned.SPAN_INCLUSIVE_INCLUSIVE); + } + + testMatch = ss; + } + } + catch (PatternSyntaxException e) { + this.compiledPattern = null; + this.patternError = e.getMessage(); + } + } + else { + patternError = "Missing pattern"; + } + } + public String getPatternError() { + return patternError; + } + public SpannableString testMatch() { + return testMatch; + } } }