123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316 |
- package com.sundata.internalevaluation.calc.calcUnit;
- import cn.hutool.core.convert.Convert;
- import cn.hutool.core.util.StrUtil;
- import cn.hutool.extra.spring.SpringUtil;
- import com.sundata.common.exception.BusinessException;
- 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.CalciteUtil;
- import com.sundata.internalevaluation.configuration.model.DataSetModel;
- import com.sundata.internalevaluation.configuration.model.IndexModel;
- import com.sundata.internalevaluation.configuration.model.IndexSourceModel;
- import com.sundata.internalevaluation.configuration.service.DataSetService;
- import com.sundata.internalevaluation.configuration.service.IndexConfigService;
- import com.sundata.internalevaluation.script.ScriptUtil;
- import com.sundata.internalevaluation.script.TemplateUtil;
- import org.apache.calcite.schema.impl.AbstractSchema;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import java.sql.SQLException;
- import java.util.*;
- import java.util.concurrent.atomic.AtomicInteger;
- import java.util.stream.Collectors;
- public class IndexCalcUnit extends CalcUnit {
- private final IndexModel indexConfigModel;
- private static final Logger log = LoggerFactory.getLogger(IndexCalcUnit.class);
- // 接收表集
- private Set<String> tableSet = null;
- /**
- * 创建数据单元的绝对对象,对象必须包含如下参数
- *
- * @param calcCode 计算对象编号
- * @param calcName 计算对象名称
- * @param initContext 计算单元初始化参数
- */
- public IndexCalcUnit(String calcCode, String calcName, Map<String, Object> initContext, IndexModel indexConfigModel) {
- super(calcCode, calcName, CalcType.INDEX, initContext);
- this.indexConfigModel = indexConfigModel;
- }
- /**
- * 判断是否已经计算过数据了
- *
- * @param calculateInstanceNumber 计算流水号
- * @return 是否计算过 true 计算过 false 没有计算过
- */
- @Override
- public boolean isCalcFinished(String calculateInstanceNumber) {
- // TODO 计算是否已经计算
- return false;
- // return DataImages.indexCalcUnitHashMap.containsKey(calculateInstanceNumber) && DataImages.indexCalcUnitHashMap.get(calculateInstanceNumber).stream().anyMatch(a -> a.getCalcCode().equals(this.getCalcCode()));
- }
- /**
- * 初始化计算结果的方法,如果已经计算过,在实现过程中,应当在此方法中根据计算流水号重新初始化 resultContext 结果对象,为其他依赖对象做准备
- * 若明明计算过本单元但再次计算时没有初始化该对象,则计算依赖出现问题无法定位与处理
- *
- * @param calculateInstanceNumber 计算流水号
- */
- @Override
- public void initResultContext(String calculateInstanceNumber) {
- // TODO 初始化
- // List<IndexCalcUnit> indexCalcUnits = new ArrayList<>();
- //// List<IndexCalcUnit> indexCalcUnits = DataImages.indexCalcUnitHashMap.get(calculateInstanceNumber);
- // // 筛选并查找对象,如果找不到则报错
- // if (indexCalcUnits.stream().noneMatch(a -> a.getCalcCode().equals(this.getCalcCode()))) {
- // throw new CalcException(calculateInstanceNumber, StrUtil.format("无法找到已计算完成的结果,计算单元编号:{},计算流水号为:{}。", this.getCalcCode(), calculateInstanceNumber));
- // }
- // this.setResultContext(indexCalcUnits.stream().filter(a -> a.getCalcCode().equals(this.getCalcCode())).findFirst().get().getResultContext());
- }
- /**
- * 根据节点配置获取源节点;
- *
- * @return 所有源头节点
- */
- @Override
- public List<CalcUnit> getSourceCalcUnits() {
- // TODO 获取源头节点
- DataSetService dataSetService = SpringUtil.getBean(DataSetService.class);
- IndexConfigService indexConfigService = SpringUtil.getBean(IndexConfigService.class);
- List<IndexSourceModel> selectList = indexConfigService.getIndexSourceList(this.indexConfigModel);
- // 定义存放数据集和其他指标的集合
- List<IndexModel> indexList = new ArrayList<>();
- List<DataSetModel> dataSetList = new ArrayList<>();
- // 查询个指标编号和数据集对应的数据
- for ( IndexSourceModel m : selectList) {
- if ("DATASET".equals(m.getDataSourceType())) {
- DataSetModel conditionModel = new DataSetModel();
- conditionModel.setDataSetNo(m.getDataSetNo());
- DataSetModel datasetModel = dataSetService.selectDetailData(conditionModel);
- dataSetList.add(datasetModel);
- } else if ("INDEX".equals(m.getDataSourceType())) {
- IndexModel conditionModel = new IndexModel();
- conditionModel.setIndexNo(m.getOtherIndexNo());
- IndexModel indexConfigModel = indexConfigService.selectDetailData(conditionModel);
- indexList.add(indexConfigModel);
- }
- }
- List<CalcUnit> indexCalcList = null;
- List<CalcUnit> dataSetCalcList = null;
- List<CalcUnit> resultCalcMap = new ArrayList<>();
- // 数据源头节点生成
- if (!indexList.isEmpty()) {
- indexCalcList = indexList.stream().map(indexConfigModel -> new IndexCalcUnit
- (indexConfigModel.getIndexNo(),indexConfigModel.getIndexName(),Map.of(),indexConfigModel)).collect(Collectors.toList());
- }
- if (!dataSetList.isEmpty()) {
- dataSetCalcList = dataSetList.stream().map(dataSetModel -> new DataSetCalcUnit
- (dataSetModel.getDataSetNo(),dataSetModel.getDataSetName(),Map.of(),dataSetModel)).collect(Collectors.toList());
- }
- // 结果封装
- if (null != indexCalcList) {
- resultCalcMap.addAll(indexCalcList);
- }
- if (null != dataSetCalcList) {
- resultCalcMap.addAll(dataSetCalcList);
- }
- // 返回所有源头节点
- return resultCalcMap;
- }
- /**
- * 计算之后的方法,可实现为空
- *
- * @param context 计算参数过程数据
- */
- @Override
- public void afterCalc(Map<String, Object> context) {
- log.debug("计算之后的参数结构:{}",context);
- }
- /**
- * 计算之前,可实现空
- *
- * @param context 计算参数过程数据
- */
- @Override
- public void beforeCalc(Map<String, Object> context) {
- log.debug("计算之前的参数结构:{}",context);
- }
- /**
- * 必须实现的主体计算内容
- *
- * @param context 节点计算参数清单
- * @param sourceResults 整个计算过程中的节点结果
- */
- @Override
- public void calc(final CalcResult<String, Object> thisResult, String calculateInstanceNumber, Map<String, Object> context, Map<CalcUnit, CalcResult<String, Object>> sourceResults) {
- //
- log.info("当前计算节点为:[{}-{}-{}],计算流水号为:{}", this.getCalcType(), this.getCalcCode(), this.getCalcName(), calculateInstanceNumber);
- // TODO 实际的计算过程
- // 记录数据集出现次数
- AtomicInteger dataSetNumber = new AtomicInteger();
- // 记录其他指标出现次数
- AtomicInteger indexNumber = new AtomicInteger();
- // 声明只存放指标源头节点变量
- Map<String, Object> indexResult = new HashMap<>();
- // 声明只存放所有数据集源头节点变量
- Map<String, AbstractSchema> dataSetResult = new HashMap<>();
- // 遍历结果集
- sourceResults.forEach((calcUnit,result) -> {
- // 数据集
- if ( calcUnit instanceof DataSetCalcUnit dataSetCalcUnit){
- if(dataSetCalcUnit.getCalcType() == CalcType.DATASET){
- // 记录记过集次数
- dataSetNumber.getAndIncrement();
- // 将源头节点的返回值取出
- // dataSetResult.putAll(result);
- String calcCode = calcUnit.getCalcCode();
- Object schemeObj = result.get(calcCode);
- if (schemeObj instanceof AbstractSchema schema) {
- dataSetResult.put(calcCode,schema);
- } else {
- String errorMsg = StrUtil.format("数据集-[{}({})]-返回的计算结果不是AbstractSchema类型",calcUnit.getCalcName(),calcCode);
- log.error(errorMsg);
- throw new CalcException(errorMsg);
- }
- }
- }
- // 其他指标
- if( calcUnit instanceof IndexCalcUnit indexCalcUnit){
- if(indexCalcUnit.getCalcType() == CalcType.INDEX){
- // 记录指标出现次数
- indexNumber.getAndIncrement();
- // 记录指标节点的返回值
- indexResult.putAll(result);
- }
- }
- });
- // 定义指标结果变量
- Object indexCalcResult = null;
- // 获取指标计算逻辑
- String calcLogic = indexConfigModel.getIndexLogic();
- if (dataSetNumber.get() > 0 && indexNumber.get() == 0){
- // 如果数据集的数量大于0(只依赖数据集)
- indexCalcResult = doExecuteSql(dataSetResult,calcLogic);
- } else if(dataSetNumber.get() == 0 && indexNumber.get() > 0){
- // 如果指标的数量大于0(只依赖其他指标)
- // 执行公式,结果放入结果集
- indexCalcResult = ScriptUtil.executeScript(indexConfigModel.getIndexNo(),calcLogic,indexResult);
- } else if (dataSetNumber.get() > 0 && indexNumber.get() >0) {
- // 同时具有指标和数据集
- // 先将sql中指标公式替换掉,再将得到的sql执行
- String editSql = TemplateUtil.execute(indexConfigModel.getIndexNo(),calcLogic,indexResult);
- // 执行拿结果
- indexCalcResult = doExecuteSql(dataSetResult,editSql);
- } else {
- // 既不依赖其他指标,也不依赖数据集
- // 执行公式,结果放入结果集
- indexCalcResult = ScriptUtil.executeScript(indexConfigModel.getIndexNo(),calcLogic,indexResult);
- }
- // *********************** 处理指标结果为null的情况
- if (null != indexCalcResult) {
- thisResult.put(this.getCalcCode(),indexCalcResult);
- } else {
- String defaultValueType = this.indexConfigModel.getDefaultValueType();
- String defaultValue = this.indexConfigModel.getDefaultValue();
- indexCalcResult = getDefaultValue(defaultValue,defaultValueType);
- thisResult.put(this.getCalcCode(),indexCalcResult);
- }
- }
- /**
- * 执行sql获取结果
- * @param dataSetResult 数据集
- * @param logic 指标计算逻辑
- * @return 计算结果
- */
- private Object doExecuteSql(Map<String,AbstractSchema> dataSetResult,String logic) {
- // 执行sql的工具类实例
- CalciteUtil finalInstance;
- try {
- // 创建示例
- CalciteUtil instance = CalciteUtil.getInstance();
- // 添加域
- dataSetResult.forEach(instance::addSchema);
- finalInstance = instance;
- } catch (SQLException e) {
- log.error(e.getMessage());
- throw new BusinessException(e.getMessage(),e);
- }
- try {
- // 执行sql返回姐果
- return finalInstance.doExecute(logic);
- } catch (SQLException e) {
- throw new RuntimeException(e);
- }
- }
- /**
- * 获取默认值
- * @param defaultValue 默认值
- * @param defaultValueType 默认值类型
- * @return 转化后值
- */
- private Object getDefaultValue(String defaultValue, String defaultValueType) {
- Object castValue = null;
- if (StrUtil.isNotBlank(defaultValue) && StrUtil.isNotBlank(defaultValueType)) {
- try {
- switch (defaultValueType) {
- case "INT":
- castValue = Convert.toInt(defaultValue);
- break;
- case "STRING":
- castValue = defaultValue;
- break;
- case "BOOLEAN":
- castValue = Convert.toBool(defaultValue);
- break;
- case "BIGDECIMAL":
- castValue = Convert.toBigDecimal(defaultValue);
- break;
- }
- if (null ==castValue) {
- String error = StrUtil.format("指标-[{}({})]-默认值转换失败,期望类型为[{}],待转换的值为[{}]。", getCalcName(),getCalcCode(),defaultValueType,defaultValue);
- log.error(error);
- throw new ClassCastException(error);
- }
- } catch (ClassCastException e) {
- throw new BusinessException(e.getMessage());
- }
- } else {
- String error = StrUtil.format("指标-[{}({})]-计算结果为null,且未设置默认值类型或默认值。", getCalcName(),getCalcCode());
- log.error(error);
- throw new BusinessException(error);
- }
- return castValue;
- }
- }
|