From 5b70d04d60b3d1045a257134e21b6a640ec1053a Mon Sep 17 00:00:00 2001
From: mr-impossibru <64555470+mr-impossibru@users.noreply.github.com>
Date: Wed, 10 Nov 2021 12:20:09 +0300
Subject: [PATCH] ft/JD-741: add isTrusted() with conditions templates (#41)
* JD-741: add isTrusted() with conditions lists
* JD-741: fix typo DELIMETER -> DELIMITER
* JD-741: remove unused dependencies, bump junit4
---
build_utils | 2 +-
pom.xml | 40 +-------
.../antlr4/com.rbkmoney.fraudo/FraudoP2P.g4 | 4 +-
.../com.rbkmoney.fraudo/FraudoPayment.g4 | 36 ++++++-
src/main/antlr4/imports/Fraudo.g4 | 20 ++--
.../converter/TrustConditionConverter.java | 42 ++++++++
.../rbkmoney/fraudo/model/TrustCondition.java | 15 +++
.../factory/FraudVisitorFactoryImpl.java | 25 ++++-
.../factory/FullVisitorFactoryImpl.java | 17 +++-
.../resolver/CustomerTypeResolver.java | 6 ++
.../payment/visitor/CustomFuncVisitor.java | 2 -
.../payment/visitor/IsTrustedFuncVisitor.java | 13 +++
.../visitor/impl/CustomFuncVisitorImpl.java | 6 --
.../visitor/impl/FirstFindVisitorImpl.java | 34 ++++++-
.../payment/visitor/impl/FullVisitorImpl.java | 15 ++-
.../impl/IsTrustedFuncVisitorImpl.java | 26 +++++
.../com/rbkmoney/fraudo/utils/TextUtil.java | 6 ++
.../java/com/rbkmoney/fraudo/CustomTest.java | 11 ---
.../com/rbkmoney/fraudo/IsTrustedTest.java | 98 +++++++++++++++++++
.../com/rbkmoney/fraudo/RealTimerTest.java | 5 +-
...th_payments_and_withdrawals_conditions.frd | 10 ++
...ents_and_withdrawals_single_conditions.frd | 8 ++
.../is_trusted_with_payments_conditions.frd | 6 ++
...is_trusted_with_withdrawals_conditions.frd | 6 ++
24 files changed, 368 insertions(+), 85 deletions(-)
create mode 100644 src/main/java/com/rbkmoney/fraudo/converter/TrustConditionConverter.java
create mode 100644 src/main/java/com/rbkmoney/fraudo/model/TrustCondition.java
create mode 100644 src/main/java/com/rbkmoney/fraudo/payment/visitor/IsTrustedFuncVisitor.java
create mode 100644 src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/IsTrustedFuncVisitorImpl.java
create mode 100644 src/test/java/com/rbkmoney/fraudo/IsTrustedTest.java
create mode 100644 src/test/resources/rules/is_trusted_with_payments_and_withdrawals_conditions.frd
create mode 100644 src/test/resources/rules/is_trusted_with_payments_and_withdrawals_single_conditions.frd
create mode 100644 src/test/resources/rules/is_trusted_with_payments_conditions.frd
create mode 100644 src/test/resources/rules/is_trusted_with_withdrawals_conditions.frd
diff --git a/build_utils b/build_utils
index 5401838..be44d69 160000
--- a/build_utils
+++ b/build_utils
@@ -1 +1 @@
-Subproject commit 540183862bc9fd04682e226de2056a320fd44be9
+Subproject commit be44d69fc87b22a0bb82d98d6eae7658d1647f98
diff --git a/pom.xml b/pom.xml
index 91fc104..4f55f64 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,7 +11,7 @@
fraudo
- 0.0.22
+ 0.0.23
Fraudo
Language for describing antifraud patterns
@@ -33,15 +33,14 @@
- 2.0.0.0
- ${project.basedir}/../target/jacoco.exec
+ 4.7.1
org.antlr
antlr4-runtime
- 4.7.1
+ ${antlr4.version}
org.projectlombok
@@ -60,13 +59,7 @@
junit
junit
- 4.13.1
- test
-
-
- org.hamcrest
- hamcrest-junit
- ${hamcrest.junit.version}
+ 4.13.2
test
@@ -88,7 +81,7 @@
org.antlr
antlr4-maven-plugin
- 4.7.1
+ ${antlr4.version}
-package
@@ -106,29 +99,6 @@
-
-
- org.jacoco
- jacoco-maven-plugin
- 0.8.4
-
- ${sonar.jacoco.reportPath}
- true
-
- com/rbkmoney/fraudo/constant/**/*
- com/rbkmoney/fraudo/model/**/*
-
-
-
-
- agent
-
- prepare-agent
-
-
-
-
-
diff --git a/src/main/antlr4/com.rbkmoney.fraudo/FraudoP2P.g4 b/src/main/antlr4/com.rbkmoney.fraudo/FraudoP2P.g4
index 39a6399..277787c 100644
--- a/src/main/antlr4/com.rbkmoney.fraudo/FraudoP2P.g4
+++ b/src/main/antlr4/com.rbkmoney.fraudo/FraudoP2P.g4
@@ -56,5 +56,5 @@ floatExpression
;
in
- : 'in' LPAREN (stringExpression) DELIMETER string_list RPAREN
- ;
\ No newline at end of file
+ : 'in' LPAREN (stringExpression) DELIMITER string_list RPAREN
+ ;
diff --git a/src/main/antlr4/com.rbkmoney.fraudo/FraudoPayment.g4 b/src/main/antlr4/com.rbkmoney.fraudo/FraudoPayment.g4
index 6fdfce9..012c9e2 100644
--- a/src/main/antlr4/com.rbkmoney.fraudo/FraudoPayment.g4
+++ b/src/main/antlr4/com.rbkmoney.fraudo/FraudoPayment.g4
@@ -71,7 +71,7 @@ count_success
;
count_error
- : 'countError' LPAREN STRING time_window DELIMETER STRING (group_by)? RPAREN
+ : 'countError' LPAREN STRING time_window DELIMITER STRING (group_by)? RPAREN
;
count_chargeback
@@ -87,7 +87,7 @@ sum_success
;
sum_error
- : 'sumError' LPAREN STRING time_window DELIMETER STRING (group_by)? RPAREN
+ : 'sumError' LPAREN STRING time_window DELIMITER STRING (group_by)? RPAREN
;
sum_chargeback
@@ -99,7 +99,7 @@ sum_refund
;
in
- : 'in' LPAREN (stringExpression) DELIMETER string_list RPAREN
+ : 'in' LPAREN (stringExpression) DELIMITER string_list RPAREN
;
is_mobile
@@ -111,5 +111,33 @@ is_recurrent
;
is_trusted
- : 'isTrusted' LPAREN RPAREN
+ : 'isTrusted' LPAREN RPAREN #isTrusted
+ | 'isTrusted' LPAREN (payment_conditions | withdrawal_conditions) RPAREN #isTrustedConditionsSingleList
+ | 'isTrusted' LPAREN payment_conditions DELIMITER withdrawal_conditions RPAREN #isTrustedPaymentsAndWithdrawalConditions
+ ;
+
+payment_conditions
+ : 'paymentsConditions' LPAREN conditions_list RPAREN
+ ;
+
+withdrawal_conditions
+ : 'withdrawalsConditions' LPAREN conditions_list RPAREN
+ ;
+
+conditions_list
+ : trusted_token_condition (DELIMITER trusted_token_condition | WS)*
+ ;
+
+trusted_token_condition
+ : 'condition' LPAREN
+ STRING DELIMITER //transactions_currency
+ INTEGER DELIMITER //transactions_years_offset
+ INTEGER DELIMITER //transactions_count
+ INTEGER //transactions_sum
+ RPAREN
+ | 'condition' LPAREN
+ STRING DELIMITER //transactions_currency
+ INTEGER DELIMITER //transactions_years_offset
+ INTEGER //transactions_count
+ RPAREN
;
diff --git a/src/main/antlr4/imports/Fraudo.g4 b/src/main/antlr4/imports/Fraudo.g4
index df91aee..238c019 100644
--- a/src/main/antlr4/imports/Fraudo.g4
+++ b/src/main/antlr4/imports/Fraudo.g4
@@ -49,11 +49,11 @@ sum
;
unique
- : 'unique' LPAREN STRING DELIMETER STRING time_window (group_by)? RPAREN
+ : 'unique' LPAREN STRING DELIMITER STRING time_window (group_by)? RPAREN
;
in
- : 'in' LPAREN (country_by | STRING) DELIMETER string_list RPAREN
+ : 'in' LPAREN (country_by | STRING) DELIMITER string_list RPAREN
;
in_white_list
@@ -69,11 +69,11 @@ in_grey_list
;
in_list
- : 'inList' LPAREN STRING DELIMETER string_list RPAREN
+ : 'inList' LPAREN STRING DELIMITER string_list RPAREN
;
like
- : 'like' LPAREN STRING DELIMETER STRING RPAREN
+ : 'like' LPAREN STRING DELIMITER STRING RPAREN
;
country_by
@@ -98,22 +98,22 @@ catch_result
;
string_list
- : STRING (DELIMETER STRING | WS)*
+ : STRING (DELIMITER STRING | WS)*
;
time_window
- : DELIMETER INTEGER | DELIMETER INTEGER DELIMETER INTEGER
+ : DELIMITER INTEGER | DELIMITER INTEGER DELIMITER INTEGER
;
group_by
- : DELIMETER string_list
+ : DELIMITER string_list
;
STRING
: '"' (~["\r\n] | '""')* '"'
;
-DELIMETER : ',' ;
+DELIMITER : ',' ;
COMMENT
: '#' ~[\r\n]* -> skip
@@ -138,6 +138,6 @@ RPAREN : ')' ;
DECIMAL : '-'? ('0'..'9')+ '.' ('0'..'9')+;
INTEGER : '-'? ('0'..'9')+;
IDENTIFIER : [a-zA-Z_] [a-zA-Z_0-9]* ;
-WS : [ \u000C\n]+ -> skip;
+WS : [ \u000C\t\n]+ -> skip;
SCOL : ';';
-BOOLEAN : TRUE | FALSE;
\ No newline at end of file
+BOOLEAN : TRUE | FALSE;
diff --git a/src/main/java/com/rbkmoney/fraudo/converter/TrustConditionConverter.java b/src/main/java/com/rbkmoney/fraudo/converter/TrustConditionConverter.java
new file mode 100644
index 0000000..abbec4c
--- /dev/null
+++ b/src/main/java/com/rbkmoney/fraudo/converter/TrustConditionConverter.java
@@ -0,0 +1,42 @@
+package com.rbkmoney.fraudo.converter;
+
+import com.rbkmoney.fraudo.FraudoPaymentParser;
+import com.rbkmoney.fraudo.model.TrustCondition;
+import lombok.RequiredArgsConstructor;
+import org.antlr.v4.runtime.tree.TerminalNode;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static com.rbkmoney.fraudo.utils.TextUtil.safeGetInteger;
+import static com.rbkmoney.fraudo.utils.TextUtil.safeGetText;
+
+@RequiredArgsConstructor
+public class TrustConditionConverter {
+
+ private static final int YEARS_OFFSET_INDEX = 0;
+ private static final int COUNT_INDEX = 1;
+ private static final int SUM_INDEX = 2;
+
+ public List convertToList(FraudoPaymentParser.Conditions_listContext conditionsListContext) {
+ return conditionsListContext.trusted_token_condition().stream()
+ .map(this::convert)
+ .collect(Collectors.toList());
+ }
+
+ public TrustCondition convert(FraudoPaymentParser.Trusted_token_conditionContext ctx) {
+ List intNodes = ctx.INTEGER();
+ return TrustCondition.builder()
+ .transactionsCurrency(safeGetText(ctx.STRING()))
+ .transactionsYearsOffset(safeGetInteger(intNodes.get(YEARS_OFFSET_INDEX)))
+ .transactionsCount(safeGetInteger(intNodes.get(COUNT_INDEX)))
+ .transactionsSum(
+ hasSumArgument(intNodes.size()) ? safeGetInteger(intNodes.get(SUM_INDEX)) : null)
+ .build();
+ }
+
+ private boolean hasSumArgument(int intNodesSize) {
+ return intNodesSize > SUM_INDEX;
+ }
+
+}
diff --git a/src/main/java/com/rbkmoney/fraudo/model/TrustCondition.java b/src/main/java/com/rbkmoney/fraudo/model/TrustCondition.java
new file mode 100644
index 0000000..267abfd
--- /dev/null
+++ b/src/main/java/com/rbkmoney/fraudo/model/TrustCondition.java
@@ -0,0 +1,15 @@
+package com.rbkmoney.fraudo.model;
+
+import lombok.Builder;
+import lombok.Data;
+
+@Data
+@Builder
+public class TrustCondition {
+
+ private String transactionsCurrency;
+ private Integer transactionsYearsOffset;
+ private Integer transactionsSum;
+ private Integer transactionsCount;
+
+}
diff --git a/src/main/java/com/rbkmoney/fraudo/payment/factory/FraudVisitorFactoryImpl.java b/src/main/java/com/rbkmoney/fraudo/payment/factory/FraudVisitorFactoryImpl.java
index 435994b..87a89b6 100644
--- a/src/main/java/com/rbkmoney/fraudo/payment/factory/FraudVisitorFactoryImpl.java
+++ b/src/main/java/com/rbkmoney/fraudo/payment/factory/FraudVisitorFactoryImpl.java
@@ -1,6 +1,7 @@
package com.rbkmoney.fraudo.payment.factory;
import com.rbkmoney.fraudo.aggregator.UniqueValueAggregator;
+import com.rbkmoney.fraudo.converter.TrustConditionConverter;
import com.rbkmoney.fraudo.finder.InListFinder;
import com.rbkmoney.fraudo.model.BaseModel;
import com.rbkmoney.fraudo.payment.aggregator.CountPaymentAggregator;
@@ -11,6 +12,7 @@ import com.rbkmoney.fraudo.payment.resolver.PaymentTimeWindowResolver;
import com.rbkmoney.fraudo.payment.resolver.PaymentTypeResolver;
import com.rbkmoney.fraudo.payment.visitor.CountVisitor;
import com.rbkmoney.fraudo.payment.visitor.CustomFuncVisitor;
+import com.rbkmoney.fraudo.payment.visitor.IsTrustedFuncVisitor;
import com.rbkmoney.fraudo.payment.visitor.ListVisitor;
import com.rbkmoney.fraudo.payment.visitor.SumVisitor;
import com.rbkmoney.fraudo.payment.visitor.impl.*;
@@ -31,8 +33,10 @@ public class FraudVisitorFactoryImpl implements FraudVisitorFactory {
PaymentTimeWindowResolver timeWindowResolver,
PaymentTypeResolver paymentTypeResolver,
CustomerTypeResolver customerTypeResolver) {
- CountVisitor countVisitor = new CountVisitorImpl<>(countPaymentAggregator, fieldResolver, paymentGroupResolver, timeWindowResolver);
- SumVisitor sumVisitor = new SumVisitorImpl<>(sumPaymentAggregator, fieldResolver, paymentGroupResolver, timeWindowResolver);
+ CountVisitor countVisitor =
+ new CountVisitorImpl<>(countPaymentAggregator, fieldResolver, paymentGroupResolver, timeWindowResolver);
+ SumVisitor sumVisitor =
+ new SumVisitorImpl<>(sumPaymentAggregator, fieldResolver, paymentGroupResolver, timeWindowResolver);
ListVisitor listVisitor = new ListVisitorImpl<>(listFinder, fieldResolver);
CustomFuncVisitor customFuncVisitor = new CustomFuncVisitorImpl<>(
uniqueValueAggregator,
@@ -40,9 +44,20 @@ public class FraudVisitorFactoryImpl implements FraudVisitorFactory {
fieldResolver,
paymentGroupResolver,
timeWindowResolver,
- paymentTypeResolver,
- customerTypeResolver);
- return new FirstFindVisitorImpl<>(countVisitor, sumVisitor, listVisitor, customFuncVisitor, fieldResolver);
+ paymentTypeResolver
+ );
+ IsTrustedFuncVisitor isTrustedFuncVisitor = new IsTrustedFuncVisitorImpl<>(customerTypeResolver);
+ TrustConditionConverter trustConditionConverter = new TrustConditionConverter();
+
+ return new FirstFindVisitorImpl<>(
+ countVisitor,
+ sumVisitor,
+ listVisitor,
+ customFuncVisitor,
+ isTrustedFuncVisitor,
+ fieldResolver,
+ trustConditionConverter
+ );
}
}
diff --git a/src/main/java/com/rbkmoney/fraudo/payment/factory/FullVisitorFactoryImpl.java b/src/main/java/com/rbkmoney/fraudo/payment/factory/FullVisitorFactoryImpl.java
index ebd03db..4370dea 100644
--- a/src/main/java/com/rbkmoney/fraudo/payment/factory/FullVisitorFactoryImpl.java
+++ b/src/main/java/com/rbkmoney/fraudo/payment/factory/FullVisitorFactoryImpl.java
@@ -1,6 +1,7 @@
package com.rbkmoney.fraudo.payment.factory;
import com.rbkmoney.fraudo.aggregator.UniqueValueAggregator;
+import com.rbkmoney.fraudo.converter.TrustConditionConverter;
import com.rbkmoney.fraudo.finder.InListFinder;
import com.rbkmoney.fraudo.model.BaseModel;
import com.rbkmoney.fraudo.payment.aggregator.CountPaymentAggregator;
@@ -11,6 +12,7 @@ import com.rbkmoney.fraudo.payment.resolver.PaymentTimeWindowResolver;
import com.rbkmoney.fraudo.payment.resolver.PaymentTypeResolver;
import com.rbkmoney.fraudo.payment.visitor.CountVisitor;
import com.rbkmoney.fraudo.payment.visitor.CustomFuncVisitor;
+import com.rbkmoney.fraudo.payment.visitor.IsTrustedFuncVisitor;
import com.rbkmoney.fraudo.payment.visitor.ListVisitor;
import com.rbkmoney.fraudo.payment.visitor.SumVisitor;
import com.rbkmoney.fraudo.payment.visitor.impl.*;
@@ -34,15 +36,24 @@ public class FullVisitorFactoryImpl implements FraudVisitorFactory {
CountVisitor countVisitor = new CountVisitorImpl<>(countPaymentAggregator, fieldResolver, paymentGroupResolver, timeWindowResolver);
SumVisitor sumVisitor = new SumVisitorImpl<>(sumPaymentAggregator, fieldResolver, paymentGroupResolver, timeWindowResolver);
ListVisitor listVisitor = new ListVisitorImpl<>(listFinder, fieldResolver);
+ IsTrustedFuncVisitor isTrustedFuncVisitor = new IsTrustedFuncVisitorImpl<>(customerTypeResolver);
+ TrustConditionConverter trustConditionConverter = new TrustConditionConverter();
CustomFuncVisitor customFuncVisitor = new CustomFuncVisitorImpl<>(
uniqueValueAggregator,
countryResolver,
fieldResolver,
paymentGroupResolver,
timeWindowResolver,
- paymentTypeResolver,
- customerTypeResolver);
- return new FullVisitorImpl<>(countVisitor, sumVisitor, listVisitor, customFuncVisitor, fieldResolver);
+ paymentTypeResolver);
+ return new FullVisitorImpl<>(
+ countVisitor,
+ sumVisitor,
+ listVisitor,
+ customFuncVisitor,
+ isTrustedFuncVisitor,
+ fieldResolver,
+ trustConditionConverter
+ );
}
}
diff --git a/src/main/java/com/rbkmoney/fraudo/payment/resolver/CustomerTypeResolver.java b/src/main/java/com/rbkmoney/fraudo/payment/resolver/CustomerTypeResolver.java
index 51379bc..42ea7b0 100644
--- a/src/main/java/com/rbkmoney/fraudo/payment/resolver/CustomerTypeResolver.java
+++ b/src/main/java/com/rbkmoney/fraudo/payment/resolver/CustomerTypeResolver.java
@@ -1,7 +1,13 @@
package com.rbkmoney.fraudo.payment.resolver;
+import com.rbkmoney.fraudo.model.TrustCondition;
+
+import java.util.List;
+
public interface CustomerTypeResolver {
Boolean isTrusted(T model);
+ Boolean isTrusted(List paymentsConditions, List withdrawalsConditions);
+
}
diff --git a/src/main/java/com/rbkmoney/fraudo/payment/visitor/CustomFuncVisitor.java b/src/main/java/com/rbkmoney/fraudo/payment/visitor/CustomFuncVisitor.java
index a44b00e..77558cb 100644
--- a/src/main/java/com/rbkmoney/fraudo/payment/visitor/CustomFuncVisitor.java
+++ b/src/main/java/com/rbkmoney/fraudo/payment/visitor/CustomFuncVisitor.java
@@ -14,6 +14,4 @@ public interface CustomFuncVisitor {
boolean visitCheckRecurrent(Is_recurrentContext ctx, T model);
- boolean visitCheckTrusted(Is_trustedContext ctx, T model);
-
}
diff --git a/src/main/java/com/rbkmoney/fraudo/payment/visitor/IsTrustedFuncVisitor.java b/src/main/java/com/rbkmoney/fraudo/payment/visitor/IsTrustedFuncVisitor.java
new file mode 100644
index 0000000..08a543f
--- /dev/null
+++ b/src/main/java/com/rbkmoney/fraudo/payment/visitor/IsTrustedFuncVisitor.java
@@ -0,0 +1,13 @@
+package com.rbkmoney.fraudo.payment.visitor;
+
+import com.rbkmoney.fraudo.model.TrustCondition;
+
+import java.util.List;
+
+public interface IsTrustedFuncVisitor {
+
+ boolean visitCheckTrusted(T model);
+
+ boolean visitCheckTrusted(List paymentsConditionsList,
+ List withdrawalConditionsList);
+}
diff --git a/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/CustomFuncVisitorImpl.java b/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/CustomFuncVisitorImpl.java
index 45d3bcc..f7868cf 100644
--- a/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/CustomFuncVisitorImpl.java
+++ b/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/CustomFuncVisitorImpl.java
@@ -23,7 +23,6 @@ public class CustomFuncVisitorImpl implements CustomFuncVisitor {
private final PaymentGroupResolver groupResolver;
private final PaymentTimeWindowResolver timeWindowResolver;
private final PaymentTypeResolver paymentTypeResolver;
- private final CustomerTypeResolver customerTypeResolver;
@Override
public String visitCountryBy(Country_byContext ctx, T model) {
@@ -63,9 +62,4 @@ public class CustomFuncVisitorImpl implements CustomFuncVisitor {
return paymentTypeResolver.isRecurrent(model);
}
- @Override
- public boolean visitCheckTrusted(Is_trustedContext ctx, T model) {
- return customerTypeResolver.isTrusted(model);
- }
-
}
diff --git a/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/FirstFindVisitorImpl.java b/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/FirstFindVisitorImpl.java
index bb9105c..42e2191 100644
--- a/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/FirstFindVisitorImpl.java
+++ b/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/FirstFindVisitorImpl.java
@@ -2,15 +2,18 @@ package com.rbkmoney.fraudo.payment.visitor.impl;
import com.rbkmoney.fraudo.FraudoPaymentBaseVisitor;
import com.rbkmoney.fraudo.constant.ResultStatus;
+import com.rbkmoney.fraudo.converter.TrustConditionConverter;
import com.rbkmoney.fraudo.exception.NotImplementedOperatorException;
import com.rbkmoney.fraudo.exception.NotValidContextException;
import com.rbkmoney.fraudo.exception.UnknownResultException;
import com.rbkmoney.fraudo.model.BaseModel;
import com.rbkmoney.fraudo.model.ResultModel;
import com.rbkmoney.fraudo.model.RuleResult;
+import com.rbkmoney.fraudo.model.TrustCondition;
import com.rbkmoney.fraudo.payment.generator.RuleKeyGenerator;
import com.rbkmoney.fraudo.payment.visitor.CountVisitor;
import com.rbkmoney.fraudo.payment.visitor.CustomFuncVisitor;
+import com.rbkmoney.fraudo.payment.visitor.IsTrustedFuncVisitor;
import com.rbkmoney.fraudo.payment.visitor.ListVisitor;
import com.rbkmoney.fraudo.payment.visitor.SumVisitor;
import com.rbkmoney.fraudo.resolver.FieldResolver;
@@ -42,7 +45,9 @@ public class FirstFindVisitorImpl extends FraudoPaymentB
private final SumVisitor sumVisitor;
private final ListVisitor listVisitor;
private final CustomFuncVisitor customFuncVisitor;
+ private final IsTrustedFuncVisitor isTrustedFuncVisitor;
private final FieldResolver fieldResolver;
+ private final TrustConditionConverter trustConditionConverter;
@Override
public void close() {
@@ -376,7 +381,32 @@ public class FirstFindVisitorImpl extends FraudoPaymentB
}
@Override
- public Boolean visitIs_trusted(Is_trustedContext ctx) {
- return customFuncVisitor.visitCheckTrusted(ctx, threadLocalModel.get());
+ public Object visitIsTrusted(IsTrustedContext ctx) {
+ return isTrustedFuncVisitor.visitCheckTrusted(threadLocalModel.get());
}
+
+ @Override
+ public Object visitIsTrustedConditionsSingleList(IsTrustedConditionsSingleListContext ctx) {
+ if (ctx.payment_conditions() != null && !ctx.payment_conditions().isEmpty()) {
+ List paymentsConditions =
+ trustConditionConverter.convertToList(ctx.payment_conditions().conditions_list());
+ return isTrustedFuncVisitor.visitCheckTrusted(paymentsConditions, null);
+ }
+ if (ctx.withdrawal_conditions() != null && !ctx.withdrawal_conditions().isEmpty()) {
+ List withdrawalsConditions =
+ trustConditionConverter.convertToList(ctx.withdrawal_conditions().conditions_list());
+ return isTrustedFuncVisitor.visitCheckTrusted(null, withdrawalsConditions);
+ }
+ throw new NotValidContextException();
+ }
+
+ @Override
+ public Object visitIsTrustedPaymentsAndWithdrawalConditions(IsTrustedPaymentsAndWithdrawalConditionsContext ctx) {
+ List paymentsConditions =
+ trustConditionConverter.convertToList(ctx.payment_conditions().conditions_list());
+ List withdrawalsConditions =
+ trustConditionConverter.convertToList(ctx.withdrawal_conditions().conditions_list());
+ return isTrustedFuncVisitor.visitCheckTrusted(paymentsConditions, withdrawalsConditions);
+ }
+
}
diff --git a/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/FullVisitorImpl.java b/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/FullVisitorImpl.java
index f029906..baab01b 100644
--- a/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/FullVisitorImpl.java
+++ b/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/FullVisitorImpl.java
@@ -1,6 +1,7 @@
package com.rbkmoney.fraudo.payment.visitor.impl;
import com.rbkmoney.fraudo.constant.ResultStatus;
+import com.rbkmoney.fraudo.converter.TrustConditionConverter;
import com.rbkmoney.fraudo.exception.UnknownResultException;
import com.rbkmoney.fraudo.model.BaseModel;
import com.rbkmoney.fraudo.model.ResultModel;
@@ -8,6 +9,7 @@ import com.rbkmoney.fraudo.model.RuleResult;
import com.rbkmoney.fraudo.payment.generator.RuleKeyGenerator;
import com.rbkmoney.fraudo.payment.visitor.CountVisitor;
import com.rbkmoney.fraudo.payment.visitor.CustomFuncVisitor;
+import com.rbkmoney.fraudo.payment.visitor.IsTrustedFuncVisitor;
import com.rbkmoney.fraudo.payment.visitor.ListVisitor;
import com.rbkmoney.fraudo.payment.visitor.SumVisitor;
import com.rbkmoney.fraudo.resolver.FieldResolver;
@@ -22,8 +24,17 @@ import static com.rbkmoney.fraudo.FraudoPaymentParser.ParseContext;
@Slf4j
public class FullVisitorImpl extends FirstFindVisitorImpl {
- public FullVisitorImpl(CountVisitor countVisitor, SumVisitor sumVisitor, ListVisitor listVisitor, CustomFuncVisitor customFuncVisitor, FieldResolver fieldResolver) {
- super(countVisitor, sumVisitor, listVisitor, customFuncVisitor, fieldResolver);
+ public FullVisitorImpl(
+ CountVisitor countVisitor,
+ SumVisitor sumVisitor,
+ ListVisitor listVisitor,
+ CustomFuncVisitor customFuncVisitor,
+ IsTrustedFuncVisitor isTrustedFuncVisitor,
+ FieldResolver fieldResolver,
+ TrustConditionConverter trustConditionConverter
+ ) {
+ super(countVisitor, sumVisitor, listVisitor, customFuncVisitor, isTrustedFuncVisitor, fieldResolver,
+ trustConditionConverter);
}
@Override
diff --git a/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/IsTrustedFuncVisitorImpl.java b/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/IsTrustedFuncVisitorImpl.java
new file mode 100644
index 0000000..c3cb506
--- /dev/null
+++ b/src/main/java/com/rbkmoney/fraudo/payment/visitor/impl/IsTrustedFuncVisitorImpl.java
@@ -0,0 +1,26 @@
+package com.rbkmoney.fraudo.payment.visitor.impl;
+
+import com.rbkmoney.fraudo.model.TrustCondition;
+import com.rbkmoney.fraudo.payment.resolver.CustomerTypeResolver;
+import com.rbkmoney.fraudo.payment.visitor.IsTrustedFuncVisitor;
+import lombok.RequiredArgsConstructor;
+
+import java.util.List;
+
+@RequiredArgsConstructor
+public class IsTrustedFuncVisitorImpl implements IsTrustedFuncVisitor {
+
+ private final CustomerTypeResolver customerTypeResolver;
+
+ @Override
+ public boolean visitCheckTrusted(T model) {
+ return customerTypeResolver.isTrusted(model);
+ }
+
+ @Override
+ public boolean visitCheckTrusted(List paymentsConditionsList,
+ List withdrawalConditionsList) {
+ return customerTypeResolver.isTrusted(paymentsConditionsList, withdrawalConditionsList);
+ }
+
+}
diff --git a/src/main/java/com/rbkmoney/fraudo/utils/TextUtil.java b/src/main/java/com/rbkmoney/fraudo/utils/TextUtil.java
index a3160c6..d72bea9 100644
--- a/src/main/java/com/rbkmoney/fraudo/utils/TextUtil.java
+++ b/src/main/java/com/rbkmoney/fraudo/utils/TextUtil.java
@@ -16,4 +16,10 @@ public class TextUtil {
.getText().replace("\"", "");
}
+ public static Integer safeGetInteger(TerminalNode field) {
+ return Optional.ofNullable(field)
+ .map(node -> Integer.parseInt(node.getText()))
+ .orElseThrow(FieldUnsetException::new);
+ }
+
}
diff --git a/src/test/java/com/rbkmoney/fraudo/CustomTest.java b/src/test/java/com/rbkmoney/fraudo/CustomTest.java
index ed83427..7dee2ae 100644
--- a/src/test/java/com/rbkmoney/fraudo/CustomTest.java
+++ b/src/test/java/com/rbkmoney/fraudo/CustomTest.java
@@ -134,17 +134,6 @@ public class CustomTest extends AbstractPaymentTest {
assertEquals(ResultStatus.ACCEPT, ResultUtils.findFirstNotNotifyStatus(result).get().getResultStatus());
}
- @Test
- public void trustedTest() throws Exception {
- InputStream resourceAsStream = CustomTest.class.getResourceAsStream("/rules/is_trusted.frd");
- when(customerTypeResolver.isTrusted(any())).thenReturn(true);
-
- ParseContext parseContext = getParseContext(resourceAsStream);
- PaymentModel model = new PaymentModel();
- ResultModel result = invoke(parseContext, model);
- assertEquals(ResultStatus.ACCEPT, ResultUtils.findFirstNotNotifyStatus(result).get().getResultStatus());
- }
-
@Test
public void payerTypeTest() throws Exception {
InputStream resourceAsStream = CustomTest.class.getResourceAsStream("/rules/is_recurrent.frd");
diff --git a/src/test/java/com/rbkmoney/fraudo/IsTrustedTest.java b/src/test/java/com/rbkmoney/fraudo/IsTrustedTest.java
new file mode 100644
index 0000000..c38420e
--- /dev/null
+++ b/src/test/java/com/rbkmoney/fraudo/IsTrustedTest.java
@@ -0,0 +1,98 @@
+package com.rbkmoney.fraudo;
+
+import com.rbkmoney.fraudo.constant.ResultStatus;
+import com.rbkmoney.fraudo.model.ResultModel;
+import com.rbkmoney.fraudo.model.TrustCondition;
+import com.rbkmoney.fraudo.test.model.PaymentModel;
+import com.rbkmoney.fraudo.utils.ResultUtils;
+import lombok.SneakyThrows;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.MockitoAnnotations;
+
+import java.io.InputStream;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyListOf;
+import static org.mockito.Matchers.isNull;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class IsTrustedTest extends AbstractPaymentTest {
+
+ @Before
+ public void init() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void trustedTest() {
+ when(customerTypeResolver.isTrusted(any())).thenReturn(true);
+ testIsTrusted("/rules/is_trusted.frd");
+ }
+
+ @Test
+ public void trustedWithWithdrawalsConditionsTest() {
+ when(customerTypeResolver.isTrusted(isNull(List.class), anyListOf(TrustCondition.class)))
+ .thenReturn(true);
+ testIsTrusted("/rules/is_trusted_with_withdrawals_conditions.frd");
+ }
+
+ @Test
+ public void trustedWithPaymentsConditionsTest() {
+ when(customerTypeResolver.isTrusted(anyListOf(TrustCondition.class), isNull(List.class)))
+ .thenReturn(true);
+ testIsTrusted("/rules/is_trusted_with_payments_conditions.frd");
+ }
+
+ @Test
+ public void trustedWithPaymentsAndWithdrawalSingleConditionsTest() {
+ when(customerTypeResolver.isTrusted(anyListOf(TrustCondition.class), anyListOf(TrustCondition.class)))
+ .thenReturn(true);
+ testIsTrusted("/rules/is_trusted_with_payments_and_withdrawals_single_conditions.frd");
+ }
+
+ @Test
+ public void trustedWithPaymentsAndWithdrawalTest() {
+ when(customerTypeResolver.isTrusted(anyListOf(TrustCondition.class), anyListOf(TrustCondition.class)))
+ .thenReturn(true);
+ testIsTrusted("/rules/is_trusted_with_payments_and_withdrawals_conditions.frd");
+
+ ArgumentCaptor> paymentsCaptor = ArgumentCaptor.forClass((Class) List.class);
+ ArgumentCaptor> withdrawalsCaptor = ArgumentCaptor.forClass((Class) List.class);
+ verify(customerTypeResolver, times(1))
+ .isTrusted(paymentsCaptor.capture(), withdrawalsCaptor.capture());
+
+ assertEquals(1, paymentsCaptor.getAllValues().size());
+ List payments = paymentsCaptor.getValue();
+ assertTrustedCondition("RUB",1,1000,10, payments.get(0));
+ assertTrustedCondition("EUR", 2, 20, null, payments.get(1));
+ assertEquals(1, withdrawalsCaptor.getAllValues().size());
+ List withdrawals = withdrawalsCaptor.getValue();
+ assertTrustedCondition("USD",3,3000,3, withdrawals.get(0));
+ assertTrustedCondition("CAD", 4, 4, null, withdrawals.get(1));
+
+ }
+
+ @SneakyThrows
+ private void testIsTrusted(String testCaseFilePath) {
+ InputStream resourceAsStream = IsTrustedTest.class.getResourceAsStream(testCaseFilePath);
+ com.rbkmoney.fraudo.FraudoPaymentParser.ParseContext parseContext = getParseContext(resourceAsStream);
+ PaymentModel model = new PaymentModel();
+ ResultModel result = invoke(parseContext, model);
+ assertEquals(ResultStatus.ACCEPT, ResultUtils.findFirstNotNotifyStatus(result).get().getResultStatus());
+ }
+
+ private void assertTrustedCondition(
+ String currency, Integer yearsOffset, Integer count, Integer sum, TrustCondition condition) {
+ assertEquals(currency, condition.getTransactionsCurrency());
+ assertEquals(yearsOffset, condition.getTransactionsYearsOffset());
+ assertEquals(count, condition.getTransactionsCount());
+ assertEquals(sum, condition.getTransactionsSum());
+ }
+
+}
diff --git a/src/test/java/com/rbkmoney/fraudo/RealTimerTest.java b/src/test/java/com/rbkmoney/fraudo/RealTimerTest.java
index 85de71a..5c3689c 100644
--- a/src/test/java/com/rbkmoney/fraudo/RealTimerTest.java
+++ b/src/test/java/com/rbkmoney/fraudo/RealTimerTest.java
@@ -23,7 +23,7 @@ public class RealTimerTest extends AbstractPaymentTest {
public static final long TIME_CALL_AGGR_FUNC = 200L;
public static final long MILLISTIME_FAST_FUNC = 10L;
- public static final long TIME_CALLING = 200L;
+ public static final long TIME_CALLING = 300L;
@Before
public void init() {
@@ -50,7 +50,7 @@ public class RealTimerTest extends AbstractPaymentTest {
assertEquals(0, countDownLatch.getCount());
assertTrue(executionTime < TIME_CALL_AGGR_FUNC + 1 + TIME_CALLING);
- System.out.println("executionTime=" + executionTime);
+ System.out.println("timingTest.executionTime=" + executionTime);
result = invokeFullVisitor(parseContext, model);
assertEquals(2, result.getRuleResults().size());
@@ -71,6 +71,7 @@ public class RealTimerTest extends AbstractPaymentTest {
long start = System.currentTimeMillis();
ResultModel result = invoke(parseContext, model);
long executionTime = System.currentTimeMillis() - start;
+ System.out.println("timingWithSuccessTest.executionTime=" + executionTime);
Assert.assertEquals(ResultStatus.ACCEPT, ResultUtils.findFirstNotNotifyStatus(result).get().getResultStatus());
assertTrue(executionTime < TIME_CALL_AGGR_FUNC * 4 + TIME_CALLING);
diff --git a/src/test/resources/rules/is_trusted_with_payments_and_withdrawals_conditions.frd b/src/test/resources/rules/is_trusted_with_payments_and_withdrawals_conditions.frd
new file mode 100644
index 0000000..1c82a9d
--- /dev/null
+++ b/src/test/resources/rules/is_trusted_with_payments_and_withdrawals_conditions.frd
@@ -0,0 +1,10 @@
+rule: isTrusted(
+ paymentsConditions(
+ condition("RUB",1,1000,10),
+ condition("EUR", 2, 20)
+ ),
+ withdrawalsConditions(
+ condition("USD",3,3000,3),
+ condition("CAD", 4, 4)
+ )
+) -> accept;
diff --git a/src/test/resources/rules/is_trusted_with_payments_and_withdrawals_single_conditions.frd b/src/test/resources/rules/is_trusted_with_payments_and_withdrawals_single_conditions.frd
new file mode 100644
index 0000000..489d981
--- /dev/null
+++ b/src/test/resources/rules/is_trusted_with_payments_and_withdrawals_single_conditions.frd
@@ -0,0 +1,8 @@
+rule: isTrusted(
+ paymentsConditions(
+ condition("RUB",1,1000,10)
+ ),
+ withdrawalsConditions(
+ condition("CAD", 4, 4)
+ )
+) -> accept;
diff --git a/src/test/resources/rules/is_trusted_with_payments_conditions.frd b/src/test/resources/rules/is_trusted_with_payments_conditions.frd
new file mode 100644
index 0000000..f19109b
--- /dev/null
+++ b/src/test/resources/rules/is_trusted_with_payments_conditions.frd
@@ -0,0 +1,6 @@
+rule: isTrusted(
+ paymentsConditions(
+ condition("RUB",1,1000,10),
+ condition("EUR", 2, 20)
+ )
+) -> accept;
diff --git a/src/test/resources/rules/is_trusted_with_withdrawals_conditions.frd b/src/test/resources/rules/is_trusted_with_withdrawals_conditions.frd
new file mode 100644
index 0000000..ed7fda1
--- /dev/null
+++ b/src/test/resources/rules/is_trusted_with_withdrawals_conditions.frd
@@ -0,0 +1,6 @@
+rule: isTrusted(
+ withdrawalsConditions(
+ condition("USD",3,3000,3),
+ condition("CAD", 4, 4)
+ )
+) -> accept;