前后端分目录
This commit is contained in:
15
ddp/ddp-enginex/runner-node/pom.xml
Normal file
15
ddp/ddp-enginex/runner-node/pom.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>ddp-enginex</artifactId>
|
||||
<groupId>com.fibo.ddp</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ddp-enginex-runner-node</artifactId>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,120 @@
|
||||
package com.fibo.ddp.enginex.runner.canal;
|
||||
|
||||
import com.fibo.ddp.common.dao.canal.TableEnum;
|
||||
import com.fibo.ddp.common.dao.datax.datasource.SimpleMapper;
|
||||
import com.fibo.ddp.common.service.redis.RedisManager;
|
||||
import com.fibo.ddp.common.service.redis.RedisUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/cache")
|
||||
public class CacheController {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Resource
|
||||
private SimpleMapper simpleMapper;
|
||||
@Autowired
|
||||
private RedisManager redisManager;
|
||||
|
||||
@RequestMapping(value = "initCache", method = RequestMethod.GET)
|
||||
public void initCache() {
|
||||
logger.info("===================== 缓存初始化开始 =====================");
|
||||
long start = System.currentTimeMillis();
|
||||
// 遍历表
|
||||
for (TableEnum tableEnum : TableEnum.values()) {
|
||||
String tableName = tableEnum.getTableName();
|
||||
logger.info("===================== 开始初始化缓存表[{}] =====================", tableName);
|
||||
|
||||
String sqlStr = "select * from " + tableName;
|
||||
Map<String, Object> parameterMap = new HashMap<>();
|
||||
parameterMap.put("sqlStr", sqlStr);
|
||||
List<LinkedHashMap<String, Object>> result = simpleMapper.customSelect(parameterMap);
|
||||
// 遍历行
|
||||
for (LinkedHashMap<String, Object> map : result) {
|
||||
row(tableEnum, map);
|
||||
}
|
||||
logger.info("===================== 结束初始化缓存表[{}],共[{}]条数据 =====================", tableName, result.size());
|
||||
}
|
||||
long end = System.currentTimeMillis();
|
||||
logger.info("===================== 缓存初始化成功!!耗时:{}ms =====================", (end - start));
|
||||
}
|
||||
|
||||
private void row(TableEnum tableEnum, LinkedHashMap<String, Object> map) {
|
||||
String tableName = tableEnum.getTableName();
|
||||
String primaryKey = null;
|
||||
String foreignKey = null;
|
||||
|
||||
if (StringUtils.isNotBlank(tableEnum.getPrimaryId())) {
|
||||
String primaryId = map.get(tableEnum.getPrimaryId()).toString();
|
||||
primaryKey = RedisUtils.getPrimaryKey(tableName, primaryId);
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(tableEnum.getForeignId())) {
|
||||
Object obj = map.get(tableEnum.getForeignId());
|
||||
if (obj != null && !"".equals(obj.toString())) {
|
||||
String foreignId = obj.toString();
|
||||
foreignKey = RedisUtils.getForeignKey(tableName, foreignId);
|
||||
}
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(primaryKey)) {
|
||||
// 遍历列
|
||||
for (String field : map.keySet()) {
|
||||
String value = map.get(field) == null ? null : map.get(field).toString();
|
||||
setColumnCache(primaryKey, field, value);
|
||||
}
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(foreignKey)) {
|
||||
setForeignKeyCache(primaryKey, foreignKey);
|
||||
}
|
||||
|
||||
// 指标表特殊处理
|
||||
dealSpecialTable(tableName, map);
|
||||
}
|
||||
|
||||
private void setColumnCache(String primaryKey, String field, String value) {
|
||||
logger.info("开始主键缓存设置, primaryKey:{}, field:{}, value:{}", primaryKey, field, value);
|
||||
|
||||
redisManager.hset(primaryKey, field, value);
|
||||
|
||||
logger.info("结束主键缓存设置, primaryKey:{}, field:{}, value:{}", primaryKey, field, value);
|
||||
}
|
||||
|
||||
private void setForeignKeyCache(String primaryKey, String foreignKey) {
|
||||
logger.info("开始外键缓存设置, primaryKey:{}, foreignKey:{}", primaryKey, foreignKey);
|
||||
|
||||
redisManager.sadd(foreignKey, primaryKey);
|
||||
|
||||
logger.info("结束外键缓存设置, primaryKey:{}, foreignKey:{}", primaryKey, foreignKey);
|
||||
}
|
||||
|
||||
private void dealSpecialTable(String tableName, LinkedHashMap<String, Object> map) {
|
||||
if(tableName.equals(TableEnum.T_FIELD.getTableName())){
|
||||
String fieldEn = "field_en:" + map.get("organ_id") + ":" + map.get("field_en");
|
||||
String fieldEnKey = RedisUtils.getPrimaryKey(tableName, fieldEn);
|
||||
|
||||
String fieldCn = "field_cn:" + map.get("organ_id") + ":" + map.get("field_cn");
|
||||
String fieldCnKey = RedisUtils.getPrimaryKey(tableName, fieldCn);
|
||||
|
||||
for (String field : map.keySet()) {
|
||||
String value = map.get(field) == null ? null : map.get(field).toString();
|
||||
setColumnCache(fieldEnKey, field, value);
|
||||
setColumnCache(fieldCnKey, field, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
package com.fibo.ddp.enginex.runner.canal;
|
||||
|
||||
import com.alibaba.otter.canal.client.CanalConnector;
|
||||
import com.alibaba.otter.canal.client.CanalConnectors;
|
||||
import com.alibaba.otter.canal.protocol.CanalEntry;
|
||||
import com.alibaba.otter.canal.protocol.Message;
|
||||
import com.fibo.ddp.common.dao.canal.TableEnum;
|
||||
import com.fibo.ddp.common.service.redis.RedisManager;
|
||||
import com.fibo.ddp.common.service.redis.RedisUtils;
|
||||
import com.fibo.ddp.common.utils.constant.Constants;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Canal数据同步
|
||||
* 实现ApplicationRunner接口,springboot启动成功后会执行run方法
|
||||
*/
|
||||
@Component
|
||||
public class CanalClient implements ApplicationRunner {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
private final static int BATCH_SIZE = 1000;
|
||||
@Autowired
|
||||
private RedisManager redisManager;
|
||||
// canal缓存同步是否开启
|
||||
@Value("${switch.canal.cache}")
|
||||
private String canalCacheSwitch;
|
||||
// canal主机地址
|
||||
@Value("${canal.hostname}")
|
||||
private String canalHostName;
|
||||
// canal端口
|
||||
@Value("${canal.port}")
|
||||
private int canalPort;
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) throws Exception {
|
||||
if(Constants.switchFlag.OFF.equals(canalCacheSwitch)){
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建链接
|
||||
CanalConnector connector = CanalConnectors.newSingleConnector(
|
||||
new InetSocketAddress(canalHostName, canalPort),
|
||||
"example", "", "");
|
||||
try {
|
||||
//打开连接
|
||||
connector.connect();
|
||||
//订阅数据库表,全部表
|
||||
connector.subscribe(".*\\..*");
|
||||
//回滚到未进行ack的地方,下次fetch的时候,可以从最后一个没有ack的地方开始拿
|
||||
connector.rollback();
|
||||
while (true) {
|
||||
logger.info("canal数据同步监听中...");
|
||||
// 获取指定数量的数据
|
||||
Message message = connector.getWithoutAck(BATCH_SIZE);
|
||||
//获取批量ID
|
||||
long batchId = message.getId();
|
||||
//获取批量的数量
|
||||
int size = message.getEntries().size();
|
||||
//如果没有数据
|
||||
if (batchId == -1 || size == 0) {
|
||||
try {
|
||||
//线程休眠2秒
|
||||
Thread.sleep(2000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
//如果有数据,处理数据
|
||||
printEntry(message.getEntries());
|
||||
}
|
||||
//进行 batch id 的确认。确认之后,小于等于此 batchId 的 Message 都会被确认。
|
||||
connector.ack(batchId);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
connector.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析binlog获得的实体类信息
|
||||
*/
|
||||
private void printEntry(List<CanalEntry.Entry> entrys) {
|
||||
for (CanalEntry.Entry entry : entrys) {
|
||||
if (entry.getEntryType() == CanalEntry.EntryType.TRANSACTIONBEGIN || entry.getEntryType() == CanalEntry.EntryType.TRANSACTIONEND) {
|
||||
//开启/关闭事务的实体类型,跳过
|
||||
continue;
|
||||
}
|
||||
|
||||
String tableName = entry.getHeader().getTableName();
|
||||
TableEnum tableEnum = TableEnum.getByTableName(tableName);
|
||||
if(tableEnum == null){
|
||||
// 没有在枚举中定义的表,跳过
|
||||
continue;
|
||||
}
|
||||
|
||||
//RowChange对象,包含了一行数据变化的所有特征
|
||||
//比如isDdl 是否是ddl变更操作 sql 具体的ddl sql beforeColumns afterColumns 变更前后的数据字段等等
|
||||
CanalEntry.RowChange rowChage;
|
||||
try {
|
||||
rowChage = CanalEntry.RowChange.parseFrom(entry.getStoreValue());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("ERROR ## parser of eromanga-event has an error , data:" + entry.toString(), e);
|
||||
}
|
||||
|
||||
//获取操作类型:insert/update/delete类型
|
||||
CanalEntry.EventType eventType = rowChage.getEventType();
|
||||
//打印Header信息
|
||||
logger.info(String.format("============= binlog[%s:%s] , name[%s,%s] , eventType : %s =============",
|
||||
entry.getHeader().getLogfileName(), entry.getHeader().getLogfileOffset(),
|
||||
entry.getHeader().getSchemaName(), entry.getHeader().getTableName(),
|
||||
eventType));
|
||||
|
||||
//判断是否是DDL语句
|
||||
if (rowChage.getIsDdl()) {
|
||||
logger.info("============= isDdl: true,sql:" + rowChage.getSql());
|
||||
}
|
||||
|
||||
//获取RowChange对象里的每一行数据
|
||||
for (CanalEntry.RowData rowData : rowChage.getRowDatasList()) {
|
||||
//如果是删除语句
|
||||
if (eventType == CanalEntry.EventType.DELETE) {
|
||||
row(rowData.getBeforeColumnsList(), tableName);
|
||||
//如果是新增语句
|
||||
} else if (eventType == CanalEntry.EventType.INSERT) {
|
||||
row(rowData.getAfterColumnsList(), tableName);
|
||||
//如果是更新的语句
|
||||
} else {
|
||||
//变更前的数据
|
||||
// printColumn(rowData.getBeforeColumnsList(), tableName);
|
||||
//变更后的数据
|
||||
row(rowData.getAfterColumnsList(), tableName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void row(List<CanalEntry.Column> columns, String tableName) {
|
||||
Optional<CanalEntry.Column> keyColumn = columns.stream().filter(item -> item.getIsKey()).findFirst();
|
||||
if(keyColumn.isPresent()){
|
||||
// 获取主键id
|
||||
String id = keyColumn.get().getValue();
|
||||
// 拼接主键key
|
||||
String key = RedisUtils.getPrimaryKey(tableName, id);
|
||||
// 拼接外键key
|
||||
String foreignKey = null;
|
||||
// 子表的redis key需要拼接上主表的id
|
||||
TableEnum tableEnum = TableEnum.getByTableName(tableName);
|
||||
if(tableEnum != null){
|
||||
Optional<CanalEntry.Column> foreignKeyColumn = columns.stream().filter(item -> item.getName().equals(tableEnum.getForeignId())).findFirst();
|
||||
if(foreignKeyColumn.isPresent()){
|
||||
String foreignKeyValue = foreignKeyColumn.get().getValue();
|
||||
foreignKey = RedisUtils.getForeignKey(tableName, foreignKeyValue);
|
||||
}
|
||||
}
|
||||
|
||||
for (CanalEntry.Column column : columns) {
|
||||
// 更新发生改变的字段缓存
|
||||
setUpdatedColumnCache(column, key, foreignKey);
|
||||
}
|
||||
|
||||
// 指标表特殊处理
|
||||
dealSpecialTable(columns, tableName);
|
||||
}
|
||||
}
|
||||
|
||||
private void setUpdatedColumnCache(CanalEntry.Column column, String key, String foreignKey){
|
||||
if(column.getUpdated()) {
|
||||
logger.info("开始主键缓存更新, {}, {}, {}", key, column.getName(), column.getValue());
|
||||
|
||||
redisManager.hset(key, column.getName(), column.getValue());
|
||||
|
||||
logger.info("结束主键缓存更新, {}, {}, {}", key, column.getName(), column.getValue());
|
||||
|
||||
if(foreignKey != null){
|
||||
logger.info("开始外键缓存更新, {}, {}", key, foreignKey);
|
||||
|
||||
redisManager.sadd(foreignKey, key);
|
||||
|
||||
logger.info("结束外键缓存更新, {}, {}", key, foreignKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setAllColumnCache(CanalEntry.Column column, String key){
|
||||
logger.info("开始主键缓存更新, {}, {}, {}", key, column.getName(), column.getValue());
|
||||
|
||||
redisManager.hset(key, column.getName(), column.getValue());
|
||||
|
||||
logger.info("结束主键缓存更新, {}, {}, {}", key, column.getName(), column.getValue());
|
||||
}
|
||||
|
||||
private void dealSpecialTable(List<CanalEntry.Column> columns, String tableName){
|
||||
if(tableName.equals(TableEnum.T_FIELD.getTableName())){
|
||||
String organ_id = null;
|
||||
String field_en = null;
|
||||
String field_cn = null;
|
||||
for (CanalEntry.Column column : columns) {
|
||||
String name = column.getName();
|
||||
switch (name) {
|
||||
case "organ_id":
|
||||
organ_id = column.getValue();
|
||||
break;
|
||||
case "field_en":
|
||||
field_en = column.getValue();
|
||||
break;
|
||||
case "field_cn":
|
||||
field_cn = column.getValue();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
String fieldEn = "field_en:" + organ_id + ":" + field_en;
|
||||
String fieldEnKey = RedisUtils.getPrimaryKey(tableName, fieldEn);
|
||||
|
||||
String fieldCn = "field_cn:" + organ_id + ":" + field_cn;
|
||||
String fieldCnKey = RedisUtils.getPrimaryKey(tableName, fieldCn);
|
||||
|
||||
// 如果field_en或field_cn发生变化,则对应的key为新生成的,需要保存所有字段缓存
|
||||
Optional<CanalEntry.Column> fieldEnOptional = columns.stream().filter(item -> item.getName().equals("field_en") && item.getUpdated()).findFirst();
|
||||
Optional<CanalEntry.Column> fieldCnOptional = columns.stream().filter(item -> item.getName().equals("field_cn") && item.getUpdated()).findFirst();
|
||||
for (CanalEntry.Column column : columns) {
|
||||
if(fieldEnOptional.isPresent()){
|
||||
// 更新所有字段缓存
|
||||
setAllColumnCache(column, fieldEnKey);
|
||||
} else {
|
||||
// 更新发生改变的字段缓存
|
||||
setUpdatedColumnCache(column, fieldEnKey, null);
|
||||
}
|
||||
|
||||
if(fieldCnOptional.isPresent()){
|
||||
setAllColumnCache(column, fieldCnKey);
|
||||
} else {
|
||||
setUpdatedColumnCache(column, fieldCnKey, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.fibo.ddp.enginex.runner.ksession;
|
||||
|
||||
import com.fibo.ddp.common.service.redis.RedisManager;
|
||||
import org.apache.commons.pool2.BaseKeyedPooledObjectFactory;
|
||||
import org.apache.commons.pool2.PooledObject;
|
||||
import org.apache.commons.pool2.impl.DefaultPooledObject;
|
||||
import org.drools.KnowledgeBase;
|
||||
import org.drools.KnowledgeBaseFactory;
|
||||
import org.drools.builder.*;
|
||||
import org.drools.io.ResourceFactory;
|
||||
import org.drools.runtime.StatefulKnowledgeSession;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* kSession工厂类
|
||||
*/
|
||||
@Component
|
||||
public class KSessionFactory extends BaseKeyedPooledObjectFactory<String, StatefulKnowledgeSession> {
|
||||
|
||||
@Autowired
|
||||
private RedisManager redisManager;
|
||||
|
||||
@Override
|
||||
public StatefulKnowledgeSession create(String key) throws Exception {
|
||||
StatefulKnowledgeSession kSession = null;
|
||||
try {
|
||||
String ruleString = redisManager.get(key);
|
||||
if(ruleString == null){
|
||||
throw new Exception("create kSession fail, key is "+ key + ", ruleString is null!");
|
||||
}
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
KnowledgeBuilder kb = KnowledgeBuilderFactory.newKnowledgeBuilder();
|
||||
kb.add(ResourceFactory.newByteArrayResource(ruleString.getBytes("utf-8")), ResourceType.DRL);
|
||||
KnowledgeBuilderErrors errors = kb.getErrors();
|
||||
for (KnowledgeBuilderError error : errors) {
|
||||
System.out.println(error);
|
||||
}
|
||||
KnowledgeBase kBase = KnowledgeBaseFactory.newKnowledgeBase();
|
||||
kBase.addKnowledgePackages(kb.getKnowledgePackages());
|
||||
kSession = kBase.newStatefulKnowledgeSession();
|
||||
long end = System.currentTimeMillis();
|
||||
System.out.println("------------------drools kSession创建耗时:" + (end - start) + " ----------------------");
|
||||
} catch (Exception e) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
return kSession;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PooledObject<StatefulKnowledgeSession> wrap(StatefulKnowledgeSession kSession) {
|
||||
return new DefaultPooledObject<StatefulKnowledgeSession>(kSession);
|
||||
}
|
||||
|
||||
public void setRedisManager(RedisManager redisManager) {
|
||||
this.redisManager = redisManager;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.fibo.ddp.enginex.runner.ksession;
|
||||
|
||||
import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
|
||||
import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
|
||||
import org.drools.runtime.StatefulKnowledgeSession;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* kSession连接池
|
||||
*/
|
||||
@Component
|
||||
public class KSessionPool implements InitializingBean {
|
||||
|
||||
private GenericKeyedObjectPool<String, StatefulKnowledgeSession> pool;
|
||||
|
||||
@Autowired
|
||||
private KSessionFactory kSessionFactory;
|
||||
|
||||
/**
|
||||
* 初始化方法
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
initPool();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化连接池
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public void initPool() throws Exception {
|
||||
GenericKeyedObjectPoolConfig poolConfig = new GenericKeyedObjectPoolConfig();
|
||||
poolConfig.setMaxTotalPerKey(200);
|
||||
poolConfig.setMaxIdlePerKey(50);
|
||||
poolConfig.setMinIdlePerKey(5);
|
||||
poolConfig.setMaxTotal(2000);
|
||||
this.pool = new GenericKeyedObjectPool(kSessionFactory, poolConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一个连接对象
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public StatefulKnowledgeSession borrowObject(String key) throws Exception {
|
||||
return pool.borrowObject(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 归还一个连接对象
|
||||
* @param ftpClient
|
||||
*/
|
||||
public void returnObject(String key, StatefulKnowledgeSession kSession) {
|
||||
if(kSession != null){
|
||||
pool.returnObject(key, kSession);
|
||||
}
|
||||
}
|
||||
|
||||
public void setkSessionFactory(KSessionFactory kSessionFactory) {
|
||||
this.kSessionFactory = kSessionFactory;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.fibo.ddp.enginex.runner.node;
|
||||
|
||||
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 引擎节点执行
|
||||
*/
|
||||
public interface EngineRunnerNode {
|
||||
|
||||
/**
|
||||
* 获取节点所需的指标
|
||||
* @param engineNode
|
||||
* @param inputParam
|
||||
*/
|
||||
void getNodeField(EngineNode engineNode, Map<String, Object> inputParam);
|
||||
|
||||
/**
|
||||
* 执行节点逻辑
|
||||
* @param engineNode
|
||||
* @param inputParam
|
||||
* @param outMap
|
||||
*/
|
||||
void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.fibo.ddp.enginex.runner.node.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
|
||||
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 聚合节点
|
||||
*/
|
||||
@Service
|
||||
public class AggregationNode implements EngineRunnerNode {
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Override
|
||||
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
|
||||
logger.info("start【执行聚合节点】AggregationNode.runNode engineNode:{},inputParam:{},outMap:{}"
|
||||
, JSONObject.toJSONString(engineNode), JSONObject.toJSONString(inputParam), JSONObject.toJSONString(outMap));
|
||||
|
||||
// 直接返回下一个节点
|
||||
outMap.put("nextNode", engineNode.getNextNodes());
|
||||
if (engineNode != null && engineNode.getSnapshot() != null) {
|
||||
outMap.put("nodeSnapshot", engineNode.getSnapshot());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,286 @@
|
||||
package com.fibo.ddp.enginex.runner.node.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.fibo.ddp.common.dao.datax.datamanage.CustListMapper;
|
||||
import com.fibo.ddp.common.dao.datax.datamanage.FieldMapper;
|
||||
import com.fibo.ddp.common.dao.strategyx.listlibrary.TblColumnMapper;
|
||||
import com.fibo.ddp.common.model.datax.datamanage.Field;
|
||||
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
|
||||
import com.fibo.ddp.common.model.strategyx.listlibrary.ListDb;
|
||||
import com.fibo.ddp.common.model.strategyx.listlibrary.TblColumn;
|
||||
import com.fibo.ddp.common.model.strategyx.strategyout.StrategyOutput;
|
||||
import com.fibo.ddp.common.service.common.runner.RunnerSessionManager;
|
||||
import com.fibo.ddp.common.service.common.runner.SessionData;
|
||||
import com.fibo.ddp.common.service.datax.runner.CommonService;
|
||||
import com.fibo.ddp.common.service.datax.runner.ExecuteUtils;
|
||||
import com.fibo.ddp.common.service.strategyx.listlibrary.ListDbService;
|
||||
import com.fibo.ddp.common.service.strategyx.strategyout.StrategyOutputService;
|
||||
import com.fibo.ddp.common.utils.constant.strategyx.StrategyType;
|
||||
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
public class BlackOrWhiteNode implements EngineRunnerNode {
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Autowired
|
||||
private CommonService commonService;
|
||||
@Autowired
|
||||
private TblColumnMapper tblColumnMapper;
|
||||
@Resource
|
||||
private ListDbService listDbService;
|
||||
@Resource
|
||||
public FieldMapper fieldMapper;
|
||||
@Resource
|
||||
public CustListMapper custListMapper;
|
||||
@Resource
|
||||
private StrategyOutputService outputService;
|
||||
|
||||
private List<Long> getExecuteVersionIdList(EngineNode engineNode) {
|
||||
return ExecuteUtils.getExecuteIdList(engineNode, "listDbId");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
|
||||
List<Long> list = getExecuteVersionIdList(engineNode);
|
||||
List<Long> fieldIds = new ArrayList<>();
|
||||
for (Long l : list) {
|
||||
fieldIds.addAll(listDbService.getNodeFieldIds(l));
|
||||
}
|
||||
commonService.getFieldByIds(fieldIds, inputParam);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
|
||||
//监控中心-节点信息快照记录
|
||||
if(engineNode!=null && engineNode.getNodeJson()!=null){
|
||||
outMap.put("nodeSnapshot",engineNode.getNodeJson());
|
||||
}
|
||||
inputParam.put("nodeId", engineNode.getNodeId());
|
||||
inputParam.put("nodeName", engineNode.getNodeName());
|
||||
JSONObject nodeInfo = new JSONObject();
|
||||
nodeInfo.put("engineNode", engineNode);
|
||||
nodeInfo.put("nodeId", engineNode.getNodeId());
|
||||
nodeInfo.put("nodeName", engineNode.getNodeName());
|
||||
nodeInfo.put("nodeType", engineNode.getNodeType());
|
||||
outMap.put("nodeInfo", nodeInfo);
|
||||
//新代码
|
||||
String hitKey = "" + engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_size";
|
||||
List<Long> list = getExecuteVersionIdList(engineNode);
|
||||
List<ListDb> hitListDb = new ArrayList<>();
|
||||
//创建内部多选的名单库结果数组
|
||||
JSONArray resultJsonArray = new JSONArray();
|
||||
JSONArray strategySnapshot = new JSONArray();
|
||||
for (Long id : list) {
|
||||
ListDb listDb = listDbService.queryById(id);
|
||||
//监控中心 == 策略层面快照信息
|
||||
if (listDb != null && listDb.getSnapshot() != null) {
|
||||
strategySnapshot.add(listDb.getSnapshot());
|
||||
}
|
||||
boolean isfalg = this.executeListDb(listDb, inputParam, outMap,resultJsonArray);
|
||||
if (isfalg) {
|
||||
hitListDb.add(listDb);
|
||||
}
|
||||
}
|
||||
//监控中心==》策略层面快照信息记录
|
||||
outMap.put("strategySnapshot",strategySnapshot);
|
||||
//构造节点信息
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("nodeId", engineNode.getNodeId());
|
||||
jsonObject.put("nodeName", engineNode.getNodeName());
|
||||
jsonObject.put("resultList", resultJsonArray);
|
||||
|
||||
//判断是否出现过同类型的,如果出现过则获取并且增加内容,如果没有则需要构建名单库类型的节点信息
|
||||
if (outMap.containsKey("blackJson")) {
|
||||
//如果出现过黑名单则从黑名单接送中获取
|
||||
JSONObject blackJson = (JSONObject) outMap.get("blackJson");
|
||||
JSONArray resultJson = blackJson.getJSONArray("resultJson");
|
||||
resultJson.add(jsonObject);
|
||||
} else {
|
||||
JSONObject nodeResult = new JSONObject();
|
||||
nodeResult.put("resultType", 5);
|
||||
JSONArray resultJson = new JSONArray();
|
||||
resultJson.add(jsonObject);
|
||||
nodeResult.put("resultJson",resultJson);
|
||||
outMap.put("blackJson", nodeResult);
|
||||
}
|
||||
|
||||
// nodeResult.put("resultJson", resultJsonArray);
|
||||
// outMap.put("blackJson", nodeResult);
|
||||
// outMap.put("nodeResult", nodeResult);
|
||||
inputParam.put(hitKey, hitListDb.size());
|
||||
//处理终止条件判断中选择的名单库
|
||||
long count = handlerResultCount(engineNode, hitListDb);
|
||||
this.terminalCondition(engineNode, inputParam, outMap, count);
|
||||
}
|
||||
|
||||
private boolean executeListDb(ListDb listDb, Map<String, Object> inputParam, Map<String, Object> outMap,JSONArray resultJsonArray) {
|
||||
SessionData sessionData = RunnerSessionManager.getSession();
|
||||
Long organId = sessionData.getOrganId();
|
||||
JSONObject resultJson = new JSONObject();
|
||||
Integer matchs = 0;
|
||||
Integer revMatchs = 0; //模糊查询时反向匹配
|
||||
// JSONArray strategySnopshot = new JSONArray();
|
||||
Long listDbId = listDb.getId();
|
||||
// if (listDb.getSnapshot() != null) {
|
||||
//
|
||||
// strategySnopshot.add(listDb.getSnapshot());
|
||||
// }
|
||||
inputParam.put("listDb", listDb);
|
||||
|
||||
ListDb version = listDb;
|
||||
String queryKeyArray[] = listDb.getQueryField().split(",");
|
||||
if (queryKeyArray.length > 0) {
|
||||
Integer queryType = version.getQueryType();//and(1),or(0)
|
||||
Integer matchType = version.getMatchType();//精确匹配(1),模糊匹配(0)
|
||||
String queryKey = ""; // t1 like '%t1%'
|
||||
String revQueryKey = ""; // 反向模糊匹配 instr('高档洗浴消费',t1) t1行业字段 eg.'洗浴'
|
||||
String tableName = "organ" + "_" + organId + "_" + listDb.getListType() + "_" + listDbId;
|
||||
inputParam.put("tableName", tableName);
|
||||
inputParam.put("schemaName", getDbName());
|
||||
|
||||
//获取名单库的匿名字段与注释的关系
|
||||
List<TblColumn> columnList = tblColumnMapper.getColumnList(inputParam);
|
||||
|
||||
//字段id转匿名字段名,准备待查字段条件
|
||||
Integer loc = 0;
|
||||
List<String> tableColumn = Arrays.asList(version.getTableColumn().split(","));
|
||||
int k = 0;
|
||||
for (int j = 0; j < queryKeyArray.length; j++) {
|
||||
k = tableColumn.indexOf(queryKeyArray[j]);
|
||||
if (k < 0) {
|
||||
continue;
|
||||
}
|
||||
Field field = fieldMapper.selectById(queryKeyArray[j]);
|
||||
String fieldEn = field.getFieldEn(); //age
|
||||
String columnKey = "t" + k;
|
||||
for (TblColumn tblColumn : columnList) {
|
||||
String colName = tblColumn.getColName(); //t5
|
||||
String paramValue = inputParam.get(fieldEn).toString();
|
||||
if (columnKey.equals(colName)) {
|
||||
if (paramValue == null || paramValue.equals("")) {
|
||||
continue ; //数据项缺失导致无法命中,默认返回没命中
|
||||
} else {
|
||||
loc += 1;
|
||||
if (matchType == 1) {
|
||||
if (loc > 1 && queryType == 1) {
|
||||
queryKey += " and ";
|
||||
} else if (loc > 1 && queryType == 0) {
|
||||
queryKey += " or ";
|
||||
}
|
||||
queryKey += colName + " = '" + paramValue + "'";
|
||||
} else if (matchType == 0) { //模糊匹配
|
||||
if (loc > 1 && queryType == 1) {
|
||||
queryKey += " and ";
|
||||
} else if (loc > 1 && queryType == 0) {
|
||||
queryKey += " or ";
|
||||
revQueryKey += " + ";
|
||||
}
|
||||
//正向模糊搜索
|
||||
queryKey += colName + " like " + "'%" + paramValue + "%'"; // t5 like '%36岁%'
|
||||
//反向模糊搜索
|
||||
revQueryKey += "max(instr('" + paramValue + "'," + colName + "))";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
inputParam.put("queryKey", queryKey);
|
||||
inputParam.put("revQueryKey", revQueryKey);
|
||||
}
|
||||
matchs += custListMapper.findByQueryKey(inputParam);
|
||||
if (!"".equals(inputParam.get("revQueryKey"))) {
|
||||
revMatchs = custListMapper.revFindByQueryKey(inputParam);
|
||||
}
|
||||
if (revMatchs == null){
|
||||
revMatchs = 0;
|
||||
}
|
||||
inputParam.put(listDb.getResultFieldEn(), "未命中");
|
||||
List<JSONObject> fieldList = new ArrayList<>();
|
||||
|
||||
JSONObject hitResult = new JSONObject();
|
||||
hitResult.put(listDb.getResultFieldEn(), "未命中");
|
||||
|
||||
// resultJson.put("nodeId", inputParam.get("nodeId").toString());
|
||||
// resultJson.put("nodeName", inputParam.get("nodeName").toString());
|
||||
resultJson.put("listDbId", listDb.getId());
|
||||
resultJson.put("listDbName", listDb.getListName());
|
||||
resultJson.put("listDbType", listDb.getListType());
|
||||
if (null != listDb.getListDesc()) {
|
||||
resultJson.put("desc", listDb.getListDesc());
|
||||
}
|
||||
resultJson.put("fieldList", fieldList);
|
||||
resultJsonArray.add(resultJson);
|
||||
if (matchs + revMatchs > 0) {
|
||||
inputParam.put(listDb.getResultFieldEn(), "命中");
|
||||
hitResult.put(listDb.getResultFieldEn(), "命中");
|
||||
List<JSONObject> jsonObjects = outputService.setOutput(new StrategyOutput(Long.valueOf(listDbId.toString()), StrategyType.LIST_DB), inputParam);
|
||||
fieldList.add(hitResult);
|
||||
fieldList.addAll(jsonObjects);
|
||||
// outMap.put("black", listDb);
|
||||
return true;
|
||||
} else {
|
||||
fieldList.add(hitResult);
|
||||
}
|
||||
|
||||
//监控中心==》策略层面记录策略的快照信息
|
||||
// JSONObject strategyObject = new JSONObject();
|
||||
// strategyObject.put("strategySnopshot", strategySnopshot);
|
||||
// outMap.put("strategySnopshot", strategyObject);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据传入数据监测是否命中黑名单
|
||||
*
|
||||
* @param paramMap
|
||||
* @return
|
||||
* @see
|
||||
*/
|
||||
public boolean findByQueryKey(Map<String, Object> paramMap, Map<String, Object> outmap, Integer type, EngineNode engineNode) {
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private String getDbName() {
|
||||
return "riskmanage";
|
||||
}
|
||||
|
||||
private long handlerResultCount(EngineNode engineNode,List<ListDb> hitListDb){
|
||||
JSONObject jsonObject = JSON.parseObject(engineNode.getNodeJson());
|
||||
JSONArray selectedRule = jsonObject.getJSONObject("terminationInfo").getJSONArray("selectedRule");
|
||||
List<Long> selectedListDbIds = new ArrayList<>();
|
||||
if (selectedRule!=null&&selectedRule.size()>0){
|
||||
for (Object o : selectedRule) {
|
||||
if (o==null){
|
||||
continue;
|
||||
}
|
||||
Long id = JSON.parseObject(JSON.toJSONString(o)).getLong("id");
|
||||
if (id==null){
|
||||
continue;
|
||||
}
|
||||
selectedListDbIds.add(id);
|
||||
}
|
||||
}
|
||||
long count = hitListDb.stream().filter(item -> selectedListDbIds.contains(item.getId())).count();
|
||||
return count;
|
||||
}
|
||||
|
||||
private void terminalCondition(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap, Object executeResult) {
|
||||
String sizeKey = engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_terminal_size";
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put(sizeKey, executeResult);
|
||||
ExecuteUtils.terminalCondition(engineNode, inputParam, outMap, map);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.fibo.ddp.enginex.runner.node.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
|
||||
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 冠军挑战节点
|
||||
*/
|
||||
@Service
|
||||
public class ChampionChallengeNode implements EngineRunnerNode {
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Override
|
||||
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
|
||||
logger.info("start【执行冠军挑战节点】ChampionChallengeNode.runNode engineNode:{},inputParam:{},outMap:{}"
|
||||
, JSONObject.toJSONString(engineNode), JSONObject.toJSONString(inputParam), JSONObject.toJSONString(outMap));
|
||||
if (engineNode != null && engineNode.getSnapshot() != null) {
|
||||
outMap.put("nodeSnapshot", engineNode.getSnapshot());
|
||||
}
|
||||
JSONArray jsonArray = JSONArray.parseArray(engineNode.getNodeJson());
|
||||
for (int i = 0; i < jsonArray.size(); i++) {
|
||||
JSONObject jsonObject = jsonArray.getJSONObject(i);
|
||||
int champion = jsonObject.getIntValue("champion");
|
||||
// 返回冠军分支对应的下一个节点
|
||||
if(champion == 1){
|
||||
outMap.put("nextNode", jsonObject.getString("nextNode"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.fibo.ddp.enginex.runner.node.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.fibo.ddp.common.model.enginex.risk.Engine;
|
||||
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
|
||||
import com.fibo.ddp.common.service.common.runner.RunnerSessionManager;
|
||||
import com.fibo.ddp.common.service.common.runner.SessionData;
|
||||
import com.fibo.ddp.common.service.enginex.risk.EngineService;
|
||||
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
public class ChildEngineNode implements EngineRunnerNode {
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
// @Autowired
|
||||
// private EngineApiService engineApiService;
|
||||
@Autowired
|
||||
public EngineService engineService;
|
||||
|
||||
@Override
|
||||
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
|
||||
SessionData sessionData = RunnerSessionManager.getSession();
|
||||
Long organId = sessionData.getOrganId();
|
||||
Integer reqType = sessionData.getReqType();
|
||||
Long childEngineId = Long.valueOf(engineNode.getNodeJson());
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
|
||||
map.put("fields",inputParam);
|
||||
map.put("engineId", childEngineId);
|
||||
map.put("organId",organId);
|
||||
map.put("reqType",reqType);
|
||||
// String result = engineApiService.engineApi(map);
|
||||
String result = null;
|
||||
String engineResult = "";
|
||||
JSONObject jsonObject = JSONObject.parseObject(result);
|
||||
if (jsonObject.getString("status").equals("0x0000")&&jsonObject.getString("result")!=null) {
|
||||
engineResult = jsonObject.getString("result");
|
||||
} else {
|
||||
logger.error("子引擎执行失败, childEngineId:{},result:{}", childEngineId, result);
|
||||
}
|
||||
|
||||
Engine engineVo = engineService.getEngineById(childEngineId);
|
||||
//监控中心--节点信息记录(不需要监控策略层面的监控)
|
||||
outMap.put("nodeSnapshot",engineVo);
|
||||
JSONObject nodeInfo = new JSONObject();
|
||||
nodeInfo.put("engineNode",engineNode);
|
||||
nodeInfo.put("nodeId",engineNode.getNodeId());
|
||||
nodeInfo.put("nodeName",engineNode.getNodeName());
|
||||
nodeInfo.put("nodeType",engineNode.getNodeType());
|
||||
outMap.put("nodeInfo",nodeInfo);
|
||||
|
||||
jsonObject.put("nodeId", engineNode.getNodeId());
|
||||
jsonObject.put("nodeName", engineNode.getNodeName());
|
||||
jsonObject.put("engineId", engineVo.getId());
|
||||
jsonObject.put("engineName", engineVo.getName());
|
||||
//监控中心====》输出结果写入Hbase
|
||||
outMap.put("nodeResult",jsonObject);
|
||||
if (outMap.containsKey("childEngineJson")) {
|
||||
JSONArray resultJson = (JSONArray) outMap.get("childEngineJson");
|
||||
resultJson.add(jsonObject);
|
||||
} else {
|
||||
JSONArray resultJson = new JSONArray();
|
||||
resultJson.add(jsonObject);
|
||||
outMap.put("childEngineJson", resultJson);
|
||||
}
|
||||
String key = engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_" + engineNode.getNodeJson() + "_result";
|
||||
inputParam.put(key, engineResult);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package com.fibo.ddp.enginex.runner.node.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
|
||||
import com.fibo.ddp.common.service.datax.runner.CommonService;
|
||||
import com.fibo.ddp.common.utils.util.runner.JevalUtil;
|
||||
import com.fibo.ddp.common.utils.util.runner.jeval.EvaluationException;
|
||||
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 决策选项节点
|
||||
*/
|
||||
@Service
|
||||
public class DecisionOptionsNode implements EngineRunnerNode {
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Autowired
|
||||
private CommonService commonService;
|
||||
|
||||
@Override
|
||||
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
|
||||
logger.info("start【获取决策选项节点指标】DecisionOptionsNode.getNodeField engineNode:{},inputParam:{}", JSONObject.toJSONString(engineNode), JSONObject.toJSONString(inputParam));
|
||||
JSONObject jsonObject = JSONObject.parseObject(engineNode.getNodeScript());
|
||||
JSONArray array = jsonObject.getJSONArray("input");
|
||||
List<Long> ids = new ArrayList<>();
|
||||
for (int i = 0; i < array.size(); i++) {
|
||||
JSONObject input = array.getJSONObject(i);
|
||||
Object fieldId = input.get("field_id");
|
||||
if(fieldId != null && !"".equals(fieldId.toString())){
|
||||
ids.add(Long.valueOf(fieldId.toString()));
|
||||
}
|
||||
}
|
||||
commonService.getFieldByIds(ids, inputParam);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
|
||||
//监控信息--节点信息记录(不需要策略层面的监控)
|
||||
outMap.put("nodeSnapshot",JSON.parseObject(engineNode.getNodeJson()));
|
||||
JSONObject nodeInfo = new JSONObject();
|
||||
nodeInfo.put("engineNode",engineNode);
|
||||
nodeInfo.put("nodeId",engineNode.getNodeId());
|
||||
nodeInfo.put("nodeName",engineNode.getNodeName());
|
||||
nodeInfo.put("nodeType",engineNode.getNodeType());
|
||||
outMap.put("nodeInfo",nodeInfo);
|
||||
JSONObject jsonObject = JSONObject.parseObject(engineNode.getNodeScript());
|
||||
JSONArray inputArray = jsonObject.getJSONArray("input");
|
||||
List<JSONObject> inputList = JSONObject.parseArray(JSONObject.toJSONString(jsonObject.getJSONArray("input")), JSONObject.class);
|
||||
JSONArray conditionArray = jsonObject.getJSONArray("conditions");
|
||||
JSONObject outputJson = jsonObject.getJSONObject("output");
|
||||
|
||||
// 变量值转义
|
||||
Map<String, Object> variablesMap = new HashMap<>();
|
||||
for (int i = 0; i < inputArray.size(); i++) {
|
||||
String input = inputArray.get(i).toString();
|
||||
JSONObject inputField = JSONObject.parseObject(input);
|
||||
String field_code = inputField.getString("field_code");
|
||||
Map<String, Integer> fieldsMap = new HashMap<>();
|
||||
fieldsMap.put(field_code, inputField.getInteger("valueType"));
|
||||
variablesMap.put(field_code, inputParam.get(field_code));
|
||||
variablesMap = JevalUtil.convertVariables(fieldsMap, variablesMap);
|
||||
}
|
||||
|
||||
// 默认值处理
|
||||
String dicisionResult ="";
|
||||
String defaultValue = outputJson.getString("defaultValue");
|
||||
if (StringUtils.isNotBlank(defaultValue)){
|
||||
dicisionResult = defaultValue;
|
||||
}
|
||||
// 决策条件判断
|
||||
if(conditionArray != null && conditionArray.size() > 0){
|
||||
for (int i = 0; i < conditionArray.size(); i++) {
|
||||
JSONObject formulaJson = JSONObject.parseObject(conditionArray.getString(i));
|
||||
try {
|
||||
boolean outfieldvalue = JevalUtil.evaluateBoolean(formulaJson.getString("formula"), variablesMap);
|
||||
if (outfieldvalue) {
|
||||
dicisionResult = formulaJson.getString("result");
|
||||
// 输出结果计算
|
||||
String result = formulaJson.getString("result");
|
||||
if(result.contains("{") && result.contains("}")){
|
||||
String expression = result;
|
||||
Pattern pattern = Pattern.compile("\\{[a-zA-Z0-9_\u4e00-\u9fa5()()-]+\\}");
|
||||
Matcher matcher = pattern.matcher(expression);
|
||||
while (matcher.find()) {
|
||||
String asName = matcher.group(0).replace("{", "").replace("}", "");
|
||||
Optional<JSONObject> inputObj = inputList.stream().filter(item -> asName.equals(item.getString("asName"))).findFirst();
|
||||
if(inputObj.isPresent()){
|
||||
String field_code = inputObj.get().getString("field_code");
|
||||
expression = expression.replaceAll(asName, field_code);
|
||||
}
|
||||
}
|
||||
expression = expression.replaceAll("\\{", "#{");
|
||||
Double calResult = JevalUtil.evaluateNumric(expression, variablesMap);
|
||||
dicisionResult = calResult.toString();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
} catch (EvaluationException e) {
|
||||
e.printStackTrace();
|
||||
logger.error("请求异常", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> outFields = new HashMap<>();
|
||||
String outputFieldCode = outputJson.getString("field_code");
|
||||
outFields.put("fieldId", outputJson.getIntValue("field_id"));
|
||||
outFields.put("fieldName", outputJson.getString("field_name"));
|
||||
outFields.put("fieldCode", outputFieldCode);
|
||||
outFields.put("outValue", dicisionResult);
|
||||
outMap.put("result", dicisionResult);
|
||||
String key = engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_result";
|
||||
inputParam.put(key, dicisionResult);
|
||||
inputParam.put(outputFieldCode, dicisionResult);
|
||||
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("nodeId", engineNode.getNodeId());
|
||||
json.put("nodeName", engineNode.getNodeName());
|
||||
json.put("outFields", JSONObject.parseObject(JSON.toJSONString(outFields)));
|
||||
//监控中心===》hbase中写入结果信息
|
||||
outMap.put("nodeResult",json);
|
||||
if (outMap.containsKey("decisionJson")) {
|
||||
JSONArray resultJson = (JSONArray) outMap.get("decisionJson");
|
||||
resultJson.add(json);
|
||||
} else {
|
||||
JSONArray resultJson = new JSONArray();
|
||||
resultJson.add(json);
|
||||
outMap.put("decisionJson", resultJson);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,385 @@
|
||||
package com.fibo.ddp.enginex.runner.node.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
|
||||
import com.fibo.ddp.common.model.enginex.risk.InputParam;
|
||||
import com.fibo.ddp.common.model.enginex.risk.Result;
|
||||
import com.fibo.ddp.common.model.enginex.runner.ExpressionParam;
|
||||
import com.fibo.ddp.common.model.strategyx.decisiontable.DecisionTablesDetailCondition;
|
||||
import com.fibo.ddp.common.model.strategyx.decisiontable.vo.DecisionTablesDetailVo;
|
||||
import com.fibo.ddp.common.model.strategyx.decisiontable.vo.DecisionTablesResultVo;
|
||||
import com.fibo.ddp.common.model.strategyx.decisiontable.vo.DecisionTablesVersionVo;
|
||||
import com.fibo.ddp.common.model.strategyx.decisiontable.vo.DecisionTablesVo;
|
||||
import com.fibo.ddp.common.service.datax.runner.CommonService;
|
||||
import com.fibo.ddp.common.service.datax.runner.ExecuteUtils;
|
||||
import com.fibo.ddp.common.service.redis.RedisManager;
|
||||
import com.fibo.ddp.common.service.strategyx.decisiontable.DecisionTablesDetailService;
|
||||
import com.fibo.ddp.common.service.strategyx.decisiontable.DecisionTablesService;
|
||||
import com.fibo.ddp.common.service.strategyx.decisiontable.impl.DecisionTablesServiceImpl;
|
||||
import com.fibo.ddp.common.utils.common.MD5;
|
||||
import com.fibo.ddp.common.utils.constant.CommonConst;
|
||||
import com.fibo.ddp.enginex.runner.ksession.KSessionPool;
|
||||
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.drools.runtime.StatefulKnowledgeSession;
|
||||
import org.drools.runtime.rule.FactHandle;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
@Service
|
||||
public class DecisionTablesNode implements EngineRunnerNode {
|
||||
private static final Logger logger = LoggerFactory.getLogger(DecisionTablesServiceImpl.class);
|
||||
|
||||
@Resource
|
||||
private RedisManager redisManager;
|
||||
@Autowired
|
||||
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
|
||||
@Autowired
|
||||
private KSessionPool kSessionPool;
|
||||
@Resource
|
||||
private DecisionTablesService decisionTablesService;
|
||||
@Autowired
|
||||
private DecisionTablesDetailService detailService;
|
||||
@Autowired
|
||||
private CommonService commonService;
|
||||
|
||||
private List<Long> getExecuteVersionIdList(EngineNode engineNode) {
|
||||
return ExecuteUtils.getExecuteIdList(engineNode, "versionId");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
|
||||
try {
|
||||
List<Long> versionIdList = getExecuteVersionIdList(engineNode);
|
||||
//获取决策表节点的字段id
|
||||
List<Long> ids = new ArrayList<>();
|
||||
for (Long versionId : versionIdList) {
|
||||
ids.addAll(detailService.queryFieldIdByDecisionTablesVersionId(versionId));
|
||||
}
|
||||
commonService.getFieldByIds(ids, inputParam);
|
||||
} catch (Exception e) {
|
||||
logger.error("【DecisionTablesNode】,getNodeField:获取决策表指标异常");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
|
||||
//监控中心-节点信息快照记录
|
||||
if (engineNode != null && engineNode.getNodeJson() != null) {
|
||||
outMap.put("nodeSnapshot", engineNode.getNodeJson());
|
||||
}
|
||||
List<Long> versionIdList = getExecuteVersionIdList(engineNode);
|
||||
JSONObject nodeInfo = new JSONObject();
|
||||
nodeInfo.put("engineNode", engineNode);
|
||||
nodeInfo.put("nodeId", engineNode.getNodeId());
|
||||
nodeInfo.put("nodeName", engineNode.getNodeName());
|
||||
nodeInfo.put("nodeType", engineNode.getNodeType());
|
||||
outMap.put("nodeInfo", nodeInfo);
|
||||
JSONArray strategySnapshot = new JSONArray();
|
||||
for (Long versionId : versionIdList) {
|
||||
//获取决策表decisionTablesVo
|
||||
DecisionTablesVo decisionTablesVo = decisionTablesService.queryByVersionId(versionId);
|
||||
//监控中心==策略层面快照信息记录
|
||||
if (decisionTablesVo.getExecuteVersion().getSnapshot() != null) {
|
||||
strategySnapshot.add(decisionTablesVo.getExecuteVersion().getSnapshot());
|
||||
}
|
||||
DecisionTablesVersionVo version = decisionTablesVo.getExecuteVersion();
|
||||
//获取存放决策表执行结果的变量
|
||||
String resultFieldEn = version.getResultFieldEn();
|
||||
//执行决策表
|
||||
Object executeResult = this.executeDecisionTables(version, inputParam);
|
||||
//处理结果
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("nodeId", engineNode.getNodeId());
|
||||
jsonObject.put("nodeName", engineNode.getNodeName());
|
||||
jsonObject.put("decisionTablesId", decisionTablesVo.getId());
|
||||
jsonObject.put("decisionTablesName", decisionTablesVo.getName());
|
||||
jsonObject.put("desc", version.getDescription());
|
||||
jsonObject.put("versionId", version.getId());
|
||||
jsonObject.put("versionCode", version.getVersionCode());
|
||||
if (executeResult != null) {
|
||||
jsonObject.put("result", executeResult);
|
||||
JSONObject resultField = new JSONObject();
|
||||
resultField.put(resultFieldEn, executeResult);
|
||||
//将执行结果按照固定格式存入参数map以供后续节点使用.
|
||||
// inputParam.put("decisionTable_"+decisionTablesId+"_"+engineNode.getNodeId(),executeResult);
|
||||
inputParam.put(resultFieldEn, executeResult);
|
||||
List<JSONObject> fieldList = new ArrayList<>();
|
||||
fieldList.add(resultField);
|
||||
//处理自定义输出
|
||||
List<JSONObject> jsonObjects = decisionTablesService.setOutput(versionId, inputParam);
|
||||
fieldList.addAll(jsonObjects);
|
||||
jsonObject.put("fieldList", fieldList);
|
||||
} else {
|
||||
jsonObject.put("result", "");
|
||||
// inputParam.put("decisionTable_"+decisionTablesId+"_"+engineNode.getNodeId(),"");
|
||||
inputParam.put(resultFieldEn, "");
|
||||
}
|
||||
//将执行结果存入最终返回值
|
||||
if (outMap.containsKey("decisionTablesJson")) {
|
||||
JSONArray resultJson = (JSONArray) outMap.get("decisionTablesJson");
|
||||
resultJson.add(jsonObject);
|
||||
//监控中心==》将执行结果写入Hbase
|
||||
JSONObject nodeResult = new JSONObject();
|
||||
nodeResult.put("result", resultJson);
|
||||
outMap.put("nodeResult", nodeResult);
|
||||
} else {
|
||||
JSONArray resultJson = new JSONArray();
|
||||
resultJson.add(jsonObject);
|
||||
outMap.put("decisionTablesJson", resultJson);
|
||||
//监控中心==》将执行结果写入Hbase
|
||||
JSONObject nodeResult = new JSONObject();
|
||||
nodeResult.put("result", resultJson);
|
||||
outMap.put("nodeResult", nodeResult);
|
||||
}
|
||||
terminalCondition(engineNode, inputParam, outMap, executeResult);
|
||||
}
|
||||
//监控中心==》策略层面快照信息记录
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("snapshot", strategySnapshot);
|
||||
outMap.put("decisionTableStrategy", jsonObject);
|
||||
}
|
||||
|
||||
//执行整个决策表返回决策结果数据
|
||||
public Object executeDecisionTables(DecisionTablesVersionVo versionVo, Map<String, Object> inputParam) {
|
||||
Future<Integer> top = null;
|
||||
Future<Integer> left = null;
|
||||
//取出行列索引
|
||||
Integer row = -1;
|
||||
Integer column = -1;
|
||||
List<DecisionTablesDetailVo> leftDetailVo = versionVo.getLeftDetailVo();
|
||||
if (CollectionUtils.isEmpty(leftDetailVo)
|
||||
|| (leftDetailVo.size() == 1
|
||||
&& StringUtils.isBlank(leftDetailVo.get(0).getFieldEn())
|
||||
&& CollectionUtils.isEmpty(leftDetailVo.get(0).getChildren()))) {
|
||||
row = 0;
|
||||
} else {
|
||||
//左侧执行
|
||||
left = threadPoolTaskExecutor.submit(new Callable<Integer>() {
|
||||
@Override
|
||||
public Integer call() {
|
||||
return executeDecisionTablesDetail(versionVo.getLeftDetailVo(), inputParam);
|
||||
}
|
||||
});
|
||||
}
|
||||
//右侧执行
|
||||
List<DecisionTablesDetailVo> topDetailVo = versionVo.getTopDetailVo();
|
||||
if (CollectionUtils.isEmpty(topDetailVo)
|
||||
|| (topDetailVo.size() == 1
|
||||
&& StringUtils.isBlank(topDetailVo.get(0).getFieldEn())
|
||||
&& CollectionUtils.isEmpty(topDetailVo.get(0).getChildren()))) {
|
||||
column = 0;
|
||||
} else {
|
||||
top = threadPoolTaskExecutor.submit(new Callable<Integer>() {
|
||||
@Override
|
||||
public Integer call() {
|
||||
return executeDecisionTablesDetail(versionVo.getTopDetailVo(), inputParam);
|
||||
}
|
||||
});
|
||||
}
|
||||
try {
|
||||
if (row == -1) {
|
||||
row = left.get();
|
||||
}
|
||||
if (column == -1) {
|
||||
column = top.get();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
//行列值均取到的进行处理
|
||||
if (row >= 0 && column >= 0) {
|
||||
//根据行列去结果集中找结果返回
|
||||
DecisionTablesResultVo resultSet = versionVo.getResultSet();
|
||||
if (row < resultSet.getRows() && column < resultSet.getColumns()) {
|
||||
String resultValue = resultSet.getResultValue();
|
||||
JSONArray array = JSON.parseArray(resultValue);
|
||||
JSONArray rowArray = JSON.parseArray(JSON.toJSONString(array.get(row)));
|
||||
return rowArray.get(column);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//执行决策表的条件获取
|
||||
public Integer executeDecisionTablesDetail(List<DecisionTablesDetailVo> decisionTablesDetailList, Map<String, Object> paramMap) {
|
||||
|
||||
for (DecisionTablesDetailVo decisionTablesDetailVo : decisionTablesDetailList) {
|
||||
//调用drools执行
|
||||
// int result = recursionExecuteDecisionTablesDetail(decisionTablesDetailVo, paramMap);
|
||||
//调用不使用drools执行
|
||||
int result = executeDecisionTablesDetail(decisionTablesDetailVo, paramMap);
|
||||
if (result >= 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//执行决策表详情得出位置坐标:drools执行
|
||||
public int recursionExecuteDecisionTablesDetail(DecisionTablesDetailVo decisionTablesDetailVo, Map<String, Object> paramMap) {
|
||||
StatefulKnowledgeSession kSession = null;
|
||||
String keyMd5 = null;
|
||||
try {
|
||||
//解析content
|
||||
String ruleString = decisionTablesDetailVo.getContent().replace("\\r\\n", "\r\n");
|
||||
ruleString = ruleString.replace("\\t", "\t");
|
||||
keyMd5 = CommonConst.DROOLS_KSESSION_KEY_PREFIX + MD5.GetMD5Code(ruleString);
|
||||
redisManager.set(keyMd5, ruleString, 120);
|
||||
|
||||
//drools执行
|
||||
kSession = kSessionPool.borrowObject(keyMd5);
|
||||
List<Result> resultList = new ArrayList<>();
|
||||
InputParam inputParam = new InputParam();
|
||||
inputParam.setInputParam(paramMap);
|
||||
inputParam.setResult(resultList);
|
||||
FactHandle fact = kSession.insert(inputParam);
|
||||
kSession.fireAllRules();
|
||||
kSession.retract(fact);
|
||||
//获取执行结果对结果进行分析。
|
||||
List<Result> results = inputParam.getResult();
|
||||
Map<String, Object> resultMap = new HashMap<>();
|
||||
if (results != null && results.size() > 0 && results.get(0) != null && results.get(0).getMap() != null) {
|
||||
resultMap = inputParam.getResult().get(0).getMap();
|
||||
}
|
||||
|
||||
//本节点命中后处理
|
||||
if (resultMap.containsKey("result")) {
|
||||
Integer type = decisionTablesDetailVo.getType();
|
||||
List<DecisionTablesDetailVo> children = decisionTablesDetailVo.getChildren();
|
||||
if (type != null) {
|
||||
switch (type) {
|
||||
//普通节点符合,让子节点继续执行。
|
||||
case 1:
|
||||
if (children != null && children.size() > 0) {
|
||||
for (DecisionTablesDetailVo child : children) {
|
||||
int result = this.recursionExecuteDecisionTablesDetail(child, paramMap);
|
||||
if (result >= 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
//叶子节点符合,返回叶子节点的值。
|
||||
case 2:
|
||||
return decisionTablesDetailVo.getIndexValue();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
logger.error("请求异常", e);
|
||||
} finally {
|
||||
if (keyMd5 != null && kSession != null) {
|
||||
kSessionPool.returnObject(keyMd5, kSession);
|
||||
}
|
||||
}
|
||||
//执行至此则不命中。
|
||||
return -1;
|
||||
}
|
||||
|
||||
//不使用drools的执行
|
||||
private int executeDecisionTablesDetail(DecisionTablesDetailVo decisionTablesDetailVo, Map<String, Object> paramMap) {
|
||||
//获取需要执行的条件列表
|
||||
List<DecisionTablesDetailCondition> conditionList = decisionTablesDetailVo.getConditionList();
|
||||
String fieldEn = decisionTablesDetailVo.getFieldEn();
|
||||
String logical = decisionTablesDetailVo.getLogical();
|
||||
boolean result = false;
|
||||
//根据不通关系进行处理
|
||||
switch (logical) {
|
||||
case "||":
|
||||
result = false;
|
||||
for (DecisionTablesDetailCondition condition : conditionList) {
|
||||
ExpressionParam expressionParam = new ExpressionParam();
|
||||
BeanUtils.copyProperties(condition, expressionParam);
|
||||
expressionParam.setFieldEn(fieldEn);
|
||||
try {
|
||||
boolean expressionResult = ExecuteUtils.getExpressionResult(expressionParam, paramMap);
|
||||
if (expressionResult) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}catch (Throwable e){
|
||||
logger.error("【DecisionTablesNode】,runNode执行异常:expressionParam{}",expressionParam);
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "&&":
|
||||
result = true;
|
||||
for (DecisionTablesDetailCondition condition : conditionList) {
|
||||
ExpressionParam expressionParam = new ExpressionParam();
|
||||
BeanUtils.copyProperties(condition, expressionParam);
|
||||
expressionParam.setFieldEn(fieldEn);
|
||||
try {
|
||||
boolean expressionResult = ExecuteUtils.getExpressionResult(expressionParam, paramMap);
|
||||
if (!expressionResult) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}catch (Throwable e){
|
||||
logger.error("【DecisionTablesNode】,runNode执行异常:expressionParam{}",expressionParam);
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
//如果本节点符合则执行后续节点
|
||||
if (result) {
|
||||
Integer type = decisionTablesDetailVo.getType();
|
||||
List<DecisionTablesDetailVo> children = decisionTablesDetailVo.getChildren();
|
||||
if (type != null) {
|
||||
switch (type) {
|
||||
//普通节点符合,让子节点继续执行。
|
||||
case 1:
|
||||
if (children != null && children.size() > 0) {
|
||||
for (DecisionTablesDetailVo child : children) {
|
||||
int executeResult = this.executeDecisionTablesDetail(child, paramMap);
|
||||
if (executeResult >= 0) {
|
||||
return executeResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
//叶子节点符合,返回叶子节点的值。
|
||||
case 2:
|
||||
return decisionTablesDetailVo.getIndexValue();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private void terminalCondition(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap, Object executeResult) {
|
||||
String resultKey = engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_terminal_result";
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put(resultKey, executeResult);
|
||||
ExecuteUtils.terminalCondition(engineNode, inputParam, outMap, map);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
package com.fibo.ddp.enginex.runner.node.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
|
||||
import com.fibo.ddp.common.model.enginex.runner.ExpressionParam;
|
||||
import com.fibo.ddp.common.model.strategyx.decisiontree.DecisionTreeDetail;
|
||||
import com.fibo.ddp.common.model.strategyx.decisiontree.DecisionTreeDetailCondition;
|
||||
import com.fibo.ddp.common.model.strategyx.decisiontree.vo.DecisionTreeVersionVo;
|
||||
import com.fibo.ddp.common.model.strategyx.decisiontree.vo.DecisionTreeVo;
|
||||
import com.fibo.ddp.common.service.datax.runner.CommonService;
|
||||
import com.fibo.ddp.common.service.datax.runner.ExecuteUtils;
|
||||
import com.fibo.ddp.common.service.strategyx.decisiontree.DecisionTreeService;
|
||||
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
public class DecisionTreeNode implements EngineRunnerNode {
|
||||
@Autowired
|
||||
private DecisionTreeService decisionTreeService;
|
||||
@Autowired
|
||||
private CommonService commonService;
|
||||
|
||||
private List<Long> getExecuteVersionIdList(EngineNode engineNode){
|
||||
return ExecuteUtils.getExecuteIdList(engineNode,"versionId");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
|
||||
List<Long> list = getExecuteVersionIdList(engineNode);
|
||||
List<Long> fieldIds = new ArrayList<>();
|
||||
for (Long l : list) {
|
||||
fieldIds.addAll(decisionTreeService.getNodeFieldIds(l));
|
||||
}
|
||||
commonService.getFieldByIds(fieldIds,inputParam);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
|
||||
//监控中心--记录节点快照信息
|
||||
if (engineNode != null && engineNode.getSnapshot() != null) {
|
||||
outMap.put("nodeSnapshot", engineNode.getSnapshot());
|
||||
}
|
||||
List<Long> list = getExecuteVersionIdList(engineNode);
|
||||
JSONObject nodeInfo = new JSONObject();
|
||||
nodeInfo.put("engineNode", engineNode);
|
||||
nodeInfo.put("nodeId", engineNode.getNodeId());
|
||||
nodeInfo.put("nodeName", engineNode.getNodeName());
|
||||
nodeInfo.put("nodeType", engineNode.getNodeType());
|
||||
outMap.put("nodeInfo", nodeInfo);
|
||||
JSONArray strategySnapshot = new JSONArray();
|
||||
for (Long versionId : list) {
|
||||
DecisionTreeVo decisionTreeVo = decisionTreeService.queryExecuteDecisionTree(null, versionId);
|
||||
if (decisionTreeVo == null) {
|
||||
continue;
|
||||
}
|
||||
//监控中心==策略层面快照信息记录
|
||||
if(decisionTreeVo.getExecuteVersion().getSnapshot()!=null){
|
||||
strategySnapshot.add(decisionTreeVo.getExecuteVersion().getSnapshot());
|
||||
}
|
||||
DecisionTreeVersionVo version = decisionTreeVo.getExecuteVersion();
|
||||
String resultFieldEn = version.getResultFieldEn();
|
||||
//执行决策表
|
||||
Object executeResult = this.executeDecisionTree(version, inputParam);
|
||||
//处理结果
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("nodeId", engineNode.getNodeId());
|
||||
jsonObject.put("nodeName", engineNode.getNodeName());
|
||||
jsonObject.put("decisionTreeId", decisionTreeVo.getId());
|
||||
jsonObject.put("decisionTreeName", decisionTreeVo.getName());
|
||||
jsonObject.put("desc", version.getDescription());
|
||||
jsonObject.put("versionId", version.getId());
|
||||
jsonObject.put("versionCode", version.getVersionCode());
|
||||
if (executeResult != null) {
|
||||
jsonObject.put("result", executeResult);
|
||||
JSONObject resultField = new JSONObject();
|
||||
resultField.put(resultFieldEn, executeResult);
|
||||
inputParam.put(resultFieldEn, executeResult);
|
||||
List<JSONObject> fieldList = new ArrayList<>();
|
||||
fieldList.add(resultField);
|
||||
//处理自定义输出
|
||||
List<JSONObject> jsonObjects = decisionTreeService.setOutput(versionId, inputParam);
|
||||
fieldList.addAll(jsonObjects);
|
||||
jsonObject.put("fieldList", fieldList);
|
||||
} else {
|
||||
jsonObject.put("result", "");
|
||||
inputParam.put(resultFieldEn, "");
|
||||
}
|
||||
//将执行结果存入最终返回值
|
||||
if (outMap.containsKey("decisionTreeJson")) {
|
||||
JSONArray resultJson = (JSONArray) outMap.get("decisionTreeJson");
|
||||
resultJson.add(jsonObject);
|
||||
//监控中心==》将执行结果写入Hbase
|
||||
JSONObject nodeResult = new JSONObject();
|
||||
nodeResult.put("result", resultJson);
|
||||
outMap.put("nodeResult", nodeResult);
|
||||
} else {
|
||||
JSONArray resultJson = new JSONArray();
|
||||
resultJson.add(jsonObject);
|
||||
outMap.put("decisionTreeJson", resultJson);
|
||||
//监控中心==》将执行结果写入Hbase
|
||||
JSONObject nodeResult = new JSONObject();
|
||||
nodeResult.put("result", resultJson);
|
||||
outMap.put("nodeResult", nodeResult);
|
||||
}
|
||||
terminalCondition(engineNode,inputParam,outMap,executeResult);
|
||||
}
|
||||
//监控中心==》策略层面快照信息记录
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("snapshot",strategySnapshot);
|
||||
outMap.put("decisionTreeStrategy",jsonObject);
|
||||
}
|
||||
|
||||
private Object executeDecisionTree(DecisionTreeVersionVo version, Map<String, Object> inputParam) {
|
||||
List<DecisionTreeDetail> detailList = version.getDetailList();
|
||||
for (DecisionTreeDetail decisionTreeDetail : detailList) {
|
||||
Object o = executeDecisionTreeDetail(decisionTreeDetail, inputParam);
|
||||
if (o != null) {
|
||||
return o;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Object executeDecisionTreeDetail(DecisionTreeDetail detail, Map<String, Object> paramMap) {
|
||||
//获取需要执行的条件列表
|
||||
List<DecisionTreeDetailCondition> conditionList = detail.getConditionList();
|
||||
String fieldEn = detail.getFieldEn();
|
||||
String logical = detail.getLogical();
|
||||
boolean result = false;
|
||||
//根据不通关系进行处理
|
||||
switch (logical) {
|
||||
case "||":
|
||||
result = false;
|
||||
for (DecisionTreeDetailCondition condition : conditionList) {
|
||||
ExpressionParam expressionParam = new ExpressionParam();
|
||||
BeanUtils.copyProperties(condition, expressionParam);
|
||||
expressionParam.setFieldEn(fieldEn);
|
||||
boolean expressionResult = ExecuteUtils.getExpressionResult(expressionParam, paramMap);
|
||||
if (expressionResult) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "&&":
|
||||
result = true;
|
||||
for (DecisionTreeDetailCondition condition : conditionList) {
|
||||
ExpressionParam expressionParam = new ExpressionParam();
|
||||
BeanUtils.copyProperties(condition, expressionParam);
|
||||
expressionParam.setFieldEn(fieldEn);
|
||||
boolean expressionResult = ExecuteUtils.getExpressionResult(expressionParam, paramMap);
|
||||
if (!expressionResult) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
//如果本节点符合则执行后续节点
|
||||
if (result) {
|
||||
Integer type = detail.getNodeType();
|
||||
List<DecisionTreeDetail> children = detail.getChildren();
|
||||
if (type == null) {
|
||||
if (children == null || children.isEmpty()) {
|
||||
type = 2;
|
||||
} else {
|
||||
type = 1;
|
||||
}
|
||||
}
|
||||
if (type != null) {
|
||||
switch (type) {
|
||||
//普通节点符合,让子节点继续执行。
|
||||
case 1:
|
||||
if (children != null && children.size() > 0) {
|
||||
for (DecisionTreeDetail child : children) {
|
||||
Object executeResult = this.executeDecisionTreeDetail(child, paramMap);
|
||||
if (executeResult != null) {
|
||||
return executeResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
//叶子节点符合,返回叶子节点的值。
|
||||
case 2:
|
||||
String resultStr = detail.getResultValue();
|
||||
Object resultValue = resultStr;
|
||||
Integer variableType = detail.getVariableType();
|
||||
if (variableType == 2) {
|
||||
resultValue = ExecuteUtils.getObjFromMap(paramMap, resultStr);
|
||||
} else if (variableType == 3) {
|
||||
resultValue = ExecuteUtils.getObjFromScript(paramMap, resultStr);
|
||||
}
|
||||
return resultValue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private void terminalCondition(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap,Object executeResult) {
|
||||
String resultKey = engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_terminal_result";
|
||||
Map<String,Object> map = new HashMap<>();
|
||||
map.put(resultKey,executeResult);
|
||||
ExecuteUtils.terminalCondition(engineNode,inputParam,outMap, map);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package com.fibo.ddp.enginex.runner.node.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
|
||||
import com.fibo.ddp.common.service.datax.runner.CommonService;
|
||||
import com.fibo.ddp.common.utils.constant.CommonConst;
|
||||
import com.fibo.ddp.common.utils.util.runner.JevalUtil;
|
||||
import com.fibo.ddp.common.utils.util.runner.jeval.EvaluationException;
|
||||
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
public class GroupNode implements EngineRunnerNode {
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Autowired
|
||||
private CommonService commonService;
|
||||
|
||||
@Override
|
||||
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
|
||||
logger.info("start【获取分组节点指标】GroupNode.getNodeField engineNode:{},inputParam:{}", JSONObject.toJSONString(engineNode), JSONObject.toJSONString(inputParam));
|
||||
JSONObject jsonObject = JSONObject.parseObject(engineNode.getNodeScript());
|
||||
JSONArray array = jsonObject.getJSONArray("fields");
|
||||
List<Long> ids = new ArrayList<>();
|
||||
for (int i = 0; i < array.size(); i++) {
|
||||
JSONObject input = array.getJSONObject(i);
|
||||
Object fieldId = input.get("fieldId");
|
||||
if(fieldId != null && !"".equals(fieldId.toString())){
|
||||
ids.add(Long.valueOf(fieldId.toString()));
|
||||
}
|
||||
}
|
||||
commonService.getFieldByIds(ids, inputParam);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
|
||||
JSONObject jsonScript = JSONObject.parseObject(engineNode.getNodeScript());
|
||||
//监控中心--节点信息记录(不需要策略层面的监控)
|
||||
outMap.put("nodeSnapshot",JSONObject.parse(engineNode.getNodeJson()));
|
||||
JSONObject nodeInfo = new JSONObject();
|
||||
nodeInfo.put("engineNode",engineNode);
|
||||
nodeInfo.put("nodeId",engineNode.getNodeId());
|
||||
nodeInfo.put("nodeName",engineNode.getNodeName());
|
||||
nodeInfo.put("nodeType",engineNode.getNodeType());
|
||||
outMap.put("nodeInfo",nodeInfo);
|
||||
try {
|
||||
String nextNode = handleClassify(jsonScript, inputParam);
|
||||
outMap.put("nextNode", nextNode);
|
||||
JSONObject result = new JSONObject();
|
||||
result.put("nodeResult",nextNode);
|
||||
outMap.put("nodeResult",result);
|
||||
} catch (EvaluationException e) {
|
||||
e.printStackTrace();
|
||||
logger.error("请求异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String handleClassify(JSONObject jsonScript, Map<String, Object> inputParam) throws EvaluationException {
|
||||
JSONArray conditions = jsonScript.getJSONArray("conditions");
|
||||
JSONArray fields = jsonScript.getJSONArray("fields");
|
||||
Map<String, Object> variablesMap = new HashMap<>();
|
||||
variablesMap.putAll(inputParam);
|
||||
Map<String, Integer> fieldsMap = new HashMap<>();
|
||||
for(int i = 0; i < fields.size(); i++){
|
||||
JSONObject jsonObject = fields.getJSONObject(i);
|
||||
fieldsMap.put(jsonObject.getString("fieldCode"), jsonObject.getIntValue("valueType"));
|
||||
}
|
||||
JevalUtil.convertVariables(fieldsMap, variablesMap);
|
||||
|
||||
String nextNode = "";
|
||||
if (conditions == null || conditions.isEmpty()) {
|
||||
//TODO 如果为空,如何处理
|
||||
return nextNode;
|
||||
} else {
|
||||
int size = conditions.size();
|
||||
boolean flag = false;
|
||||
JSONObject formula = null;
|
||||
for (int i = 0; i < size; i++) {
|
||||
formula = conditions.getJSONObject(i);
|
||||
//公式为空,则为else条件分支
|
||||
if (CommonConst.STRING_EMPTY.equals(formula.getString("formula"))) {
|
||||
//else条件
|
||||
if (nextNode.equals(CommonConst.STRING_EMPTY)) {
|
||||
nextNode = formula.getString("nextNode");
|
||||
}
|
||||
} else {
|
||||
//正常条件分支
|
||||
flag = JevalUtil.evaluateBoolean(formula.getString("formula"), variablesMap);
|
||||
if (flag) {
|
||||
nextNode = formula.getString("nextNode");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nextNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
package com.fibo.ddp.enginex.runner.node.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
|
||||
import com.fibo.ddp.common.service.datax.runner.CommonService;
|
||||
import com.fibo.ddp.common.service.datax.runner.ExecuteUtils;
|
||||
import com.fibo.ddp.common.service.strategyx.listlibrary.ListDbService;
|
||||
import com.fibo.ddp.common.utils.constant.enginex.NodeTypeEnum;
|
||||
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ListDbNode implements EngineRunnerNode {
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Autowired
|
||||
private CommonService commonService;
|
||||
|
||||
@Resource
|
||||
private ListDbService listDbService;
|
||||
|
||||
private List<Long> getExecuteVersionIdList(EngineNode engineNode){
|
||||
return ExecuteUtils.getExecuteIdList(engineNode,"versionId");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
|
||||
List<Long> list = getExecuteVersionIdList(engineNode);
|
||||
List<Long> fieldIds = new ArrayList<>();
|
||||
for (Long l : list) {
|
||||
fieldIds.addAll(listDbService.getNodeFieldIds(l));
|
||||
}
|
||||
commonService.getFieldByIds(fieldIds,inputParam);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
|
||||
//监控中心--节点信息快照记录,主要用于监控中心节点信息配置页面显示
|
||||
JSONObject snapshot = new JSONObject();
|
||||
snapshot.put("snapshot",engineNode.getSnapshot());
|
||||
outMap.put("nodeSnapshot",snapshot);
|
||||
inputParam.put("nodeId", engineNode.getNodeId());
|
||||
inputParam.put("nodeName", engineNode.getNodeName());
|
||||
JSONObject nodeInfo = new JSONObject();
|
||||
nodeInfo.put("engineNode",engineNode);
|
||||
nodeInfo.put("nodeId",engineNode.getNodeId());
|
||||
nodeInfo.put("nodeName",engineNode.getNodeName());
|
||||
nodeInfo.put("nodeType",engineNode.getNodeType());
|
||||
outMap.put("nodeInfo",nodeInfo);
|
||||
int type = 0;
|
||||
if(engineNode.getNodeType() == NodeTypeEnum.BLACKLIST.getValue()){
|
||||
type = 1;
|
||||
} else if(engineNode.getNodeType() == NodeTypeEnum.WHITELIST.getValue()){
|
||||
type = 2;
|
||||
}
|
||||
boolean isfalg = this.findByQueryKey(inputParam, outMap, type,engineNode);
|
||||
if (isfalg) {
|
||||
if (type == 1) {
|
||||
outMap.put("isBlack", "true");
|
||||
outMap.put("enginefalg", "true");
|
||||
// engineNode.setNextNodes(null);
|
||||
} else {
|
||||
outMap.put("isWhite", "true");
|
||||
outMap.put("engineWhite", "true");
|
||||
// engineNode.setNextNodes(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据传入数据监测是否命中黑名单
|
||||
*
|
||||
* @param paramMap
|
||||
* @return
|
||||
* @see
|
||||
*/
|
||||
public boolean findByQueryKey(Map<String, Object> paramMap, Map<String, Object> outmap, Integer type,EngineNode engineNode) {
|
||||
// SessionData sessionData = SessionManager.getSession();
|
||||
// Long organId = sessionData.getOrganId();
|
||||
// JSONObject blackandWhite = new JSONObject();
|
||||
// JSONObject resultJson = new JSONObject();
|
||||
// //传递nodeId
|
||||
// String strlistDbIds = null;
|
||||
// if (!paramMap.get("nodeId").equals("0")) {
|
||||
// NodeListDb nodeListDb = nodeListDbMapper.findByNodeId(paramMap);
|
||||
// strlistDbIds = nodeListDb.getInnerListdbs();
|
||||
// //节点配置信息快照,hbase入库用
|
||||
//// JSONObject bwNodeSnopshot = new JSONObject();
|
||||
//// String strListDbIdsOut = nodeListDb.getOuterListdbs();
|
||||
//// if(strListDbIdsOut!=null && strListDbIdsOut.length()>0){
|
||||
//// bwNodeSnopshot.put("outerIdList",strListDbIdsOut.split(","));
|
||||
//// }
|
||||
// //循环处理所有内部黑/白名单库
|
||||
// String[] arraylistDBIds = null;
|
||||
// Integer matchs = 0;
|
||||
// Integer revMatchs = 0; //模糊查询时反向匹配
|
||||
// if (strlistDbIds.length() > 0) {
|
||||
// arraylistDBIds = strlistDbIds.split(",");
|
||||
//// bwNodeSnopshot.put("innerIdList",arraylistDBIds);
|
||||
//// outmap.put("nodeSnapshot",bwNodeSnopshot);
|
||||
// String hitKey = ""+engineNode.getNodeType()+"_"+engineNode.getNodeId()+"_size";
|
||||
// int hitSize = 0;
|
||||
// JSONArray strategySnopshot = new JSONArray();
|
||||
// for (int i = 0; i < arraylistDBIds.length; i++) {
|
||||
// HashMap<String, Object> param1 = new HashMap<String, Object>();
|
||||
// param1.put("organId", organId);
|
||||
// Integer listDbId = Integer.valueOf(arraylistDBIds[i]).intValue();
|
||||
// param1.put("listDbId", listDbId);
|
||||
// ListDb listDb = new ListDb();
|
||||
//// listDb = listDbService.findListDbByIdandByorganId(param1);
|
||||
// //监控中心--策略层面记录名单库快照信息
|
||||
// if(listDb.getSnapshot()!=null){
|
||||
// strategySnopshot.add(listDb.getSnapshot());
|
||||
// }
|
||||
// paramMap.put("listDb", listDb);
|
||||
// String listType = listDb.getListType();
|
||||
// String queryKeyArray[] = listDb.getQueryField().split(",");
|
||||
// if (queryKeyArray.length > 0) {
|
||||
// Integer queryType = listDb.getQueryType();//and(1),or(0)
|
||||
// Integer matchType = listDb.getMatchType();//精确匹配(1),模糊匹配(0)
|
||||
//
|
||||
// String queryKey = ""; // t1 like '%t1%'
|
||||
// String revQueryKey = ""; // 反向模糊匹配 instr('高档洗浴消费',t1) t1行业字段 eg.'洗浴'
|
||||
// String tableName = "organ" + "_" + organId + "_" + listType + "_" + listDbId;
|
||||
// paramMap.put("tableName", tableName);
|
||||
// paramMap.put("schemaName", getDbName());
|
||||
//
|
||||
// //获取名单库的匿名字段与注释的关系
|
||||
// List<TblColumn> columnList = tblColumnMapper.getColumnList(paramMap);
|
||||
//
|
||||
// //字段id转匿名字段名,准备待查字段条件
|
||||
// Integer loc = 0;
|
||||
//
|
||||
// for (int j = 0; j < queryKeyArray.length; j++) {
|
||||
//
|
||||
// HashMap<String, Object> inputParam = new HashMap<String, Object>();
|
||||
// inputParam.put("id", queryKeyArray[j]);
|
||||
// inputParam.put("organId", organId);
|
||||
// inputParam.put("engineId", null);
|
||||
// //id(3)-field(age)
|
||||
// Field field = fieldMapper.findByFieldIdbyorganId(inputParam);
|
||||
// String fieldEn = field.getFieldEn(); //age
|
||||
//
|
||||
// for (TblColumn tblColumn : columnList) {
|
||||
//
|
||||
// String colComment = tblColumn.getColComment(); //age
|
||||
// String colName = tblColumn.getColName(); //t5
|
||||
// String paramValue =paramMap.get(fieldEn).toString();
|
||||
//
|
||||
// if (colName.startsWith("t") && queryKeyArray[j].equals(colComment)) {
|
||||
//
|
||||
// if (paramValue == null || paramValue.equals("")) {
|
||||
// return false; //数据项缺失导致无法命中,默认返回没命中
|
||||
// } else {
|
||||
// loc += 1;
|
||||
// if (matchType == 1) {
|
||||
// if (loc > 1 && queryType == 1) {
|
||||
// queryKey += " and ";
|
||||
// } else if (loc > 1 && queryType == 0) {
|
||||
// queryKey += " or ";
|
||||
// }
|
||||
// queryKey += colName + " = '" + paramValue + "'";
|
||||
// } else if (matchType == 0) { //模糊匹配
|
||||
// if (loc > 1 && queryType == 1) {
|
||||
// queryKey += " and ";
|
||||
// } else if (loc > 1 && queryType == 0) {
|
||||
// queryKey += " or ";
|
||||
// revQueryKey += " + ";
|
||||
// }
|
||||
// //正向模糊搜索
|
||||
// queryKey += colName + " like " + "'%" + paramValue + "%'"; // t5 like '%36岁%'
|
||||
// //反向模糊搜索
|
||||
// revQueryKey += "max(instr('" + paramValue + "'," + colName + "))";
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// paramMap.put("queryKey", queryKey);
|
||||
// paramMap.put("revQueryKey", revQueryKey);
|
||||
// }
|
||||
// matchs += custListMapper.findByQueryKey(paramMap);
|
||||
// if (!paramMap.get("revQueryKey").equals("")) {
|
||||
// revMatchs = custListMapper.revFindByQueryKey(paramMap);
|
||||
// }
|
||||
// if (revMatchs == null)
|
||||
// revMatchs = 0;
|
||||
//
|
||||
// paramMap.put(listDb.getResultFieldEn(),"未命中");
|
||||
// List<JSONObject> fieldList = new ArrayList<>();
|
||||
//
|
||||
// JSONObject hitResult = new JSONObject();
|
||||
// hitResult.put(listDb.getResultFieldEn(),"未命中");
|
||||
// if (matchs + revMatchs > 0) {
|
||||
// resultJson.put("nodeId", paramMap.get("nodeId").toString());
|
||||
// resultJson.put("nodeName", paramMap.get("nodeName").toString());
|
||||
// resultJson.put("status", "0x0000");
|
||||
// paramMap.put(listDb.getResultFieldEn(),"命中");
|
||||
// hitResult.put(listDb.getResultFieldEn(),"命中");
|
||||
// hitSize++;
|
||||
// List<JSONObject> jsonObjects = outputService.setOutput(new StrategyOutput(Long.valueOf(listDbId.toString()), StrategyType.LIST_DB), paramMap);
|
||||
// fieldList.add(hitResult);
|
||||
// fieldList.addAll(jsonObjects);
|
||||
// resultJson.put("fieldList",fieldList);
|
||||
// if (type == 1) {
|
||||
// blackandWhite.put("resultType", 5);
|
||||
// outmap.put("black", listDb);
|
||||
// resultJson.put("blackId", listDb.getId());
|
||||
// resultJson.put("blackName", listDb.getListName());
|
||||
// resultJson.put("blackType", listDb.getListType());
|
||||
// if (null != listDb.getListDesc()) {
|
||||
// resultJson.put("desc", listDb.getListDesc());
|
||||
// }
|
||||
//
|
||||
// blackandWhite.put("resultJson", resultJson);
|
||||
// //黑名单api返回
|
||||
// outmap.put("blackJson", blackandWhite);
|
||||
// } else {
|
||||
// blackandWhite.put("resultType", 6);
|
||||
// resultJson.put("status", "0x0000");
|
||||
// resultJson.put("whiteId", listDb.getId());
|
||||
// resultJson.put("whiteName", listDb.getListName());
|
||||
// resultJson.put("whiteType", listDb.getListType());
|
||||
// if (null != listDb.getListDesc()) {
|
||||
// resultJson.put("desc", listDb.getListDesc());
|
||||
// }
|
||||
// blackandWhite.put("resultJson", resultJson);
|
||||
// //白名单api返回
|
||||
// outmap.put("whiteJson", blackandWhite);
|
||||
// outmap.put("white", listDb);
|
||||
// }
|
||||
// paramMap.put(hitKey,hitSize);
|
||||
// return true;
|
||||
// }else {
|
||||
// //未命中
|
||||
// blackandWhite.put("resultJson","未命中");
|
||||
// fieldList.add( hitResult);
|
||||
// }
|
||||
// //监控中心==》将评分卡的执行结果得分明细放入 输出变量池 用于存入hbase
|
||||
// outmap.put("nodeResult",blackandWhite);
|
||||
// }
|
||||
// paramMap.put(hitKey,hitSize);
|
||||
// //监控中心==》策略层面记录策略的快照信息
|
||||
// JSONObject strategyObject = new JSONObject();
|
||||
// strategyObject.put("strategySnopshot",strategySnopshot);
|
||||
// outmap.put("strategySnopshot",strategyObject);
|
||||
// } else
|
||||
// return false;
|
||||
// }
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Description: 获取jdbc.properties里配置的数据库名
|
||||
*
|
||||
* @return
|
||||
* @see
|
||||
*/
|
||||
private String getDbName() {
|
||||
|
||||
// ResourceBundle resource = ResourceBundle.getBundle("conf/jdbc");
|
||||
// String mysqlUrl = resource.getString("mysql.url");
|
||||
//
|
||||
// String aArray[] = mysqlUrl.split("/");
|
||||
// String bArray[] = aArray[3].split("\\?");
|
||||
// String dbName = bArray[0];
|
||||
//
|
||||
// return dbName;
|
||||
return "riskmanage";
|
||||
}
|
||||
private void terminalCondition(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap,Object executeResult) {
|
||||
String sizeKey = engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_terminal_size";
|
||||
Map<String,Object> map = new HashMap<>();
|
||||
map.put(sizeKey,executeResult);
|
||||
ExecuteUtils.terminalCondition(engineNode,inputParam,outMap, map);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package com.fibo.ddp.enginex.runner.node.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
|
||||
import com.fibo.ddp.common.model.strategyx.aimodel.MachineLearningModels;
|
||||
import com.fibo.ddp.common.model.strategyx.strategyout.StrategyOutput;
|
||||
import com.fibo.ddp.common.service.datax.runner.CommonService;
|
||||
import com.fibo.ddp.common.service.datax.runner.ExecuteUtils;
|
||||
import com.fibo.ddp.common.service.strategyx.aimodel.ModelsService;
|
||||
import com.fibo.ddp.common.service.strategyx.aimodel.PMMLExecutor.PMMLExecutor;
|
||||
import com.fibo.ddp.common.service.strategyx.strategyout.StrategyOutputService;
|
||||
import com.fibo.ddp.common.utils.constant.strategyx.StrategyType;
|
||||
import com.fibo.ddp.common.utils.util.StringUtil;
|
||||
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
public class ModelNode implements EngineRunnerNode {
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Autowired
|
||||
private CommonService commonService;
|
||||
@Resource
|
||||
public ModelsService modelsService;
|
||||
@Resource(name = "PMMLExecutorRFImpl")
|
||||
private PMMLExecutor pmmlExecutor;
|
||||
@Resource
|
||||
private StrategyOutputService outputService;
|
||||
|
||||
private List<Long> getExecuteVersionIdList(EngineNode engineNode) {
|
||||
return ExecuteUtils.getExecuteIdList(engineNode, "modelId");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
|
||||
logger.info("start【获取模型节点指标】ModelNode.getNodeField engineNode:{},inputParam:{}", JSONObject.toJSONString(engineNode), JSONObject.toJSONString(inputParam));
|
||||
// Long modelId = Long.valueOf(engineNode.getNodeJson());
|
||||
List<Long> modelIds = getExecuteVersionIdList(engineNode);
|
||||
List<Long> ids = new ArrayList<>();
|
||||
for (Long modelId : modelIds) {
|
||||
MachineLearningModels models = modelsService.selectById(Integer.valueOf(modelId.toString()));
|
||||
ids.addAll(StringUtil.toLongList(models.getMappingField()));
|
||||
}
|
||||
try {
|
||||
commonService.getFieldByIds(ids, inputParam);
|
||||
}catch (Exception e){
|
||||
logger.error("模型中字段未完全找到");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
|
||||
|
||||
List<Long> modelIds = getExecuteVersionIdList(engineNode);
|
||||
if (modelIds == null || modelIds.isEmpty()){
|
||||
logger.error("模型节点内容为空,node:{}",engineNode);
|
||||
return;
|
||||
}
|
||||
Long modelId = modelIds.get(0);
|
||||
MachineLearningModels models = modelsService.selectById(Integer.valueOf(modelId.toString()));
|
||||
//监控中心--节点信息记录
|
||||
outMap.put("nodeSnapshot", models);
|
||||
JSONObject nodeInfo = new JSONObject();
|
||||
nodeInfo.put("engineNode", engineNode);
|
||||
nodeInfo.put("nodeId", engineNode.getNodeId());
|
||||
nodeInfo.put("nodeName", engineNode.getNodeName());
|
||||
nodeInfo.put("nodeType", engineNode.getNodeType());
|
||||
outMap.put("nodeInfo", nodeInfo);
|
||||
// 加载模型文件
|
||||
org.jpmml.evaluator.Evaluator evaluator = pmmlExecutor.loadPmml(models.getFilePath());
|
||||
|
||||
Map<String, Object> input = new HashMap<>();
|
||||
String[] modelFieldArr = models.getModelField().split(",");
|
||||
String[] mappingFieldArr = models.getMappingField().split(",");
|
||||
for (int i = 0; i < modelFieldArr.length; i++) {
|
||||
input.put(modelFieldArr[i], inputParam.get(mappingFieldArr[i]));
|
||||
}
|
||||
// 调用模型
|
||||
double modelResult = 0d;
|
||||
try {
|
||||
modelResult =pmmlExecutor.predict(evaluator, input);
|
||||
}catch (Exception e){
|
||||
logger.error("模型节点执行异常,node:{}",engineNode);
|
||||
}
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("nodeId", engineNode.getNodeId());
|
||||
jsonObject.put("nodeName", engineNode.getNodeName());
|
||||
jsonObject.put("modelId", models.getId());
|
||||
jsonObject.put("modelName", models.getModelName());
|
||||
List<JSONObject> fieldList = new ArrayList<>();
|
||||
JSONObject result = new JSONObject();
|
||||
result.put(models.getResultFieldEn(), modelResult);
|
||||
fieldList.add(result);
|
||||
fieldList.addAll(outputService.setOutput(new StrategyOutput(modelId, StrategyType.MODELS), input));
|
||||
jsonObject.put("fieldList", fieldList);
|
||||
outMap.put("nodeResult", jsonObject);
|
||||
if (outMap.containsKey("modelJson")) {
|
||||
JSONArray resultJson = (JSONArray) outMap.get("modelJson");
|
||||
resultJson.add(jsonObject);
|
||||
} else {
|
||||
JSONArray resultJson = new JSONArray();
|
||||
resultJson.add(jsonObject);
|
||||
outMap.put("modelJson", resultJson);
|
||||
}
|
||||
inputParam.put("model_" + modelId, modelResult);
|
||||
inputParam.put(models.getResultFieldEn(), modelResult);
|
||||
outMap.put("model_" + modelId, modelResult);
|
||||
terminalCondition(engineNode, inputParam, outMap, modelResult);
|
||||
}
|
||||
|
||||
private void terminalCondition(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap, Object executeResult) {
|
||||
String resultKey = engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_terminal_result";
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put(resultKey, executeResult);
|
||||
ExecuteUtils.terminalCondition(engineNode, inputParam, outMap, map);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.fibo.ddp.enginex.runner.node.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
|
||||
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 并行节点
|
||||
*/
|
||||
@Service
|
||||
public class ParallelNode implements EngineRunnerNode {
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Override
|
||||
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
|
||||
logger.info("start【执行并行节点】ParallelNode.runNode engineNode:{},inputParam:{},outMap:{}"
|
||||
, JSONObject.toJSONString(engineNode), JSONObject.toJSONString(inputParam), JSONObject.toJSONString(outMap));
|
||||
if (engineNode != null && engineNode.getSnapshot() != null) {
|
||||
outMap.put("nodeSnapshot", engineNode.getSnapshot());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.fibo.ddp.enginex.runner.node.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.fibo.ddp.common.model.datax.datainterface.InterfaceInfo;
|
||||
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
|
||||
import com.fibo.ddp.common.service.datax.datainterface.InterfaceService;
|
||||
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 远程调用节点
|
||||
*/
|
||||
@Service
|
||||
public class RpcNode implements EngineRunnerNode {
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Autowired
|
||||
private InterfaceService interfaceService;
|
||||
|
||||
@Override
|
||||
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
|
||||
logger.info("start【执行RPC节点】RpcNode.runNode engineNode:{},inputParam:{},outMap:{}"
|
||||
, JSONObject.toJSONString(engineNode), JSONObject.toJSONString(inputParam), JSONObject.toJSONString(outMap));
|
||||
if (engineNode != null && engineNode.getSnapshot() != null) {
|
||||
outMap.put("nodeSnapshot", engineNode.getSnapshot());
|
||||
}
|
||||
JSONObject nodeJson = JSONObject.parseObject(engineNode.getNodeJson());
|
||||
JSONObject callConfig = nodeJson.getJSONObject("callConfig");
|
||||
int callType = callConfig.getInteger("callType");
|
||||
JSONArray resultConfig = nodeJson.getJSONArray("resultConfig");
|
||||
InterfaceInfo interfaceInfo = interfaceService.getInterfaceById(callConfig.getInteger("interfaceId"));
|
||||
// 发送http请求
|
||||
String result = interfaceService.getHttpResponse(interfaceInfo, inputParam, callType);
|
||||
// 解析指标
|
||||
parseField(result, resultConfig, inputParam);
|
||||
}
|
||||
|
||||
private void parseField(String result, JSONArray resultConfig, Map<String, Object> inputParam){
|
||||
if(resultConfig != null && !resultConfig.isEmpty() && StringUtils.isNotBlank(result)){
|
||||
JSONObject configJson = resultConfig.getJSONObject(0);
|
||||
String fieldEn = configJson.getString("fieldEn");
|
||||
String parseField = configJson.getString("parseField");
|
||||
String fieldValue = interfaceService.interfaceParseField(parseField, result);
|
||||
inputParam.put(fieldEn, fieldValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,769 @@
|
||||
package com.fibo.ddp.enginex.runner.node.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.fibo.ddp.common.model.datax.datamanage.Field;
|
||||
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
|
||||
import com.fibo.ddp.common.model.enginex.runner.ExpressionParam;
|
||||
import com.fibo.ddp.common.model.strategyx.guiderule.RuleInfo;
|
||||
import com.fibo.ddp.common.model.strategyx.guiderule.RuleLoopGroupAction;
|
||||
import com.fibo.ddp.common.model.strategyx.guiderule.vo.RuleConditionVo;
|
||||
import com.fibo.ddp.common.model.strategyx.guiderule.vo.RuleVersionVo;
|
||||
import com.fibo.ddp.common.model.strategyx.scriptrule.RuleScriptVersion;
|
||||
import com.fibo.ddp.common.service.datax.datamanage.FieldService;
|
||||
import com.fibo.ddp.common.service.datax.runner.CommonService;
|
||||
import com.fibo.ddp.common.service.datax.runner.ExecuteUtils;
|
||||
import com.fibo.ddp.common.service.strategyx.guiderule.RuleConditionService;
|
||||
import com.fibo.ddp.common.service.strategyx.guiderule.RuleService;
|
||||
import com.fibo.ddp.common.service.strategyx.guiderule.RuleVersionService;
|
||||
import com.fibo.ddp.common.service.strategyx.scriptrule.RuleScriptVersionService;
|
||||
import com.fibo.ddp.common.utils.constant.Constants;
|
||||
import com.fibo.ddp.common.utils.constant.strategyx.RuleConst;
|
||||
import com.fibo.ddp.common.utils.constant.strategyx.StrategyType;
|
||||
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class RuleSetNode implements EngineRunnerNode {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Autowired
|
||||
private CommonService commonService;
|
||||
@Resource
|
||||
private RuleService ruleService;
|
||||
@Autowired
|
||||
private RuleConditionService conditionService;
|
||||
@Resource
|
||||
private RuleScriptVersionService ruleScriptVersionService;
|
||||
@Resource
|
||||
private FieldService fieldService;
|
||||
@Autowired
|
||||
private RuleVersionService versionService;
|
||||
@Autowired
|
||||
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
|
||||
|
||||
@Override
|
||||
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
|
||||
logger.info("start【获取规则集节点指标】RuleSetNode.getNodeField engineNode:{},inputParam:{}", JSONObject.toJSONString(engineNode), JSONObject.toJSONString(inputParam));
|
||||
JSONObject nodeJson = JSONObject.parseObject(engineNode.getNodeJson());
|
||||
List<Long> ids = new ArrayList<>();
|
||||
List<Long> versionIds = new ArrayList<>(); // 复杂规则集
|
||||
List<Long> scriptVersionIds = new ArrayList<>(); // 脚本规则集
|
||||
|
||||
JSONArray jsonArray = null;
|
||||
int groupType = nodeJson.getInteger("groupType");
|
||||
if (groupType == Constants.ruleNode.MUTEXGROUP) {
|
||||
jsonArray = nodeJson.getJSONObject("mutexGroup").getJSONArray("rules");
|
||||
} else {
|
||||
jsonArray = nodeJson.getJSONObject("executeGroup").getJSONArray("rules");
|
||||
}
|
||||
|
||||
for (int i = 0; i < jsonArray.size(); i++) {
|
||||
JSONObject ruleObj = jsonArray.getJSONObject(i);
|
||||
Long versionId = ruleObj.getLong("ruleVersionId");
|
||||
Long difficulty = ruleObj.getLong("difficulty");
|
||||
if (difficulty != null && difficulty == 3) {
|
||||
scriptVersionIds.add(versionId); // 脚本式规则
|
||||
} else if (versionId != null) {
|
||||
versionIds.add(versionId); // 复杂规则
|
||||
}
|
||||
}
|
||||
|
||||
//获取字段en
|
||||
List<String> fieldEnList = new ArrayList<>();
|
||||
if (!versionIds.isEmpty()) {
|
||||
fieldEnList.addAll(conditionService.queryFieldEnByVersionIds(versionIds));
|
||||
}
|
||||
if (!scriptVersionIds.isEmpty()) {
|
||||
fieldEnList.addAll(ruleScriptVersionService.queryFieldEnByVersionIds(scriptVersionIds));
|
||||
}
|
||||
|
||||
//筛选调那些循环或者嵌套中的字段
|
||||
fieldEnList = fieldEnList.stream().distinct().filter(f -> f != null && !f.contains(".") && !f.contains("%")).collect(Collectors.toList());
|
||||
if (fieldEnList != null && !fieldEnList.isEmpty()) {
|
||||
List<Field> fieldList = fieldService.selectFieldListByEns(fieldEnList);
|
||||
for (Field field : fieldList) {
|
||||
ids.add(field.getId());
|
||||
}
|
||||
}
|
||||
|
||||
if (!ids.isEmpty()) {
|
||||
commonService.getFieldByIds(ids, inputParam);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
|
||||
JSONObject nodeJson = JSONObject.parseObject(engineNode.getNodeJson());
|
||||
//监控中心--记录节点快照信息
|
||||
if (engineNode != null && engineNode.getSnapshot() != null) {
|
||||
outMap.put("nodeSnapshot", engineNode.getSnapshot());
|
||||
}
|
||||
JSONObject nodeInfo = new JSONObject();
|
||||
nodeInfo.put("engineNode", engineNode);
|
||||
nodeInfo.put("nodeId", engineNode.getNodeId());
|
||||
nodeInfo.put("nodeName", engineNode.getNodeName());
|
||||
nodeInfo.put("nodeType", engineNode.getNodeType());
|
||||
outMap.put("nodeInfo", nodeInfo);
|
||||
int groupType = nodeJson.getInteger("groupType") == null ? Constants.ruleNode.EXECUTEGROUP : nodeJson.getInteger("groupType");
|
||||
CopyOnWriteArrayList<Map> ruleResultList = new CopyOnWriteArrayList<>();// 规则执行结果集合
|
||||
List<RuleInfo> ruleHitList = new ArrayList<>(); // 命中的规则集合
|
||||
|
||||
// 互斥组(串行)
|
||||
if (groupType == Constants.ruleNode.MUTEXGROUP) {
|
||||
JSONArray jsonArray = nodeJson.getJSONObject("mutexGroup").getJSONArray("rules");
|
||||
List<RuleInfo> ruleInfoList = getRuleFromJsonArray(jsonArray);
|
||||
//监控中心--循环获取策略层面的快照信息
|
||||
recordStrategySnopshot(ruleInfoList, outMap);
|
||||
ruleHitList = serialRule(inputParam, outMap, ruleInfoList, ruleResultList);
|
||||
}
|
||||
// 执行组(并行)
|
||||
else if (groupType == Constants.ruleNode.EXECUTEGROUP) {
|
||||
JSONArray jsonArray = nodeJson.getJSONObject("executeGroup").getJSONArray("rules");
|
||||
List<RuleInfo> ruleInfoList = getRuleFromJsonArray(jsonArray);
|
||||
//监控中心--循环获取策略层面的快照信息
|
||||
recordStrategySnopshot(ruleInfoList, outMap);
|
||||
ruleHitList = parallelRule(inputParam, outMap, ruleInfoList, ruleResultList);
|
||||
}
|
||||
|
||||
// 终止条件处理
|
||||
terminalCondition(engineNode, nodeJson, outMap, ruleHitList);
|
||||
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("nodeId", engineNode.getNodeId());
|
||||
jsonObject.put("nodeName", engineNode.getNodeName());
|
||||
jsonObject.put("ruleResultList", ruleResultList);
|
||||
|
||||
if (outMap.containsKey("ruleJson")) {
|
||||
JSONArray resultJson = (JSONArray) outMap.get("ruleJson");
|
||||
resultJson.add(jsonObject);
|
||||
} else {
|
||||
JSONArray resultJson = new JSONArray();
|
||||
resultJson.add(jsonObject);
|
||||
outMap.put("ruleJson", resultJson);
|
||||
}
|
||||
int hitSize = 0;
|
||||
double scoreSum = 0d;
|
||||
for (Map map : ruleResultList) {
|
||||
Object ruleScore = map.get("ruleScore");
|
||||
Object ruleResult = map.get("ruleResult");
|
||||
if (null != ruleResult && "命中".equals(ruleResult)) {
|
||||
hitSize++;
|
||||
if (null != ruleScore) {
|
||||
try {
|
||||
scoreSum += Double.valueOf(ruleScore.toString());
|
||||
} catch (Exception e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
String hitKey = "" + engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_size";
|
||||
String scoreKey = "" + engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_score";
|
||||
inputParam.put(hitKey, hitSize);
|
||||
inputParam.put(scoreKey, scoreSum);
|
||||
//监控中心==》记录节点输出结果
|
||||
//记录整个规则集中的所有规则的命中情况,以及总的统计次数 放到输出变量池
|
||||
JSONObject nodeResult = new JSONObject();
|
||||
nodeResult.put("ruleResultList", ruleResultList);
|
||||
nodeResult.put("hitNum", hitSize);
|
||||
nodeResult.put("scoreTotal", scoreSum);
|
||||
outMap.put("nodeResult", nodeResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* 监控中心--获取策略层面快照信息
|
||||
*
|
||||
* @param ruleInfoList
|
||||
* @param outMap
|
||||
*/
|
||||
private void recordStrategySnopshot(List<RuleInfo> ruleInfoList, Map<String, Object> outMap) {
|
||||
JSONArray jsonObject = new JSONArray();
|
||||
ruleInfoList.stream().forEach(ruleInfo -> {
|
||||
logger.info("===========================监控添加策略信息快照情况==============版本id:{}=====:{}",ruleInfo.getVersion().getId(),ruleInfo.getVersion().getSnapshot());
|
||||
if (ruleInfo.getVersion().getSnapshot() != null) {
|
||||
jsonObject.add(ruleInfo.getVersion().getSnapshot());
|
||||
|
||||
}
|
||||
});
|
||||
JSONObject jsonObject1 = new JSONObject();
|
||||
jsonObject1.put("snopshot", jsonObject);
|
||||
logger.info("===========================监控添加策略信息快照情况:{}",jsonObject1);
|
||||
outMap.put("strategySnopshot", jsonObject1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 串行执行规则
|
||||
*
|
||||
* @param inputParam
|
||||
* @param outMap
|
||||
* @param ruleInfoList
|
||||
* @param ruleResultList
|
||||
* @return
|
||||
*/
|
||||
private List<RuleInfo> serialRule(Map<String, Object> inputParam, Map<String, Object> outMap, List<RuleInfo> ruleInfoList, CopyOnWriteArrayList<Map> ruleResultList) {
|
||||
logger.info("请求参数--串行执行规则" + "map:" + JSONObject.toJSONString(inputParam));
|
||||
List<RuleInfo> resultList = new ArrayList<>();
|
||||
for (int i = 0; i < ruleInfoList.size(); i++) {
|
||||
RuleInfo rule = ruleInfoList.get(i);
|
||||
boolean hitFlag = executeByDifficulty(inputParam, outMap, rule, ruleResultList);
|
||||
if (hitFlag) {
|
||||
resultList.add(rule);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 并行执行规则
|
||||
*
|
||||
* @param inputParam
|
||||
* @param outMap
|
||||
* @param ruleInfoList
|
||||
* @param ruleResultList
|
||||
* @return
|
||||
*/
|
||||
private List<RuleInfo> parallelRule(Map<String, Object> inputParam, Map<String, Object> outMap, List<RuleInfo> ruleInfoList, CopyOnWriteArrayList<Map> ruleResultList) {
|
||||
logger.info("请求参数--并行执行规则" + "map:" + JSONObject.toJSONString(inputParam));
|
||||
List<RuleInfo> resultList = new ArrayList<>();
|
||||
List<CompletableFuture<RuleInfo>> futureList = new ArrayList<>();
|
||||
for (int i = 0; i < ruleInfoList.size(); i++) {
|
||||
final int index = i;
|
||||
CompletableFuture<RuleInfo> future = CompletableFuture.supplyAsync(() -> {
|
||||
RuleInfo rule = ruleInfoList.get(index);
|
||||
boolean hitFlag = executeByDifficulty(inputParam, outMap, rule, ruleResultList);
|
||||
if (hitFlag) {
|
||||
return rule;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}, threadPoolTaskExecutor);
|
||||
|
||||
futureList.add(future);
|
||||
}
|
||||
|
||||
for (CompletableFuture<RuleInfo> future : futureList) {
|
||||
try {
|
||||
RuleInfo rule = future.get();
|
||||
if (rule != null) {
|
||||
resultList.add(rule);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return resultList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根究规则类型选择执行
|
||||
*
|
||||
* @param inputParam
|
||||
* @param outMap
|
||||
* @param rule
|
||||
* @param ruleResultList
|
||||
* @return
|
||||
*/
|
||||
private boolean executeByDifficulty(Map<String, Object> inputParam, Map<String, Object> outMap, RuleInfo rule, CopyOnWriteArrayList<Map> ruleResultList) {
|
||||
boolean hitFlag = false;
|
||||
if (rule.getDifficulty() == 2) {
|
||||
hitFlag = executeComplexRule(inputParam, outMap, rule, ruleResultList);
|
||||
} else if (rule.getDifficulty() == 3) {
|
||||
hitFlag = executeScriptRule(inputParam, outMap, rule, ruleResultList);
|
||||
}
|
||||
return hitFlag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行复杂规则
|
||||
*
|
||||
* @param input
|
||||
* @param output
|
||||
* @param rule
|
||||
* @param ruleResultList
|
||||
* @return
|
||||
*/
|
||||
public boolean executeComplexRule(Map<String, Object> input, Map<String, Object> output, RuleInfo rule, CopyOnWriteArrayList<Map> ruleResultList) {
|
||||
boolean hitFlag = false;
|
||||
//获取需要执行的整个规则。
|
||||
// RuleVo rule = ruleService.queryByVersionId(ruleId);
|
||||
// Long versionId = rule.getVersionId();
|
||||
// if (versionId==null){
|
||||
// return false;
|
||||
// }
|
||||
// RuleVersionVo ruleVersion = versionService.queryByVersionId(versionId);
|
||||
RuleVersionVo ruleVersion = rule.getVersion();
|
||||
if (ruleVersion == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//取出本规则的条件列表
|
||||
Map<String, Object> ruleMap = new HashMap<>();
|
||||
ruleMap.put("ruleId", rule.getId());
|
||||
ruleMap.put("ruleVersionId",ruleVersion.getId());
|
||||
ruleMap.put("ruleCode", rule.getCode());
|
||||
ruleMap.put("ruleName", rule.getName());
|
||||
ruleMap.put("versionCode", ruleVersion.getVersionCode());
|
||||
ruleMap.put("versionDesc", ruleVersion.getDescription());
|
||||
ruleMap.put("desc", rule.getDescription());
|
||||
ruleMap.put("ruleResult", "未命中");
|
||||
|
||||
//获取规则需要执行的condition逻辑。
|
||||
RuleConditionVo ruleCondition = ruleVersion.getRuleConditionVo();
|
||||
//传入输入参数、中间变量、输出参数和需要执行的condition逻辑获取执行结果
|
||||
Map<String, Object> temp = JSON.parseObject(JSON.toJSONString(input), Map.class);
|
||||
boolean result = this.executeRuleCondition(temp, output, ruleCondition);
|
||||
String resultFieldEn = ruleVersion.getResultFieldEn();
|
||||
if (resultFieldEn == null || "".equals(resultFieldEn)) {
|
||||
resultFieldEn = "rule_2_"+rule.getId()+"_"+ruleVersion.getId()+"_hitResult";
|
||||
}
|
||||
String scoreFieldEn = ruleVersion.getScoreFieldEn();
|
||||
if (StringUtils.isBlank(scoreFieldEn)){
|
||||
scoreFieldEn = "rule_2_"+rule.getId()+"_"+ruleVersion.getId()+"_score";
|
||||
}
|
||||
input.put(resultFieldEn, "未命中");
|
||||
//根据执行的最终结果处理此规则输出内容
|
||||
List<JSONObject> fieldList = new ArrayList<>();
|
||||
JSONObject resultJson = new JSONObject();
|
||||
if (result) {
|
||||
ruleMap.put("ruleResult", "命中");
|
||||
ruleMap.put("ruleScore", rule.getScore());
|
||||
JSONObject scoreJson = new JSONObject();
|
||||
resultJson.put(resultFieldEn, "命中");
|
||||
fieldList.add(resultJson);
|
||||
// if (StringUtils.isNotBlank(ruleVersion.getScoreFieldEn())) {
|
||||
scoreJson.put(scoreFieldEn, ruleVersion.getScore());
|
||||
fieldList.add(scoreJson);
|
||||
input.put(scoreFieldEn, ruleVersion.getScore());
|
||||
// }
|
||||
input.put(resultFieldEn, "命中");
|
||||
//处理此规则需要输出的内容
|
||||
fieldList.addAll(ruleService.setComplexRuleOutput(ruleVersion.getId(), temp, input, StrategyType.OutType.SUCCESS_OUT));
|
||||
ruleMap.put("fieldList", fieldList);
|
||||
hitFlag = true;
|
||||
} else {
|
||||
resultJson.put(resultFieldEn, "未命中");
|
||||
ruleMap.put("ruleScore", 0);
|
||||
input.put(scoreFieldEn,0);
|
||||
fieldList.add(resultJson);
|
||||
fieldList.addAll(ruleService.setComplexRuleOutput(ruleVersion.getId(), temp, input, StrategyType.OutType.FAIL_OUT));
|
||||
ruleMap.put("fieldList", fieldList);
|
||||
}
|
||||
ruleResultList.add(ruleMap);
|
||||
return hitFlag;
|
||||
}
|
||||
|
||||
//执行规则的条件
|
||||
private boolean executeRuleCondition(Map<String, Object> input, Map<String, Object> output, RuleConditionVo ruleCondition) {
|
||||
Integer conditionType = ruleCondition.getConditionType();
|
||||
boolean result = false;
|
||||
switch (conditionType) {
|
||||
//关系条件节点 &&和||
|
||||
case RuleConst.RELATION_CONDITION:
|
||||
//循环结果的条件
|
||||
case RuleConst.LOOP_RESULT_CONDITION:
|
||||
case RuleConst.CONDITION_RESULT_CONDITION:
|
||||
result = executeRelation(input, output, ruleCondition);
|
||||
break;
|
||||
//表达式条件节点
|
||||
case RuleConst.EXPRESSION_CONDITION:
|
||||
result = executeExpression(input, output, ruleCondition);
|
||||
break;
|
||||
//循环条件根节点
|
||||
case RuleConst.LOOP_CONDITION:
|
||||
result = executeLoop(input, output, ruleCondition);
|
||||
break;
|
||||
//条件组根节点
|
||||
case RuleConst.CONDITION_GROUP_CONDITION:
|
||||
result = executeCondGroup(input, output, ruleCondition);
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//执行条件组
|
||||
private boolean executeCondGroup(Map<String, Object> input, Map<String, Object> output, RuleConditionVo ruleCondition) {
|
||||
//取出子条件
|
||||
List<RuleConditionVo> children = ruleCondition.getChildren();
|
||||
//存储命中条数
|
||||
int hitNum = 0;
|
||||
if (children == null) {
|
||||
return false;
|
||||
}
|
||||
//执行条件组中条件列表,命中则添加命中条数
|
||||
for (RuleConditionVo child : children) {
|
||||
boolean childResult = executeRuleCondition(input, output, child);
|
||||
if (childResult) {
|
||||
hitNum++;
|
||||
}
|
||||
}
|
||||
//获取条件组命中条件,为null直接不命中
|
||||
RuleConditionVo condGroup = ruleCondition.getCondGroupResultCondition();
|
||||
if (condGroup == null) {
|
||||
return false;
|
||||
}
|
||||
//传入命中条件和组内命中条数执行并返回
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
//将命中条数存入map然后判断执行结果
|
||||
map.put("hitNum", hitNum);
|
||||
return executeRuleCondition(map, output, condGroup);
|
||||
}
|
||||
|
||||
//关系条件节点 &&和||
|
||||
private boolean executeRelation(Map<String, Object> input, Map<String, Object> output, RuleConditionVo ruleCondition) {
|
||||
//获取关系逻辑
|
||||
String logical = ruleCondition.getLogical();
|
||||
//处理子逻辑
|
||||
List<RuleConditionVo> children = ruleCondition.getChildren();
|
||||
|
||||
boolean result = false;
|
||||
switch (logical) {
|
||||
case "||":
|
||||
result = false;
|
||||
for (RuleConditionVo child : children) {
|
||||
boolean childResult = executeRuleCondition(input, output, child);
|
||||
if (childResult) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "&&":
|
||||
result = true;
|
||||
for (RuleConditionVo child : children) {
|
||||
boolean childResult = executeRuleCondition(input, output, child);
|
||||
if (!childResult) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//表达式条件节点
|
||||
private boolean executeExpression(Map<String, Object> input, Map<String, Object> output, RuleConditionVo ruleCondition) {
|
||||
String executionLogic = ruleCondition.getExecutionLogic();
|
||||
boolean result = false;
|
||||
ExpressionParam expressionParam = new ExpressionParam();
|
||||
//复制执行的关键参数到统一入参
|
||||
BeanUtils.copyProperties(ruleCondition, expressionParam);
|
||||
result = ExecuteUtils.getExpressionResult(expressionParam, input);
|
||||
return result;
|
||||
}
|
||||
|
||||
//循环条件根节点
|
||||
private boolean executeLoop(Map<String, Object> input, Map<String, Object> output, RuleConditionVo ruleCondition) {
|
||||
List<RuleConditionVo> children = ruleCondition.getChildren();
|
||||
String fieldEn = ruleCondition.getFieldEn();
|
||||
|
||||
//对循环中每个条件进行处理
|
||||
String[] split = fieldEn.split("\\.");
|
||||
//从map中取元素返回最终取到的对象
|
||||
Object obj = ExecuteUtils.getObjFromMap(input, fieldEn);
|
||||
List arrayList = new ArrayList();
|
||||
if (obj != null) {
|
||||
arrayList.addAll(JSON.parseObject(JSON.toJSONString(obj), ArrayList.class));
|
||||
}
|
||||
//取不到这个数组
|
||||
if (arrayList.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
//拼接当前对象的key
|
||||
String currentKey = "%" + split[split.length - 1] + "%";
|
||||
for (RuleConditionVo child : children) {
|
||||
List<RuleLoopGroupAction> loopGroupActions = child.getLoopGroupActions();
|
||||
// 调用for循环条件下的操作,并且将其存入input中
|
||||
for (RuleLoopGroupAction loopGroupAction : loopGroupActions) {
|
||||
this.initLoopGroupAction(loopGroupAction, input);
|
||||
}
|
||||
}
|
||||
for (Object currentObj : arrayList) {
|
||||
//将循环时的当前对象存入input
|
||||
input.put(currentKey, currentObj);
|
||||
//循环执行当前for中的每个判断单元
|
||||
for (RuleConditionVo child : children) {
|
||||
if (executeRuleCondition(input, output, child)) {
|
||||
List<RuleLoopGroupAction> loopGroupActions = child.getLoopGroupActions();
|
||||
// 调用for循环条件下的操作,并且将其存入input中
|
||||
for (RuleLoopGroupAction loopGroupAction : loopGroupActions) {
|
||||
this.saveLoopGroupAction(loopGroupAction, input);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//计算for的返回结果
|
||||
RuleConditionVo loopResultCondition = ruleCondition.getLoopResultCondition();
|
||||
boolean result = executeRuleCondition(input, output, loopResultCondition);
|
||||
return result;
|
||||
}
|
||||
|
||||
//保存循环规则的动作
|
||||
private void saveLoopGroupAction(RuleLoopGroupAction loopGroupAction, Map<String, Object> input) {
|
||||
Integer actionType = loopGroupAction.getActionType();
|
||||
String actionKey = loopGroupAction.getActionKey();
|
||||
String actionValue = loopGroupAction.getActionValue();
|
||||
if (actionType == null) {
|
||||
return;
|
||||
}
|
||||
switch (actionType) {
|
||||
case RuleConst.LOOP_GROUP_ACTION_TYPE_SUM:
|
||||
Integer count = 1;
|
||||
if (input.containsKey(actionKey) && StringUtils.isNumeric(ExecuteUtils.getObjFromMap(input, actionKey).toString())) {
|
||||
count = count + Integer.parseInt(ExecuteUtils.getObjFromMap(input, actionKey).toString());
|
||||
}
|
||||
input.put(actionKey, count);
|
||||
break;
|
||||
case RuleConst.LOOP_GROUP_ACTION_TYPE_ASSIGNMENT:
|
||||
//赋值待添加
|
||||
break;
|
||||
case RuleConst.LOOP_GROUP_ACTION_TYPE_OUT_CONST:
|
||||
input.put(actionKey, actionValue);
|
||||
break;
|
||||
case RuleConst.LOOP_GROUP_ACTION_TYPE_OUT_VARIABLE:
|
||||
input.put(actionKey, ExecuteUtils.getObjFromMap(input, actionValue));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void initLoopGroupAction(RuleLoopGroupAction loopGroupAction, Map<String, Object> input){
|
||||
Integer actionType = loopGroupAction.getActionType();
|
||||
String actionKey = loopGroupAction.getActionKey();
|
||||
String actionValue = loopGroupAction.getActionValue();
|
||||
if (actionType == null) {
|
||||
return;
|
||||
}
|
||||
switch (actionType) {
|
||||
case RuleConst.LOOP_GROUP_ACTION_TYPE_SUM:
|
||||
input.put(actionKey, 0);
|
||||
break;
|
||||
case RuleConst.LOOP_GROUP_ACTION_TYPE_ASSIGNMENT:
|
||||
//赋值待添加
|
||||
break;
|
||||
case RuleConst.LOOP_GROUP_ACTION_TYPE_OUT_CONST:
|
||||
input.put(actionKey, "");
|
||||
break;
|
||||
case RuleConst.LOOP_GROUP_ACTION_TYPE_OUT_VARIABLE:
|
||||
input.put(actionKey,new HashSet<>());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 终止条件判断
|
||||
*
|
||||
* @param engineNode
|
||||
* @param inputParam
|
||||
* @param outMap
|
||||
* @param ruleHitList
|
||||
*/
|
||||
private void terminalCondition(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap, List<RuleInfo> ruleHitList) {
|
||||
if (StringUtils.isBlank(engineNode.getNodeScript())) {
|
||||
return;
|
||||
}
|
||||
JSONObject nodeScript = JSONObject.parseObject(engineNode.getNodeScript());
|
||||
JSONObject terminationInfo = nodeScript.getJSONObject("terminationInfo");
|
||||
JSONArray selectedRule = terminationInfo.getJSONArray("selectedRule");
|
||||
String conditions = terminationInfo.getString("conditions");
|
||||
if (!selectedRule.isEmpty()) {
|
||||
if (!selectedRule.isEmpty()) {
|
||||
List<JSONObject> selectedRuleList = JSONObject.parseArray(JSONObject.toJSONString(selectedRule), JSONObject.class);
|
||||
// 查找已选规则中命名的规则集合
|
||||
List<RuleInfo> selectedHitRules = new ArrayList<>();
|
||||
for (JSONObject jsonObject : selectedRuleList) {
|
||||
Optional<RuleInfo> rule = ruleHitList.stream().filter(item -> item.getId().equals(jsonObject.getLong("id"))).findFirst();
|
||||
if (rule.isPresent()) {
|
||||
selectedHitRules.add(rule.get());
|
||||
}
|
||||
}
|
||||
|
||||
int totalSize = selectedHitRules.size(); // 规则命名个数
|
||||
double totalScore = selectedHitRules.stream().mapToDouble(RuleInfo::getScore).sum(); // 规则总得分
|
||||
String sizeKey = engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_terminal_size";
|
||||
String scoreKey = engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_terminal_score";
|
||||
Map<String, Object> variablesMap = new HashMap<>();
|
||||
variablesMap.put(sizeKey, totalSize);
|
||||
variablesMap.put(scoreKey, totalScore);
|
||||
|
||||
ExecuteUtils.terminalCondition(engineNode,inputParam,outMap,variablesMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<RuleInfo> getRuleFromJsonArray(JSONArray jsonArray) {
|
||||
List<Long> ruleIds = new ArrayList<>();
|
||||
Map<Long, Long> map = new HashMap<>();
|
||||
for (int i = 0; i < jsonArray.size(); i++) {
|
||||
JSONObject ruleObj = jsonArray.getJSONObject(i);
|
||||
Long versionId = ruleObj.getLong("ruleVersionId");
|
||||
Long ruleId = ruleObj.getLong("id");
|
||||
if (ruleId != null) {
|
||||
ruleIds.add(ruleId);
|
||||
if (versionId != null) {
|
||||
map.put(ruleId, versionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<RuleInfo> ruleInfoList = ruleService.getRuleList(ruleIds);
|
||||
for (RuleInfo ruleInfo : ruleInfoList) {
|
||||
if (ruleInfo.getDifficulty() == 2 || ruleInfo.getDifficulty() == 3) {
|
||||
Long versionId = map.get(ruleInfo.getId());
|
||||
ruleInfo.setVersionId(versionId);
|
||||
if (versionId != null) {
|
||||
switch (ruleInfo.getDifficulty()) {
|
||||
case 2:
|
||||
RuleVersionVo ruleVersionVo = versionService.queryById(versionId);
|
||||
ruleInfo.setVersion(ruleVersionVo);
|
||||
ruleInfo.setScore(ruleVersionVo.getScore());
|
||||
break;
|
||||
case 3:
|
||||
RuleScriptVersion ruleScriptVersion = ruleScriptVersionService.queryById(versionId);
|
||||
ruleInfo.setScriptVersion(ruleScriptVersion);
|
||||
ruleInfo.setVersion(JSON.parseObject(JSON.toJSONString(ruleScriptVersion), RuleVersionVo.class));
|
||||
ruleInfo.setScore(0);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ruleInfo.setScore(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ruleInfoList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行脚本规则
|
||||
*
|
||||
* @param inputParam
|
||||
* @param outMap
|
||||
* @param rule
|
||||
* @param ruleResultList
|
||||
* @return
|
||||
*/
|
||||
private boolean executeScriptRule(Map<String, Object> inputParam, Map<String, Object> outMap, RuleInfo rule, CopyOnWriteArrayList<Map> ruleResultList) {
|
||||
boolean hitFlag = false;
|
||||
RuleScriptVersion scriptVersion = rule.getScriptVersion();
|
||||
if (RuleConst.ScriptType.GROOVY.equals(rule.getScriptType())&&RuleConst.ScriptType.GROOVY.equals( scriptVersion.getScriptType())) {
|
||||
//groovy脚本执行
|
||||
//取出需要执行的版本
|
||||
if (scriptVersion == null || StringUtils.isBlank(scriptVersion.getScriptContent())) {
|
||||
return false;
|
||||
}
|
||||
//取出脚本内容
|
||||
String scriptContent = scriptVersion.getScriptContent();
|
||||
//取出本规则集的规则列表
|
||||
Map<String, Object> ruleMap = new HashMap<>();
|
||||
ruleMap.put("ruleId", rule.getId());
|
||||
ruleMap.put("ruleVersionId",scriptVersion.getId());
|
||||
ruleMap.put("ruleCode", rule.getCode());
|
||||
ruleMap.put("ruleName", rule.getName());
|
||||
ruleMap.put("versionCode", scriptVersion.getVersionCode());
|
||||
ruleMap.put("versionDesc", scriptVersion.getDescription());
|
||||
ruleMap.put("desc", rule.getDescription());
|
||||
ruleMap.put("ruleResult", "未命中");
|
||||
|
||||
|
||||
String resultFieldEn = "hitResult";
|
||||
String resultEn = "rule_"+rule.getDifficulty()+"_"+rule.getId()+"_"+scriptVersion.getId()+"_hitResult";
|
||||
String scoreEn = "rule_"+rule.getDifficulty()+"_"+rule.getId()+"_"+scriptVersion.getId()+"_score";
|
||||
inputParam.put(resultEn, "未命中");
|
||||
inputParam.put(scoreEn,0);
|
||||
//根据执行的最终结果处理此规则输出内容
|
||||
List fieldList = new ArrayList<>();
|
||||
JSONObject resultJson = new JSONObject();
|
||||
try {
|
||||
Object resp = ExecuteUtils.getObjFromScript(inputParam, scriptContent);
|
||||
String result = "未命中";
|
||||
JSONObject executeResult = null;
|
||||
int ruleScore = 0;
|
||||
if (resp instanceof HashMap) {
|
||||
Map resultMap = (HashMap) resp;
|
||||
executeResult = JSON.parseObject(JSON.toJSONString(resultMap));
|
||||
ruleScore = executeResult.getIntValue("ruleScore");
|
||||
result = executeResult.getString(resultFieldEn);
|
||||
JSONArray fieldListJson = executeResult.getJSONArray("fieldList");
|
||||
JSONObject updateInputMap = executeResult.getJSONObject("updateInputMap");
|
||||
if (fieldListJson != null) {
|
||||
fieldList = fieldListJson.toJavaList(Object.class);
|
||||
List list = new ArrayList();
|
||||
for (Object o : fieldList) {
|
||||
if (o!=null&& o instanceof Map){
|
||||
Map map = ExecuteUtils.handleGroovyResult((Map) o);
|
||||
list.add(map);
|
||||
}
|
||||
}
|
||||
fieldList = list;
|
||||
}
|
||||
|
||||
if (executeResult != null) {
|
||||
ruleMap.put("ruleResult", result);
|
||||
ruleMap.put("ruleScore", ruleScore);
|
||||
resultJson.put(resultFieldEn, result);
|
||||
fieldList.add(resultJson);
|
||||
inputParam.put(resultFieldEn, result);
|
||||
//处理此规则需要输出的内容
|
||||
ruleMap.put("fieldList", fieldList);
|
||||
}
|
||||
if ("命中".equals(result)) {
|
||||
hitFlag = true;
|
||||
inputParam.put(resultEn,"命中");
|
||||
inputParam.put(scoreEn,ruleScore);
|
||||
}
|
||||
//更新入参
|
||||
if (updateInputMap!=null&&!updateInputMap.isEmpty()){
|
||||
Set<Map.Entry<String, Object>> entries = ExecuteUtils.handleGroovyResult(updateInputMap).entrySet();
|
||||
for (Map.Entry<String, Object> entry : entries) {
|
||||
inputParam.put(entry.getKey(),entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
logger.error("脚本规则集执行错误:{}" + e);
|
||||
}
|
||||
ruleResultList.add(ruleMap);
|
||||
}
|
||||
return hitFlag;
|
||||
}
|
||||
|
||||
// public static void main(String[] args) {
|
||||
//// HashMap<String, Object> result = new HashMap<>(); //规则执行的返回值
|
||||
//// int ruleScore = 0; //规则命中时得分
|
||||
//// String hitResult = "未命中"; //命中结果,可选类型为:命中、未命中
|
||||
//// HashMap<String, Object> updateInputMap = new HashMap<>(); //用于更新入参的map,此map中的所有内容将被更新到入参中,key重复的将被覆盖。
|
||||
//// ArrayList<HashMap<String, Object>> fieldList = new ArrayList<>(); //用于存放输出字段的值
|
||||
//// //自定义代码区域,根据需要书写逻辑代码
|
||||
////
|
||||
////
|
||||
////
|
||||
//// //返回固定格式的结果用于后续执行
|
||||
//// result.put("hitResult",hitResult);
|
||||
//// result.put("ruleScore",ruleScore);
|
||||
//// result.put("fieldList",fieldList);
|
||||
//// result.put("updateInputMap",updateInputMap);
|
||||
//// return result;
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package com.fibo.ddp.enginex.runner.node.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
|
||||
import com.fibo.ddp.common.model.enginex.runner.Sandbox;
|
||||
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
@Service
|
||||
public class SandboxProportionNode implements EngineRunnerNode {
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Override
|
||||
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
|
||||
if (null != engineNode.getNodeScript()) {
|
||||
List<Sandbox> list = JSON.parseArray(engineNode.getNodeScript(), Sandbox.class);
|
||||
//监控中心-- 节点配置信息记录(不需要策略层面的监控)
|
||||
JSONObject nodeSnapshot = new JSONObject();
|
||||
nodeSnapshot.put("nodeSnapshot",JSON.parseArray(engineNode.getNodeJson()));
|
||||
outMap.put("nodeSnapshot",nodeSnapshot);
|
||||
JSONObject nodeInfo = new JSONObject();
|
||||
nodeInfo.put("engineNode",engineNode);
|
||||
nodeInfo.put("nodeId",engineNode.getNodeId());
|
||||
nodeInfo.put("nodeName",engineNode.getNodeName());
|
||||
nodeInfo.put("nodeType",engineNode.getNodeType());
|
||||
outMap.put("nodeInfo",nodeInfo);
|
||||
int num = 0;//随机生成的数
|
||||
int startNum = 0;
|
||||
int endNum = 0;
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
Sandbox sandbox = list.get(i);
|
||||
endNum = startNum + sandbox.getProportion();
|
||||
if (num == 0)
|
||||
num = getRandoms(0, sandbox.getSum(), 1)[0];
|
||||
int[] range = getRandoms(startNum, endNum, sandbox.getProportion());
|
||||
for (int j = 0; j < range.length; j++) {
|
||||
if (range[j] == num) {
|
||||
if (StringUtils.isBlank(sandbox.getNextNode())) {
|
||||
List<Sandbox> sblist = JSON.parseArray(engineNode.getNodeJson(), Sandbox.class);
|
||||
for (Sandbox sb : sblist) {
|
||||
if (sb.getSandbox() == sandbox.getSandbox()) {
|
||||
sandbox.setNextNode(sb.getNextNode());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
outMap.put("nextNode", sandbox.getNextNode());
|
||||
JSONObject nodeResult = new JSONObject();
|
||||
nodeResult.put("nodeResult",sandbox.getNextNode());
|
||||
outMap.put("nodeResult",nodeResult);
|
||||
break;
|
||||
}
|
||||
}
|
||||
startNum = endNum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据min和max随机生成count个不重复的随机数组
|
||||
*
|
||||
* @param min
|
||||
* @param max
|
||||
* @param count
|
||||
* @return int[]
|
||||
*/
|
||||
public int[] getRandoms(int min, int max, int count) {
|
||||
int[] randoms = new int[count];
|
||||
List<Integer> listRandom = new ArrayList<Integer>();
|
||||
|
||||
if (count > (max - min + 1)) {
|
||||
return null;
|
||||
}
|
||||
// 将所有的可能出现的数字放进候选list
|
||||
for (int i = min; i < max; i++) {
|
||||
listRandom.add(i);
|
||||
}
|
||||
// 从候选list中取出放入数组,已经被选中的就从这个list中移除
|
||||
for (int i = 0; i < count; i++) {
|
||||
int index = getRandom(0, listRandom.size() - 1);
|
||||
randoms[i] = listRandom.get(index);
|
||||
listRandom.remove(index);
|
||||
}
|
||||
|
||||
return randoms;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据min和max随机生成一个范围在[min,max]的随机数,包括min和max
|
||||
*
|
||||
* @param min
|
||||
* @param max
|
||||
* @return int
|
||||
*/
|
||||
public int getRandom(int min, int max) {
|
||||
Random random = new Random();
|
||||
return random.nextInt(max - min + 1) + min;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
package com.fibo.ddp.enginex.runner.node.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.fibo.ddp.common.model.datax.datamanage.Field;
|
||||
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
|
||||
import com.fibo.ddp.common.model.strategyx.scorecard.ScorecardDetail;
|
||||
import com.fibo.ddp.common.model.strategyx.scorecard.ScorecardDimension;
|
||||
import com.fibo.ddp.common.model.strategyx.scorecard.vo.ScorecardDetailVo;
|
||||
import com.fibo.ddp.common.model.strategyx.scorecard.vo.ScorecardDimensionVo;
|
||||
import com.fibo.ddp.common.model.strategyx.scorecard.vo.ScorecardVersionVo;
|
||||
import com.fibo.ddp.common.model.strategyx.scorecard.vo.ScorecardVo;
|
||||
import com.fibo.ddp.common.service.datax.datamanage.FieldService;
|
||||
import com.fibo.ddp.common.service.datax.runner.CommonService;
|
||||
import com.fibo.ddp.common.service.datax.runner.ExecuteUtils;
|
||||
import com.fibo.ddp.common.service.strategyx.scorecard.ScorecardDetailService;
|
||||
import com.fibo.ddp.common.service.strategyx.scorecard.ScorecardDimensionService;
|
||||
import com.fibo.ddp.common.service.strategyx.scorecard.ScorecardService;
|
||||
import com.fibo.ddp.common.utils.util.runner.JevalUtil;
|
||||
import com.fibo.ddp.common.utils.util.runner.StrUtils;
|
||||
import com.fibo.ddp.common.utils.util.runner.jeval.EvaluationException;
|
||||
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class ScorecardNode implements EngineRunnerNode {
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Autowired
|
||||
private CommonService commonService;
|
||||
|
||||
@Resource
|
||||
public FieldService fieldService;
|
||||
|
||||
@Resource
|
||||
public ScorecardService scorecardService;
|
||||
|
||||
@Autowired
|
||||
private ScorecardDimensionService scorecardDimensionService; // 维度
|
||||
|
||||
@Autowired
|
||||
private ScorecardDetailService scorecardDetailService; // 明细
|
||||
|
||||
private List<Long> getExecuteVersionIdList(EngineNode engineNode) {
|
||||
return ExecuteUtils.getExecuteIdList(engineNode,"versionId");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
|
||||
List<Long> versionIdList = getExecuteVersionIdList(engineNode);
|
||||
Set<Long> fieldIdSet = new HashSet<>();
|
||||
for (Long versionId : versionIdList) {
|
||||
List<ScorecardDimension> scorecardDimensions = scorecardDimensionService.getDimensionListByVersionId(versionId);
|
||||
|
||||
List<Integer> dimensionIds = scorecardDimensions.stream().map(item -> item.getId()).collect(Collectors.toList());
|
||||
|
||||
List<ScorecardDetail> scorecardDetails = scorecardDetailService.getDetailListByDimensionIds(dimensionIds);
|
||||
fieldIdSet.addAll(scorecardDetails.stream().map(item -> Long.valueOf(item.getFieldId().toString())).collect(Collectors.toSet()));
|
||||
}
|
||||
List<Long> ids = new ArrayList<>(fieldIdSet);
|
||||
|
||||
commonService.getFieldByIds(ids, inputParam);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
|
||||
//监控中心--节点快照信息
|
||||
if (engineNode != null && engineNode.getSnapshot() != null) {
|
||||
outMap.put("nodeSnapshot", engineNode.getSnapshot());
|
||||
}
|
||||
List<Long> versionIdList = getExecuteVersionIdList(engineNode);
|
||||
for (Long versionId : versionIdList) {
|
||||
ScorecardVo scorecard = scorecardService.queryExecuteScorecard(versionId);
|
||||
JSONObject nodeInfo = new JSONObject();
|
||||
nodeInfo.put("engineNode", engineNode);
|
||||
nodeInfo.put("nodeId", engineNode.getNodeId());
|
||||
nodeInfo.put("nodeName", engineNode.getNodeName());
|
||||
nodeInfo.put("nodeType", engineNode.getNodeType());
|
||||
outMap.put("nodeInfo", nodeInfo);
|
||||
|
||||
List<ScorecardDetail> hitDetailList = new ArrayList<>(); // 命中的评分字段列表
|
||||
ScorecardVersionVo versionVo = scorecard.getExecuteVersion();
|
||||
List<ScorecardDimensionVo> scorecardDimensions = new ArrayList<>();
|
||||
if (versionVo != null) {
|
||||
//监控中心 == 策略层面快照信息
|
||||
if (versionVo != null && versionVo.getSnapshot() != null) {
|
||||
outMap.put("scorecardStrategy", versionVo.getSnapshot());
|
||||
}
|
||||
scorecardDimensions = versionVo.getScorecardDimension();
|
||||
for (ScorecardDimensionVo scorecardDimensionVo : scorecardDimensions) {
|
||||
List<ScorecardDetailVo> scorecardDetailVoList = scorecardDimensionVo.getChildren();
|
||||
scorecardHit(hitDetailList, 0, scorecardDetailVoList, inputParam);
|
||||
}
|
||||
}
|
||||
Double totalScore = 0d;
|
||||
List<JSONObject> scoreDetail = new ArrayList<>();
|
||||
for (ScorecardDimension scorecardDimension : scorecardDimensions) {
|
||||
Double dimensionScore = 0d;
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("dimensionName", scorecardDimension.getDimensionName());
|
||||
jsonObject.put("dimensionId", scorecardDimension.getId());
|
||||
for (ScorecardDetail scorecardDetail : hitDetailList) {
|
||||
if (!scorecardDetail.getDimensionId().equals(scorecardDimension.getId())) {
|
||||
continue;
|
||||
}
|
||||
String fieldEn = scorecardDetail.getFieldEn();
|
||||
Integer scoreCalculateType = scorecard.getScoreCalculateType();
|
||||
Integer calculateType = scorecardDetail.getCalculateType();
|
||||
// 计算方式为 得分
|
||||
if (calculateType == 1) {
|
||||
if (scoreCalculateType == 1) { // 评分计算方式为 求和
|
||||
Double value = scorecardDetail.getScore();
|
||||
totalScore += value;
|
||||
dimensionScore += value;
|
||||
} else if (scoreCalculateType == 2) { // 评分计算方式为 加权求和
|
||||
Double value = scorecardDetail.getScore() * scorecardDimension.getWeight();
|
||||
totalScore += value;
|
||||
dimensionScore += value;
|
||||
}
|
||||
}
|
||||
// 计算方式为 系数
|
||||
else if (calculateType == 2) {
|
||||
if (scoreCalculateType == 1) { // 评分计算方式为 求和
|
||||
Double value = Double.valueOf(inputParam.get(fieldEn).toString()) * scorecardDetail.getCoefficient();
|
||||
totalScore += value;
|
||||
dimensionScore += value;
|
||||
} else if (scoreCalculateType == 2) { // 评分计算方式为 加权求和
|
||||
Double value = Double.valueOf(inputParam.get(fieldEn).toString()) * scorecardDetail.getCoefficient() * scorecardDimension.getWeight();
|
||||
totalScore += value;
|
||||
dimensionScore += value;
|
||||
}
|
||||
}
|
||||
// 计算方式为 自定义
|
||||
else if (calculateType == 3) {
|
||||
double value = 0d;
|
||||
String custom = scorecardDetail.getCustom();
|
||||
if (custom != null && !"".equals(custom)) {
|
||||
Double result = StrUtils.strToDouble(ExecuteUtils.getObjFromScript(inputParam, custom).toString());
|
||||
if (result != null) {
|
||||
value = result;
|
||||
}
|
||||
}
|
||||
totalScore += value;
|
||||
dimensionScore += value;
|
||||
}
|
||||
}
|
||||
jsonObject.put("score", dimensionScore);
|
||||
scoreDetail.add(jsonObject);
|
||||
}
|
||||
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("nodeId", engineNode.getNodeId());
|
||||
jsonObject.put("nodeName", engineNode.getNodeName());
|
||||
jsonObject.put("cardId", scorecard.getId());
|
||||
jsonObject.put("cardName", scorecard.getName());
|
||||
jsonObject.put("cardCode", scorecard.getCode());
|
||||
String versionCode = "";
|
||||
Long cardVersionId = null;
|
||||
if (versionVo != null) {
|
||||
versionCode = versionVo.getVersionCode();
|
||||
cardVersionId = versionVo.getId();
|
||||
}
|
||||
|
||||
jsonObject.put("cardVersion", versionCode);
|
||||
jsonObject.put("cardVersionId",cardVersionId);
|
||||
jsonObject.put("desc", scorecard.getDescription());
|
||||
jsonObject.put("score", totalScore);
|
||||
jsonObject.put("scoreDetail", scoreDetail);
|
||||
//给入参中放入评分卡执行结果
|
||||
String resultFieldEn = versionVo.getResultFieldEn();
|
||||
if (StringUtils.isBlank(resultFieldEn)) {
|
||||
resultFieldEn = engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_" + versionVo.getId() + "_score";
|
||||
}
|
||||
inputParam.put(resultFieldEn, totalScore);
|
||||
inputParam.put(scorecard.getCode(), totalScore);
|
||||
List<JSONObject> fieldList = new ArrayList<>();
|
||||
JSONObject scoreResult = new JSONObject();
|
||||
scoreResult.put(resultFieldEn, totalScore);
|
||||
fieldList.add(scoreResult);
|
||||
if (totalScore != 0) {
|
||||
List<JSONObject> jsonObjects = scorecardService.setOutput(scorecard.getId(), inputParam);
|
||||
fieldList.addAll(jsonObjects);
|
||||
}
|
||||
jsonObject.put("fieldList", fieldList);
|
||||
//监控中心==》将评分卡的执行结果得分明细放入 输出变量池 用于存入hbase
|
||||
outMap.put("nodeResult", jsonObject);
|
||||
if (outMap.containsKey("scoreJson")) {
|
||||
JSONArray resultJson = (JSONArray) outMap.get("scoreJson");
|
||||
resultJson.add(jsonObject);
|
||||
} else {
|
||||
JSONArray resultJson = new JSONArray();
|
||||
resultJson.add(jsonObject);
|
||||
outMap.put("scoreJson", resultJson);
|
||||
}
|
||||
terminalCondition(engineNode,inputParam,outMap,totalScore);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 评分卡命中判断
|
||||
*
|
||||
* @param hitDetailList
|
||||
* @param detailId
|
||||
* @param scorecardDetailVoList
|
||||
* @param inputParam
|
||||
*/
|
||||
private void scorecardHit(List<ScorecardDetail> hitDetailList, Integer detailId, List<ScorecardDetailVo> scorecardDetailVoList, Map<String, Object> inputParam) {
|
||||
List<ScorecardDetailVo> scorecardDetailVos = scorecardDetailVoList.stream().filter(item -> item.getParentId().equals(detailId)).collect(Collectors.toList());
|
||||
for (ScorecardDetailVo scorecardDetailVo : scorecardDetailVos) {
|
||||
Field field = fieldService.queryById(Long.valueOf(scorecardDetailVo.getFieldId()));
|
||||
String fieldEn = field.getFieldEn();
|
||||
scorecardDetailVo.setFieldEn(fieldEn);
|
||||
|
||||
String condition = scorecardDetailVo.getCondition();
|
||||
Boolean isHit = isScoreFieldValue(inputParam, fieldEn, condition);
|
||||
if (isHit) {
|
||||
if (scorecardDetailVo.getType() == 1) {
|
||||
hitDetailList.add(scorecardDetailVo);
|
||||
} else {
|
||||
this.scorecardHit(hitDetailList, scorecardDetailVo.getId(), scorecardDetailVoList, inputParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 评分卡字段是否在区间内
|
||||
*
|
||||
* @param map
|
||||
* @param fieldCode
|
||||
* @param condition
|
||||
* @return
|
||||
*/
|
||||
private Boolean isScoreFieldValue(Map<String, Object> map, String fieldCode, String condition) {
|
||||
if ("(,)".equals(condition)) {
|
||||
return true;
|
||||
}
|
||||
String exp = JevalUtil.getNumericInterval(condition, fieldCode);
|
||||
try {
|
||||
if (JevalUtil.evaluateBoolean(exp, map)) {
|
||||
return true;
|
||||
}
|
||||
} catch (EvaluationException e) {
|
||||
e.printStackTrace();
|
||||
logger.error("请求异常", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void terminalCondition(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap,Object executeResult) {
|
||||
String resultKey = engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_terminal_score";
|
||||
Map<String,Object> map = new HashMap<>();
|
||||
map.put(resultKey,executeResult);
|
||||
ExecuteUtils.terminalCondition(engineNode,inputParam,outMap, map);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user