mirror of
https://github.com/valitydev/geck.git
synced 2024-11-06 01:35:22 +00:00
BJ-197: Add collection support in filter (#51)
* BJ-197: Add collection support * BJ-197: Review performance fix * BJ-197: Bump version to 0.5.0-SNAPSHOT * BJ-197: Rewrite split function * BJ-197: Rewrite test expected values
This commit is contained in:
parent
ab86104b0a
commit
db78998480
@ -1,6 +1,7 @@
|
||||
package com.rbkmoney.geck.common.util;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* Created by vpankrashkin on 03.02.17.
|
||||
@ -85,6 +86,18 @@ public final class StringUtil {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static String[] split(String value, String delimiter) {
|
||||
StringTokenizer tokenizer = new StringTokenizer(value, delimiter);
|
||||
String[] items = new String[tokenizer.countTokens()];
|
||||
|
||||
int itemId = 0;
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
items[itemId++] = tokenizer.nextToken();
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
|
||||
public static String intToString(int number, int groupSize, int maxBits) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
@ -9,6 +9,8 @@ public interface Parser {
|
||||
|
||||
String getItemPath(int item);
|
||||
|
||||
Parser getSubParser(int from);
|
||||
|
||||
int size();
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,9 @@ import com.rbkmoney.geck.common.util.TypeUtil;
|
||||
import com.rbkmoney.geck.filter.rule.PathConditionRule;
|
||||
import org.apache.thrift.TBase;
|
||||
import org.apache.thrift.TFieldIdEnum;
|
||||
import org.apache.thrift.TUnion;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Created by tolkonepiu on 17/03/2017.
|
||||
@ -17,35 +20,45 @@ public class PathConditionFilter implements Filter<TBase> {
|
||||
this.rules = rules;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean match(TBase object) {
|
||||
public boolean match(TBase value) {
|
||||
for (PathConditionRule rule : rules) {
|
||||
Object value = object;
|
||||
Parser parser = rule.getParser();
|
||||
|
||||
for (int item = 0; item < parser.size(); item++) {
|
||||
if (value == null || !(value instanceof TBase)) {
|
||||
return false;
|
||||
}
|
||||
value = getFieldValue(parser.getItem(item), TypeUtil.convertType(TBase.class, value));
|
||||
}
|
||||
|
||||
for (Condition condition : rule.getConditions()) {
|
||||
if(!condition.accept(value)) {
|
||||
return false;
|
||||
}
|
||||
if (!match(value, parser, rule.getConditions())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private Object getFieldValue(String path, TBase tBase) {
|
||||
TFieldIdEnum tFieldIdEnum = TBaseUtil.getField(path, tBase);
|
||||
if (tFieldIdEnum != null && tBase.isSet(tFieldIdEnum)) {
|
||||
return tBase.getFieldValue(tFieldIdEnum);
|
||||
public boolean match(Object value, Parser parser, Condition... conditions) {
|
||||
for (int item = 0; item < parser.size(); item++) {
|
||||
if (value instanceof TBase) {
|
||||
TBase tBase = TypeUtil.convertType(TBase.class, value);
|
||||
TFieldIdEnum tFieldIdEnum = TBaseUtil.getField(parser.getItem(item), tBase);
|
||||
if (tFieldIdEnum == null
|
||||
|| ((tBase instanceof TUnion) && !tBase.isSet(tFieldIdEnum))) {
|
||||
return false;
|
||||
}
|
||||
value = tBase.getFieldValue(tFieldIdEnum);
|
||||
} else if (value instanceof Collection) {
|
||||
Collection collection = TypeUtil.convertType(Collection.class, value);
|
||||
for (Object collectionItem : collection) {
|
||||
if (match(collectionItem, parser.getSubParser(item), conditions)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
for (Condition condition : conditions) {
|
||||
if (!condition.accept(value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,62 +1,51 @@
|
||||
package com.rbkmoney.geck.filter.parser;
|
||||
|
||||
import com.rbkmoney.geck.common.util.StringUtil;
|
||||
import com.rbkmoney.geck.filter.Parser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Created by tolkonepiu on 16/03/2017.
|
||||
*/
|
||||
public class PathParser implements Parser {
|
||||
|
||||
private String fieldPath;
|
||||
private List<String> items;
|
||||
private List<String> forNameItems;
|
||||
private final String[] items;
|
||||
private final String delimiter;
|
||||
|
||||
public static final String DEFAULT_DELIMITER = ".";
|
||||
private String delimiter;
|
||||
|
||||
public PathParser(String fieldPath) {
|
||||
this(fieldPath, DEFAULT_DELIMITER);
|
||||
}
|
||||
|
||||
public PathParser(String fieldPath, String delimiter) {
|
||||
this.fieldPath = fieldPath;
|
||||
this.delimiter = delimiter;
|
||||
init();
|
||||
this(StringUtil.split(fieldPath, delimiter), delimiter);
|
||||
}
|
||||
|
||||
private void init() {
|
||||
List<String> items = new ArrayList<>();
|
||||
List<String> forNameItems = new ArrayList<>();
|
||||
int last = 0;
|
||||
int next;
|
||||
while ((next = fieldPath.indexOf(delimiter, last)) != -1) {
|
||||
items.add(fieldPath.substring(last, next));
|
||||
forNameItems.add(fieldPath.substring(0, next));
|
||||
last = next + delimiter.length();
|
||||
}
|
||||
forNameItems.add(fieldPath.substring(0, fieldPath.length()));
|
||||
items.add(fieldPath.substring(last, fieldPath.length()));
|
||||
|
||||
public PathParser(String[] items, String delimiter) {
|
||||
this.items = items;
|
||||
this.forNameItems = forNameItems;
|
||||
this.delimiter = delimiter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getItem(int item) {
|
||||
return items.get(item);
|
||||
return items[item];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getItemPath(int item) {
|
||||
return forNameItems.get(item);
|
||||
return String.join(delimiter, Arrays.copyOfRange(items, 0, item + 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Parser getSubParser(int from) {
|
||||
return new PathParser(Arrays.copyOfRange(items, from, items.length), delimiter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return items.size();
|
||||
return items.length;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,8 +5,6 @@ import com.rbkmoney.geck.filter.Parser;
|
||||
import com.rbkmoney.geck.filter.Rule;
|
||||
import com.rbkmoney.geck.filter.parser.PathParser;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Created by tolkonepiu on 16/03/2017.
|
||||
*/
|
||||
|
@ -12,6 +12,7 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Created by tolkonepiu on 17/03/2017.
|
||||
@ -35,6 +36,40 @@ public class PathConditionFilterTest {
|
||||
testObject.setStatus(Status.ok_status(new Ok()));
|
||||
testObject.setType(Type.BLACK);
|
||||
testObject.setNumbers(Arrays.asList(new Long[]{23L, 31L, 41L}));
|
||||
|
||||
List<Ids> listIds = new ArrayList<>();
|
||||
listIds.add(ids);
|
||||
ids = new Ids();
|
||||
ids.setMicroId((byte) 32);
|
||||
ids.setMiniId((short) 33);
|
||||
ids.setId(34);
|
||||
listIds.add(ids);
|
||||
testObject.setListIds(listIds);
|
||||
|
||||
List<Status> statuses1 = new ArrayList<>();
|
||||
statuses1.add(Status.ok_status(new Ok()));
|
||||
|
||||
Unknown unknownField = new Unknown();
|
||||
List<Type> resultTypes = new ArrayList<>();
|
||||
resultTypes.add(Type.BLACK);
|
||||
resultTypes.add(Type.GREEN);
|
||||
unknownField.setUnknown(UnknownType.resultTypes(resultTypes));
|
||||
statuses1.add(Status.unknown_status(unknownField));
|
||||
List<List<Status>> kebabStatus = new ArrayList<>();
|
||||
kebabStatus.add(statuses1);
|
||||
|
||||
Unknown unknownField2 = new Unknown();
|
||||
List<Type> resultTypes2 = new ArrayList<>();
|
||||
resultTypes2.add(Type.BLACK);
|
||||
resultTypes2.add(Type.GREEN);
|
||||
unknownField2.setUnknown(UnknownType.resultTypes(resultTypes));
|
||||
statuses1.add(Status.unknown_status(unknownField));
|
||||
|
||||
List<Status> statuses2 = new ArrayList<>();
|
||||
statuses1.add(Status.ok_status(new Ok()));
|
||||
kebabStatus.add(statuses2);
|
||||
testObject.setStatuses(kebabStatus);
|
||||
|
||||
testObjectList.add(testObject);
|
||||
|
||||
testObject = new TestObject();
|
||||
@ -111,4 +146,20 @@ public class PathConditionFilterTest {
|
||||
assertEquals(filter.match(testObjectList.get(0)), false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterInCollectionTest() {
|
||||
PathConditionRule rule = new PathConditionRule("list_ids.micro_id", new EqualsCondition((byte) 32));
|
||||
Filter filter = new PathConditionFilter(rule);
|
||||
assertTrue(filter.match(testObjectList.get(0)));
|
||||
|
||||
List<Type> resultTypes = new ArrayList<>();
|
||||
resultTypes.add(Type.BLACK);
|
||||
resultTypes.add(Type.GREEN);
|
||||
rule = new PathConditionRule("statuses.unknown_status.unknown.resultTypes", new EqualsCondition(resultTypes));
|
||||
filter = new PathConditionFilter(rule);
|
||||
assertTrue(filter.match(testObjectList.get(0)));
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -14,18 +14,27 @@ public class PathParserTest {
|
||||
public void parserInitTest() {
|
||||
Parser parser = new PathParser("kek.tsss.qwe");
|
||||
|
||||
assertEquals(parser.getItem(0), "kek");
|
||||
assertEquals(parser.getItemPath(0), "kek");
|
||||
assertEquals(parser.getItem(1), "tsss");
|
||||
assertEquals(parser.getItemPath(1), "kek.tsss");
|
||||
assertEquals(parser.getItem(2), "qwe");
|
||||
assertEquals(parser.getItemPath(2), "kek.tsss.qwe");
|
||||
assertEquals(parser.size(), 3);
|
||||
assertEquals("kek", parser.getItem(0));
|
||||
assertEquals("kek", parser.getItemPath(0));
|
||||
assertEquals("tsss", parser.getItem(1));
|
||||
assertEquals("kek.tsss", parser.getItemPath(1));
|
||||
assertEquals("qwe", parser.getItem(2));
|
||||
assertEquals("kek.tsss.qwe", parser.getItemPath(2));
|
||||
assertEquals(3, parser.size());
|
||||
|
||||
parser = new PathParser("kek..kek...");
|
||||
assertEquals(parser.getItem(1), "");
|
||||
assertEquals(parser.getItemPath(1), "kek.");
|
||||
assertEquals(parser.size(), 6);
|
||||
assertEquals("kek", parser.getItem(1));
|
||||
assertEquals("kek.kek", parser.getItemPath(1));
|
||||
assertEquals(2, parser.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subParserTest() {
|
||||
Parser parser = new PathParser("1.2.3.4.5");
|
||||
assertEquals(5, parser.size());
|
||||
parser = parser.getSubParser(2);
|
||||
assertEquals(3, parser.size());
|
||||
assertEquals("3.4.5", parser.getItemPath(parser.size() - 1));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ struct TestObject {
|
||||
4: required Type type
|
||||
5: optional slist words
|
||||
6: optional list<i64> numbers
|
||||
7: optional list<Ids> list_ids
|
||||
8: optional list<list<Status>> statuses
|
||||
}
|
||||
|
||||
struct Ids {
|
||||
|
Loading…
Reference in New Issue
Block a user