Skip to content

Commit

Permalink
Improve parsing and application of query slightly
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
Bios-Marcel committed Jul 14, 2024
1 parent 9d79cba commit 3c1bde3
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 29 deletions.
4 changes: 2 additions & 2 deletions src/main/antlr4/link/biosmarcel/baka/FilterLexer.g4
Original file line number Diff line number Diff line change
Expand Up @@ -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);
7 changes: 5 additions & 2 deletions src/main/java/link/biosmarcel/baka/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -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) -> {
Expand All @@ -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),
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/link/biosmarcel/baka/filter/FieldData.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

import java.util.function.Function;

public class FieldData<FilterTarget> {
final FilterTargetPredicate<FilterTarget> operate;
final Function<String, Object> convertString;
public class FieldData<FilterTarget, ValueType> {
final FilterTargetPredicate<FilterTarget, ValueType> operate;
final Function<String, ValueType> convertString;

public FieldData(final FilterTargetPredicate<FilterTarget> operate, final Function<String, Object> convertString) {
public FieldData(final FilterTargetPredicate<FilterTarget, ValueType> operate, final Function<String, ValueType> convertString) {
this.operate = operate;
this.convertString = convertString;
}
Expand Down
27 changes: 17 additions & 10 deletions src/main/java/link/biosmarcel/baka/filter/Filter.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@
public class Filter<FilterTarget> implements Predicate<FilterTarget> {
private @Nullable Expression<FilterTarget> query;

final Map<String, Map<Operator, FieldData<FilterTarget>>> fieldToOperatorToExtractor = new HashMap<>();
final Map<String, Map<Operator, FieldData<FilterTarget, ?>>> fieldToOperatorToExtractor = new HashMap<>();

public void register(
public <ValueType> void register(
final String field,
final Operator operator,
final FilterTargetPredicate<FilterTarget> predicate,
final Function<String, Object> convertString) {
final FilterTargetPredicate<FilterTarget, ValueType> predicate,
final Function<String, ValueType> convertString) {
fieldToOperatorToExtractor
.computeIfAbsent(field, _ -> new HashMap<>(/* FIXME Fixed Operator Size*/))
.put(operator, new FieldData<>(predicate, convertString));
Expand Down Expand Up @@ -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<FilterTarget, Object> extractor = (FieldData<FilterTarget, Object>) 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<FilterTarget> predicate = x -> extractor.operate.test(x, filterValue);

final var converted = extractor.convertString.apply(unquoted);
final Predicate<FilterTarget> predicate = x -> extractor.operate.test(x, converted);
insertPredicate(targetContext, predicate);
}
}, parsedQuery);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package link.biosmarcel.baka.filter;

@FunctionalInterface
public interface FilterTargetPredicate<FilterTarget> {
boolean test(FilterTarget target, Object value);
public interface FilterTargetPredicate<FilterTarget, ValueType> {
boolean test(FilterTarget target, ValueType value);
}
2 changes: 2 additions & 0 deletions src/main/java/link/biosmarcel/baka/filter/Operator.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ public enum Operator {
EQ,
NOT_EQ,
HAS,
LT,
GT,
}
20 changes: 11 additions & 9 deletions src/main/java/link/biosmarcel/baka/view/PaymentFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@

public class PaymentFilter extends Filter<Payment> {
{
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) -> )
}
}

0 comments on commit 3c1bde3

Please sign in to comment.