Browse Source

计算单元修改

JoeLazy 2 months ago
parent
commit
86fd9738fe

+ 10 - 1
src/main/java/com/sundata/internalevaluation/calc/calcUnit/InterfaceCalcUnit.java

@@ -3,11 +3,14 @@ package com.sundata.internalevaluation.calc.calcUnit;
 import cn.hutool.http.HttpRequest;
 import cn.hutool.http.HttpUtil;
 import com.sundata.common.util.JsonUtil;
+import com.sundata.internalevaluation.calc.model.CalcException;
 import com.sundata.internalevaluation.calc.model.CalcResult;
 import com.sundata.internalevaluation.calc.model.CalcUnit;
 import com.sundata.internalevaluation.calc.model.finals.CalcType;
 import com.sundata.internalevaluation.configuration.model.SysInterface;
 import com.sundata.internalevaluation.configuration.model.SysInterfaceParam;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.HashMap;
 import java.util.List;
@@ -23,6 +26,8 @@ import java.util.stream.Collectors;
  */
 public class InterfaceCalcUnit extends CalcUnit {
 
+    private static final Logger log = LoggerFactory.getLogger(InterfaceCalcUnit.class);
+
 
     private final SysInterface sysInterface;
 
@@ -110,6 +115,9 @@ public class InterfaceCalcUnit extends CalcUnit {
                      Map<String, Object> context,
                      Map<CalcUnit, CalcResult<String, Object>> sourceResults) {
 
+        log.debug("计算{}:编号:{},名称:{},流水号:{}", getCalcType().getName(),getCalcCode(),getCalcName(),calculateInstanceNumber);
+
+
         // 接口内容类型
         String reqContentTypeCode = this.sysInterface.getReqContentTypeCode();
         // 接口请求类型
@@ -141,7 +149,8 @@ public class InterfaceCalcUnit extends CalcUnit {
             thisResult.put(getCalcCode(), JsonUtil.jsonToMap(responseStr));
         } else {
             // TODO Socket 请求
-            thisResult.put(getCalcCode(), "非http、https请求,并且参数不是json格式");
+            throw new CalcException("目前仅支持http和https的请求");
+//            thisResult.put(getCalcCode(), "非http、https请求,并且参数不是json格式");
         }
     }
 }

+ 16 - 3
src/main/java/com/sundata/internalevaluation/calc/calcUnit/InterfaceParamCalcUnit.java

@@ -2,11 +2,15 @@ package com.sundata.internalevaluation.calc.calcUnit;
 
 import com.sundata.common.util.DBExecutor;
 import com.sundata.common.util.JsonUtil;
+import com.sundata.internalevaluation.calc.model.CalcException;
 import com.sundata.internalevaluation.calc.model.CalcResult;
 import com.sundata.internalevaluation.calc.model.CalcUnit;
 import com.sundata.internalevaluation.calc.model.finals.CalcType;
 import com.sundata.internalevaluation.calc.util.InvokeUtil;
+import com.sundata.internalevaluation.calc.util.SqlUtil;
 import com.sundata.internalevaluation.configuration.model.SysInterfaceParam;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.List;
 import java.util.Map;
@@ -20,6 +24,8 @@ import java.util.Map;
  */
 public class InterfaceParamCalcUnit extends CalcUnit {
 
+    private static final Logger log = LoggerFactory.getLogger(InterfaceParamCalcUnit.class);
+
     /**
      * 接口参数实体
      */
@@ -101,6 +107,11 @@ public class InterfaceParamCalcUnit extends CalcUnit {
      */
     @Override
     public void calc(CalcResult<String, Object> thisResult, String calculateInstanceNumber, Map<String, Object> context, Map<CalcUnit, CalcResult<String, Object>> sourceResults) {
+
+
+        log.debug("计算{}:编号:{},名称:{},流水号:{}", getCalcType().getName(),getCalcCode(),getCalcName(),calculateInstanceNumber);
+
+
         // 参数获取类型
         String paramRetrievalTypeCode = sysInterfaceParam.getParamRetrievalTypeCode();
 
@@ -127,15 +138,15 @@ public class InterfaceParamCalcUnit extends CalcUnit {
                 break;
             // SQL-Map
             case "sqlmap":
-                result = DBExecutor.doQuery(paramRetrievalTypeCont);
+                result = DBExecutor.doQuery(SqlUtil.sqlFormat(paramRetrievalTypeCont, context));
                 break;
             // SQL-List
             case "sqllist":
-                result = DBExecutor.doQueryMapList(paramRetrievalTypeCont);
+                result = DBExecutor.doQueryMapList(SqlUtil.sqlFormat(paramRetrievalTypeCont, context));
                 break;
             // SQL-String
             case "sqlstring":
-                result = DBExecutor.doQuery(paramRetrievalTypeCont);
+                result = DBExecutor.doQuery(SqlUtil.sqlFormat(paramRetrievalTypeCont, context));
                 break;
         }
 
@@ -168,6 +179,8 @@ public class InterfaceParamCalcUnit extends CalcUnit {
             } else {
                 throw new RuntimeException("数据类型不匹配:计算机过不为'数字'");
             }
+        } else {
+            throw new CalcException("返回值类型有无,目前仅有 数字和字符串");
         }
         thisResult.put(getCalcCode(), result);
         thisResult.put("entity", sysInterfaceParam);

+ 27 - 20
src/main/java/com/sundata/internalevaluation/calc/calcUnit/RuleCalcUnit.java

@@ -1,7 +1,6 @@
 package com.sundata.internalevaluation.calc.calcUnit;
 
 import cn.hutool.extra.spring.SpringUtil;
-import com.sundata.common.util.StringUtil;
 import com.sundata.internalevaluation.calc.model.CalcResult;
 import com.sundata.internalevaluation.calc.model.CalcUnit;
 import com.sundata.internalevaluation.calc.model.finals.CalcType;
@@ -10,7 +9,10 @@ import com.sundata.internalevaluation.configuration.model.SysReqRule;
 import com.sundata.internalevaluation.configuration.service.IndexConfigService;
 import com.sundata.internalevaluation.script.ScriptUtil;
 import com.sundata.internalevaluation.script.TemplateUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
@@ -24,6 +26,8 @@ import java.util.stream.Collectors;
  */
 public class RuleCalcUnit extends CalcUnit {
 
+    private static final Logger log = LoggerFactory.getLogger(RuleCalcUnit.class);
+
     private SysReqRule reqRule;
 
     private final IndexConfigService indexConfigService;
@@ -50,6 +54,10 @@ public class RuleCalcUnit extends CalcUnit {
      */
     @Override
     public boolean isCalcFinished(String calculateInstanceNumber) {
+
+        //calculateInstanceNumber
+//        getCalcCode()
+//        getCalcType().getName();
         // TODO  是否计算完成
         return false;
     }
@@ -110,30 +118,29 @@ public class RuleCalcUnit extends CalcUnit {
                      String calculateInstanceNumber,
                      Map<String, Object> context,
                      Map<CalcUnit, CalcResult<String, Object>> sourceResults) {
+        log.debug("计算{}:编号:{},名称:{},流水号:{}", getCalcType().getName(),getCalcCode(),getCalcName(),calculateInstanceNumber);
 
-        // 获取道规则的计算模板或脚本
-        String ruleTemplate = this.reqRule.getRuleTemplate();
 
-        // 模板或脚本需要的参数
-        // TODO 根据实际情况获取
-        Map<String, Object> initContext = this.getInitContext();
+        // 所有规则计算的结果
+        Map<String, Object> indexResult = new HashMap<>();
+
+        sourceResults.forEach((calcUnit, calcResult) -> {
+            indexResult.put(calcUnit.getCalcCode(), calcResult.get(calcUnit.getCalcCode()));
+        });
+
+        // 规则的模板
+        String ruleTemplate = this.reqRule.getRuleTemplate();
 
-        // 执行脚本  获取结果
-        Object res = ScriptUtil.executeScript(String.valueOf(System.currentTimeMillis()), ruleTemplate, initContext);
+        // 实际值替换变量
+        String script = TemplateUtil.execute("template-rule-" + getCalcCode(), ruleTemplate, indexResult);
 
-        // 填充结果
-        // true 表示出发规则 所以执行规则结果
-        // false 未触发  所以 无执行
-        thisResult.put(this.getCalcCode(), res.equals(true) ? reqRule.getRuleResult():"none");
+        // 执行脚本
+        Object res = ScriptUtil.executeScript("script-rule-" + getCalcCode(), script, indexResult);
 
+        // 放计算结果
+        thisResult.put(this.getCalcCode(), res);
 
-        // ******************************
-        String ruleConclusionTemplate = this.reqRule.getRuleConclusionTemplate();
-        if (StringUtil.isNotEmpty(ruleConclusionTemplate)) {
-            String result = TemplateUtil.execute("tempNo" + System.currentTimeMillis(), ruleConclusionTemplate, Map.of("result", res));
-            System.err.printf("%s-%s-结论:%s\n\r", this.getCalcCode(), this.getCalcName(), result);
-        } else {
-            System.err.printf("%s-%s-[没有结论模板]....\n\r", this.getCalcCode(), this.getCalcName());
-        }
+        // 放实体
+        thisResult.put("entity", this.reqRule);
     }
 }

+ 39 - 27
src/main/java/com/sundata/internalevaluation/calc/calcUnit/RulesCalcUnit.java

@@ -1,13 +1,11 @@
 package com.sundata.internalevaluation.calc.calcUnit;
 
-import cn.hutool.extra.spring.SpringUtil;
 import com.sundata.internalevaluation.calc.model.CalcResult;
 import com.sundata.internalevaluation.calc.model.CalcUnit;
 import com.sundata.internalevaluation.calc.model.finals.CalcType;
 import com.sundata.internalevaluation.configuration.model.SysReqRule;
 import com.sundata.internalevaluation.configuration.model.SysReqRules;
 import com.sundata.internalevaluation.configuration.service.SysReqRuleService;
-import com.sundata.internalevaluation.configuration.service.SysReqRulesService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -103,8 +101,8 @@ public class RulesCalcUnit extends CalcUnit {
     public List<CalcUnit> getSourceCalcUnits() {
         List<SysReqRule> sysReqRules = sysReqRuleService.selectRuleListByRulesNo(reqRules.getRulesNo());
         return sysReqRules.stream()
-                .map(rule-> new RuleCalcUnit(rule.getRuleNo(),rule.getRuleName(),
-                        CalcType.RULE, Map.of("age",15), rule)).collect(Collectors.toList());
+                .map(rule -> new RuleCalcUnit(rule.getRuleNo(), rule.getRuleName(),
+                        CalcType.RULE, Map.of(), rule)).collect(Collectors.toList());
 
     }
 
@@ -132,7 +130,7 @@ public class RulesCalcUnit extends CalcUnit {
     /**
      * 必须实现的主体计算内容
      *
-     * @param context 节点计算参数清单
+     * @param context       节点计算参数清单
      * @param sourceResults 源头计算节点的结果
      */
     @Override
@@ -141,33 +139,47 @@ public class RulesCalcUnit extends CalcUnit {
                      Map<String, Object> context,
                      Map<CalcUnit, CalcResult<String, Object>> sourceResults) {
 
-        Map<Object, List<CalcUnit>> collect = sourceResults.entrySet().stream()
-                .collect(Collectors.groupingBy(
-                        s -> s.getValue().get(s.getKey().getCalcCode()),
-                        Collectors.mapping(Map.Entry::getKey, Collectors.toList()))
-                );
-
-        List<CalcUnit> intercept = collect.get("intercept");
-        StringBuilder sb = new StringBuilder();
-        if (intercept != null && !intercept.isEmpty()) {
-            sb.append("触发拦截规则:\n");
-            intercept.forEach(a -> {
-                sb.append(" ·").append(a.getCalcCode()).append("-").append(a.getCalcName()).append("\n");
-            });
-            thisResult.put(this.getCalcCode(),sb.toString());
+        log.debug("计算{}:编号:{},名称:{},流水号:{}", getCalcType().getName(),getCalcCode(),getCalcName(),calculateInstanceNumber);
+
+        // 规则结果为 true 的规则
+        List<Map.Entry<CalcUnit, CalcResult<String, Object>>> resIsTrue = sourceResults.entrySet().stream()
+                .filter(entry -> entry.getValue().get(entry.getKey().getCalcCode()).equals(true))
+                .collect(Collectors.toList());
+
+        //
+        Map<String, List<SysReqRule>> ruleListMap = resIsTrue.stream()
+                .collect(Collectors.groupingBy(e1 -> {
+                    SysReqRule o = (SysReqRule) e1.getValue().get("entity");
+                    return o.getRuleResult();
+                }, Collectors.mapping(e ->
+                        (SysReqRule) e.getValue().get("entity"), Collectors.toList()
+                )));
+
+
+        List<SysReqRule> interceptRuleList = ruleListMap.get("intercept");
+        List<SysReqRule> warnRuleList = ruleListMap.get("warn");
+
+        if (interceptRuleList != null && !interceptRuleList.isEmpty()) {
+            // 存在拦截的规则
+            // TODO  拦截处理
+            List<String> resList = interceptRuleList.stream().map(rule -> String.format("【%s】%s 触发 %s", rule.getRuleNo(), rule.getRuleName(), "拦截")).collect(Collectors.toList());
+            thisResult.put(getCalcCode(),resList);
             return;
         }
 
-        List<CalcUnit> warn = collect.get("warn");
-        if (warn != null && !warn.isEmpty()) {
-            sb.append("触发预警规则:\n");
-            warn.forEach(a -> {
-                sb.append(" ·").append(a.getCalcCode()).append("-").append(a.getCalcName()).append("\n");
-            });
-            thisResult.put(this.getCalcCode(),sb.toString());
+
+
+        if (warnRuleList != null && !warnRuleList.isEmpty()) {
+            // 存在预警的规则
+            // TODO  预警处理
+            List<String> resList = warnRuleList.stream().map(rule -> String.format("【%s】%s 触发 %s", rule.getRuleNo(), rule.getRuleName(), "预警")).collect(Collectors.toList());
+            thisResult.put(getCalcCode(),resList);
             return;
         }
 
-        thisResult.put(this.getCalcCode(),"规则集未拦截");
+
+        // 无拦截和预警
+        thisResult.put(this.getCalcCode(), "无拦截");
+
     }
 }

+ 59 - 0
src/main/java/com/sundata/internalevaluation/calc/custom/GetDataTest.java

@@ -2,6 +2,8 @@ package com.sundata.internalevaluation.calc.custom;
 
 import java.text.SimpleDateFormat;
 import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * Created by IntelliJ IDEA.
@@ -57,4 +59,61 @@ public class GetDataTest {
         return str;
     }
 
+
+//    public void aa() {
+//        // 模板字符${value}的正则表达式
+//        String regex = "\\$\\{([^}]+)}";
+//        // 生成正则表达式对象
+//        Pattern pattern = Pattern.compile(regex);
+//
+//        // 应入参数
+//        String[] values = {"workDate","account","orgcode","TaskId","TaskSerialNum"};
+//        // 替换模板字符用
+//        Map<String,String> inputMap = new HashMap<String,String>();
+//        // 造假参数
+//        inputMap.put("workDate","'a'");
+//        inputMap.put("account","'a'");
+//        inputMap.put("orgcode","'a'");
+//        inputMap.put("TaskId","'a'");
+//        inputMap.put("TaskSerialNum","'a'");
+//        // 使用apache的StrSubstitutor替换模板字符
+//        StrSubstitutor sub = new StrSubstitutor(inputMap);
+//
+//
+//        // 对请求中的数据逻辑说明的sql进行正则匹配
+//        Matcher matcher = pattern.matcher(relationModel.getSqlCode());
+//        // 判断缺失参数用
+//        ArrayList<String> paramList = new ArrayList<String>(Arrays.asList(values));
+//        // 游标
+//        int matcherCount = 0;
+//        // 检查开始
+//        while (matcher.find()) {
+//            if (!paramList.contains(matcher.group(1))) {
+//                String err = "数据初始化逻辑中,该参数[" + matcher.group(1) + "]不应存在!";
+//                log.error(err);
+//                throw new BusinessException(err);
+//            } else {
+//                // 排除不缺失参数
+//                paramList.remove(matcher.group(1));
+//            }
+//            matcherCount++;
+//        }
+//
+//        // 假参数赋值
+//        String resolvedString = sub.replace(relationModel.getSqlCode());
+//    }
+
+
+
+    public static void main(String[] args) {
+        String sql = "select * from a where a = ${a} and b = ${b} and c =${a}";
+        Map<String, Object> map = new HashMap<>();
+
+        map.put("a", "isA");
+        map.put("b", "isB");
+
+
+//        bb(sql, map);
+    }
+
 }

+ 25 - 0
src/main/java/com/sundata/internalevaluation/calc/util/CalcUtil.java

@@ -1,8 +1,15 @@
 package com.sundata.internalevaluation.calc.util;
 
+import cn.hutool.extra.spring.SpringUtil;
+import com.sundata.internalevaluation.calc.calcUnit.RulesCalcUnit;
+import com.sundata.internalevaluation.calc.model.CalcException;
 import com.sundata.internalevaluation.calc.model.CalcUnit;
 import com.sundata.internalevaluation.calc.running.CalcRunning;
 import com.sundata.internalevaluation.calc.running.threads.CalcTaskResult;
+import com.sundata.internalevaluation.configuration.model.SysReqRules;
+import com.sundata.internalevaluation.configuration.service.SysReqRuleService;
+import com.sundata.internalevaluation.configuration.service.SysReqRulesService;
+import org.apache.commons.lang3.StringUtils;
 
 import java.util.Map;
 
@@ -20,4 +27,22 @@ public class CalcUtil {
     public static CalcTaskResult calc(String calculateInstanceNumber, CalcUnit calcUnit, Map<String, Object> context) {
         return new CalcRunning().startCalc(calculateInstanceNumber, calcUnit, context);
     }
+
+    /**
+     * 计算规则
+     * @param calculateInstanceNumber 计算流水号
+     * @param rulesNo 规则集编号
+     * @param context 参数  网贷传入的报文
+     * @return 计算结果
+     */
+    public static CalcTaskResult calcRules(String calculateInstanceNumber, String rulesNo, Map<String, Object> context) {
+        if (StringUtils.isNotBlank(rulesNo)) {
+            throw new CalcException("数据集编号不能为空!!!");
+        }
+        SysReqRulesService rulesService = SpringUtil.getBean(SysReqRulesService.class);
+        SysReqRules rules = rulesService.getById(rulesNo);
+
+        CalcUnit calcUnit = new RulesCalcUnit(rules.getRulesNo(),rules.getRulesName(),Map.of(),rules,SpringUtil.getBean(SysReqRuleService.class));
+        return calc(calculateInstanceNumber, calcUnit, context);
+    }
 }

+ 66 - 0
src/main/java/com/sundata/internalevaluation/calc/util/JsonToCalciteUtil.java

@@ -0,0 +1,66 @@
+package com.sundata.internalevaluation.calc.util;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.calcite.adapter.file.JsonScannableTable;
+import org.apache.calcite.jdbc.CalciteConnection;
+import org.apache.calcite.schema.SchemaPlus;
+import org.apache.calcite.schema.impl.AbstractSchema;
+import org.apache.calcite.util.Sources;
+
+import java.sql.*;
+
+/**
+ * Created by IntelliJ IDEA.
+ *
+ * @author JoeLazy
+ * @date 2025-02-18 11:44:07
+ * @description: json转虚拟表
+ */
+public class JsonToCalciteUtil {
+
+    private Connection connection = null;
+
+    private Statement statement = null;
+
+    private ResultSet resultSet = null;
+
+    public ResultSet jsonToResultSet(String jsonStr, String sql) throws SQLException, JsonProcessingException {
+        // 1. 使用 Jackson 解析 JSON 数据
+        ObjectMapper objectMapper = new ObjectMapper();
+        JsonNode rootNode = objectMapper.readTree(jsonStr);
+
+        //2. 创建 Calcite Schema
+        connection = DriverManager.getConnection("jdbc:calcite:");
+        CalciteConnection calciteConnection = connection.unwrap(CalciteConnection.class);
+
+        SchemaPlus rootSchema = calciteConnection.getRootSchema();
+        rootSchema.add("credite", new AbstractSchema());
+
+        // 注册 JSON 数据为表
+        rootNode.fields().forEachRemaining(entry -> {
+            String tableName = entry.getKey();
+            JsonNode tableData = entry.getValue();
+            rootSchema.add(tableName, new JsonScannableTable(Sources.of(tableData.toString())));
+        });
+
+        // 4. 执行 SQL 查询
+        statement = connection.createStatement();
+        return resultSet = statement.executeQuery(sql);
+    }
+
+    public void closeResource() throws SQLException {
+        // 关闭连接
+        if (resultSet != null) {
+            resultSet.close();
+        }
+        if (statement != null) {
+            statement.close();
+        }
+        if (connection != null) {
+            connection.close();
+        }
+    }
+
+}

+ 32 - 0
src/main/java/com/sundata/internalevaluation/calc/util/SqlUtil.java

@@ -0,0 +1,32 @@
+package com.sundata.internalevaluation.calc.util;
+
+import org.apache.commons.lang.text.StrSubstitutor;
+
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Created by IntelliJ IDEA.
+ *
+ * @author JoeLazy
+ * @date 2025-02-17 16:16:49
+ * @description: sql语句工具类
+ */
+public class SqlUtil {
+
+    public static String sqlFormat(String sql, Map<String, Object> map) {
+
+        // 模板字符${value}的正则表达式
+        String regex = "\\$\\{([^}]+)}";
+        // 生成正则表达式对象
+        Pattern pattern = Pattern.compile(regex);
+        // 对请求中的数据逻辑说明的sql进行正则匹配
+        Matcher matcher = pattern.matcher(sql);
+        StrSubstitutor sub = new StrSubstitutor(map);
+
+        return sub.replace(sql);
+
+    }
+
+}