Browse Source

Implement OR logic in EDQS checkKeyFilters with DRY helper extraction

- Extract evaluateSingleFilter helper to avoid duplicating filter evaluation logic
- Add 3-arg checkKeyFilters overload accepting ComplexOperation parameter
- OR mode: any matching filter includes entity (short-circuit on first true)
- AND mode: all filters must match (short-circuit on first false, unchanged behavior)
- Null operation defaults to AND for backward compatibility
- Update checkFilters to pass query.getKeyFiltersOperation() through to checkKeyFilters
pull/15394/head
Viacheslav Klimov 6 months ago
parent
commit
caac757f18
Failed to extract signature
  1. 76
      common/edqs/src/main/java/org/thingsboard/server/edqs/util/RepositoryUtils.java

76
common/edqs/src/main/java/org/thingsboard/server/edqs/util/RepositoryUtils.java

@ -22,6 +22,7 @@ import org.thingsboard.server.common.data.edqs.DataPoint;
import org.thingsboard.server.common.data.permission.QueryContext; import org.thingsboard.server.common.data.permission.QueryContext;
import org.thingsboard.server.common.data.query.BooleanFilterPredicate; import org.thingsboard.server.common.data.query.BooleanFilterPredicate;
import org.thingsboard.server.common.data.query.ComplexFilterPredicate; import org.thingsboard.server.common.data.query.ComplexFilterPredicate;
import org.thingsboard.server.common.data.query.ComplexOperation;
import org.thingsboard.server.common.data.query.EntityCountQuery; import org.thingsboard.server.common.data.query.EntityCountQuery;
import org.thingsboard.server.common.data.query.EntityDataQuery; import org.thingsboard.server.common.data.query.EntityDataQuery;
import org.thingsboard.server.common.data.query.EntityDataSortOrder; import org.thingsboard.server.common.data.query.EntityDataSortOrder;
@ -198,38 +199,55 @@ public class RepositoryUtils {
} }
public static boolean checkKeyFilters(EntityData entity, List<EdqsFilter> keyFilters) { public static boolean checkKeyFilters(EntityData entity, List<EdqsFilter> keyFilters) {
for (EdqsFilter keyFilter : keyFilters) { return checkKeyFilters(entity, keyFilters, ComplexOperation.AND);
EntityKeyValueType valueType = keyFilter.valueType(); }
if (valueType == null) {
valueType = switch (keyFilter.predicate().getType()) { public static boolean checkKeyFilters(EntityData entity, List<EdqsFilter> keyFilters, ComplexOperation operation) {
case STRING -> EntityKeyValueType.STRING; ComplexOperation op = operation != null ? operation : ComplexOperation.AND;
case NUMERIC -> EntityKeyValueType.NUMERIC; if (op == ComplexOperation.OR) {
case BOOLEAN -> EntityKeyValueType.BOOLEAN; for (EdqsFilter keyFilter : keyFilters) {
default -> throw new IllegalStateException(); if (evaluateSingleFilter(entity, keyFilter)) {
}; return true;
}
DataKey dataKey = keyFilter.key();
DataPoint dp = entity.getDataPoint(dataKey, null);
boolean checkResult = switch (valueType) {
case STRING -> {
String str = dp != null ? dp.valueToString() : null;
yield (dataKey.type() == EntityKeyType.ENTITY_FIELD) ? (str == null || checkKeyFilter(str, keyFilter.predicate())) :
(str != null && checkKeyFilter(str, keyFilter.predicate()));
}
case BOOLEAN -> {
Boolean booleanValue = dp != null ? dp.getBool() : null;
yield booleanValue != null && checkKeyFilter(booleanValue, keyFilter.predicate());
} }
case DATE_TIME, NUMERIC -> { }
Double doubleValue = dp != null ? dp.getDouble() : null; return keyFilters.isEmpty();
yield doubleValue != null && checkKeyFilter(doubleValue, keyFilter.predicate()); } else {
for (EdqsFilter keyFilter : keyFilters) {
if (!evaluateSingleFilter(entity, keyFilter)) {
return false;
} }
};
if (!checkResult) {
return false;
} }
return true;
} }
return true; }
private static boolean evaluateSingleFilter(EntityData entity, EdqsFilter keyFilter) {
EntityKeyValueType valueType = keyFilter.valueType();
if (valueType == null) {
valueType = switch (keyFilter.predicate().getType()) {
case STRING -> EntityKeyValueType.STRING;
case NUMERIC -> EntityKeyValueType.NUMERIC;
case BOOLEAN -> EntityKeyValueType.BOOLEAN;
default -> throw new IllegalStateException();
};
}
DataKey dataKey = keyFilter.key();
DataPoint dp = entity.getDataPoint(dataKey, null);
return switch (valueType) {
case STRING -> {
String str = dp != null ? dp.valueToString() : null;
yield (dataKey.type() == EntityKeyType.ENTITY_FIELD) ? (str == null || checkKeyFilter(str, keyFilter.predicate())) :
(str != null && checkKeyFilter(str, keyFilter.predicate()));
}
case BOOLEAN -> {
Boolean booleanValue = dp != null ? dp.getBool() : null;
yield booleanValue != null && checkKeyFilter(booleanValue, keyFilter.predicate());
}
case DATE_TIME, NUMERIC -> {
Double doubleValue = dp != null ? dp.getDouble() : null;
yield doubleValue != null && checkKeyFilter(doubleValue, keyFilter.predicate());
}
};
} }
public static boolean checkKeyFilter(String value, KeyFilterPredicate keyFilterPredicate) { public static boolean checkKeyFilter(String value, KeyFilterPredicate keyFilterPredicate) {
@ -378,7 +396,7 @@ public class RepositoryUtils {
if (entity == null || entity.getFields() == null) { if (entity == null || entity.getFields() == null) {
return false; // Entity was already removed or not arrived yet; return false; // Entity was already removed or not arrived yet;
} }
if (query.isHasKeyFilters() && !checkKeyFilters(entity, query.getKeyFilters())) { if (query.isHasKeyFilters() && !checkKeyFilters(entity, query.getKeyFilters(), query.getKeyFiltersOperation())) {
return false; return false;
} }
if (query instanceof EdqsDataQuery dataQuery) { if (query instanceof EdqsDataQuery dataQuery) {

Loading…
Cancel
Save