From 3c1bde31f4a75aab06fcc083f1f981c7b198b965 Mon Sep 17 00:00:00 2001 From: Marcel Schramm Date: Fri, 12 Jul 2024 18:52:40 +0200 Subject: [PATCH] Improve parsing and application of query slightly * identifiers can no longer contain quotes * a string can now be empty * the query now returns exceptions if elements are still missing, later on we can use this to communicate with the user --- .../link/biosmarcel/baka/FilterLexer.g4 | 4 +-- src/main/java/link/biosmarcel/baka/Main.java | 7 +++-- .../biosmarcel/baka/filter/FieldData.java | 8 +++--- .../link/biosmarcel/baka/filter/Filter.java | 27 ++++++++++++------- .../baka/filter/FilterTargetPredicate.java | 4 +-- .../link/biosmarcel/baka/filter/Operator.java | 2 ++ .../biosmarcel/baka/view/PaymentFilter.java | 20 +++++++------- 7 files changed, 43 insertions(+), 29 deletions(-) diff --git a/src/main/antlr4/link/biosmarcel/baka/FilterLexer.g4 b/src/main/antlr4/link/biosmarcel/baka/FilterLexer.g4 index d0b27fd..e1ec6cd 100644 --- a/src/main/antlr4/link/biosmarcel/baka/FilterLexer.g4 +++ b/src/main/antlr4/link/biosmarcel/baka/FilterLexer.g4 @@ -15,8 +15,8 @@ GT: '>'; GT_EQ: '>='; EQ: '='; NOT_EQ: '!='; -STRING: ["].+?["]; +STRING: ["].*?["]; BOOLEAN: ('true'|'false'); NUMBER: [,.0-9]+; -WORD: ~[ \u000B\t\r\n]+; +WORD: ~[ \u000B\t\r\n"]+; SPACES: [ \u000B\t\r\n] -> channel(HIDDEN); \ No newline at end of file diff --git a/src/main/java/link/biosmarcel/baka/Main.java b/src/main/java/link/biosmarcel/baka/Main.java index 1013071..8166dc8 100644 --- a/src/main/java/link/biosmarcel/baka/Main.java +++ b/src/main/java/link/biosmarcel/baka/Main.java @@ -27,8 +27,8 @@ public void start(Stage stage) { final Data data = new Data(); final var storageManager = EmbeddedStorageConfiguration .Builder() - .setStorageDirectory(getDataDir("storage").toString()) - .setBackupDirectory(getDataDir("backup").toString()) + .setStorageDirectory(getDataDir("storage_temp").toString()) + .setBackupDirectory(getDataDir("backup_temp").toString()) .setChannelCount(1) .createEmbeddedStorageFoundation() //.onConnectionFoundation((connection) -> { @@ -44,6 +44,9 @@ public void start(Stage stage) { ApplicationState state = new ApplicationState(storageManager, storageManager.createEagerStorer(), data); +// data.payments.clear(); +// storageManager.store(data); + TabPane tabs = new TabPane( new PaymentsView(state), new AccountsView(state), diff --git a/src/main/java/link/biosmarcel/baka/filter/FieldData.java b/src/main/java/link/biosmarcel/baka/filter/FieldData.java index 4d2d0e7..3178249 100644 --- a/src/main/java/link/biosmarcel/baka/filter/FieldData.java +++ b/src/main/java/link/biosmarcel/baka/filter/FieldData.java @@ -2,11 +2,11 @@ import java.util.function.Function; -public class FieldData { - final FilterTargetPredicate operate; - final Function convertString; +public class FieldData { + final FilterTargetPredicate operate; + final Function convertString; - public FieldData(final FilterTargetPredicate operate, final Function convertString) { + public FieldData(final FilterTargetPredicate operate, final Function convertString) { this.operate = operate; this.convertString = convertString; } diff --git a/src/main/java/link/biosmarcel/baka/filter/Filter.java b/src/main/java/link/biosmarcel/baka/filter/Filter.java index 1d83d5a..6792dee 100644 --- a/src/main/java/link/biosmarcel/baka/filter/Filter.java +++ b/src/main/java/link/biosmarcel/baka/filter/Filter.java @@ -18,13 +18,13 @@ public class Filter implements Predicate { private @Nullable Expression query; - final Map>> fieldToOperatorToExtractor = new HashMap<>(); + final Map>> fieldToOperatorToExtractor = new HashMap<>(); - public void register( + public void register( final String field, final Operator operator, - final FilterTargetPredicate predicate, - final Function convertString) { + final FilterTargetPredicate predicate, + final Function convertString) { fieldToOperatorToExtractor .computeIfAbsent(field, _ -> new HashMap<>(/* FIXME Fixed Operator Size*/)) .put(operator, new FieldData<>(predicate, convertString)); @@ -120,27 +120,34 @@ public void enterComparatorExpression(final FilterParser.ComparatorExpressionCon throw new IllegalStateException("Field not registered: " + ctx.field().getText()); } + if (ctx.children.size() <= 1) { + throw new IllegalStateException("missing operator"); + } + final Operator operator = switch (ctx.operator.getText()) { case "=" -> Operator.EQ; case "!=" -> Operator.NOT_EQ; case "contains", "has" -> Operator.HAS; default -> throw new UnsupportedOperationException("Unknown operator: " + ctx.operator.getText()); }; - final var extractor = operatorToExtractor.get(operator); + final FieldData extractor = (FieldData) operatorToExtractor.get(operator); if (extractor == null) { throw new IllegalStateException("Extractor not registered: " + ctx.field().getText() + "." + ctx.operator.getText()); } - String unquoted; final var value = ctx.value(); + String unquoted = value.getText(); + if (unquoted.isBlank()) { + throw new IllegalStateException("missing value"); + } + final var stringToken = value.STRING(); if (stringToken != null) { unquoted = stringToken.getText().substring(1, stringToken.getText().length() - 1); - } else { - unquoted = value.getText(); } - final Object filterValue = extractor.convertString.apply(unquoted); - final Predicate predicate = x -> extractor.operate.test(x, filterValue); + + final var converted = extractor.convertString.apply(unquoted); + final Predicate predicate = x -> extractor.operate.test(x, converted); insertPredicate(targetContext, predicate); } }, parsedQuery); diff --git a/src/main/java/link/biosmarcel/baka/filter/FilterTargetPredicate.java b/src/main/java/link/biosmarcel/baka/filter/FilterTargetPredicate.java index 8e1caa7..7414f48 100644 --- a/src/main/java/link/biosmarcel/baka/filter/FilterTargetPredicate.java +++ b/src/main/java/link/biosmarcel/baka/filter/FilterTargetPredicate.java @@ -1,6 +1,6 @@ package link.biosmarcel.baka.filter; @FunctionalInterface -public interface FilterTargetPredicate { - boolean test(FilterTarget target, Object value); +public interface FilterTargetPredicate { + boolean test(FilterTarget target, ValueType value); } diff --git a/src/main/java/link/biosmarcel/baka/filter/Operator.java b/src/main/java/link/biosmarcel/baka/filter/Operator.java index a24128f..c474927 100644 --- a/src/main/java/link/biosmarcel/baka/filter/Operator.java +++ b/src/main/java/link/biosmarcel/baka/filter/Operator.java @@ -4,4 +4,6 @@ public enum Operator { EQ, NOT_EQ, HAS, + LT, + GT, } diff --git a/src/main/java/link/biosmarcel/baka/view/PaymentFilter.java b/src/main/java/link/biosmarcel/baka/view/PaymentFilter.java index ba3f166..2bcb2cf 100644 --- a/src/main/java/link/biosmarcel/baka/view/PaymentFilter.java +++ b/src/main/java/link/biosmarcel/baka/view/PaymentFilter.java @@ -6,16 +6,18 @@ public class PaymentFilter extends Filter { { - register("name", Operator.EQ, (payment, value) -> payment.name.equalsIgnoreCase((String) value), String::toLowerCase); - register("name", Operator.NOT_EQ, (payment, value) -> !payment.name.equalsIgnoreCase((String) value), String::toLowerCase); - register("name", Operator.HAS, (payment, value) -> payment.name.toLowerCase().contains((String) value), String::toLowerCase); + register("name", Operator.EQ, (payment, value) -> payment.name.equalsIgnoreCase(value), String::toLowerCase); + register("name", Operator.NOT_EQ, (payment, value) -> !payment.name.equalsIgnoreCase(value), String::toLowerCase); + register("name", Operator.HAS, (payment, value) -> payment.name.toLowerCase().contains(value), String::toLowerCase); - register("reference", Operator.EQ, (payment, value) -> payment.reference.equalsIgnoreCase((String) value), String::toLowerCase); - register("reference", Operator.NOT_EQ, (payment, value) -> !payment.reference.equalsIgnoreCase((String) value), String::toLowerCase); - register("reference", Operator.HAS, (payment, value) -> payment.reference.toLowerCase().contains((String) value), String::toLowerCase); + register("reference", Operator.EQ, (payment, value) -> payment.reference.equalsIgnoreCase(value), String::toLowerCase); + register("reference", Operator.NOT_EQ, (payment, value) -> !payment.reference.equalsIgnoreCase(value), String::toLowerCase); + register("reference", Operator.HAS, (payment, value) -> payment.reference.toLowerCase().contains(value), String::toLowerCase); - register("participant", Operator.EQ, (payment, value) -> payment.participant != null && payment.participant.equalsIgnoreCase((String) value), String::toLowerCase); - register("participant", Operator.NOT_EQ, (payment, value) -> payment.participant == null || payment.participant.equalsIgnoreCase((String) value), String::toLowerCase); - register("participant", Operator.HAS, (payment, value) -> payment.participant != null && payment.participant.toLowerCase().contains((String) value), String::toLowerCase); + register("participant", Operator.EQ, (payment, value) -> payment.participant != null && payment.participant.equalsIgnoreCase(value), String::toLowerCase); + register("participant", Operator.NOT_EQ, (payment, value) -> payment.participant == null || payment.participant.equalsIgnoreCase(value), String::toLowerCase); + register("participant", Operator.HAS, (payment, value) -> payment.participant != null && payment.participant.toLowerCase().contains(value), String::toLowerCase); + +// register("effective_date", Operator.LT, (payment, value) -> ) } }