package com.engine.salary.service.impl; import com.engine.core.impl.Service; import com.engine.salary.encrypt.AESEncryptUtil; import com.engine.salary.entity.datacollection.DataCollectionEmployee; import com.engine.salary.entity.salaryformula.ExpressFormula; import com.engine.salary.entity.salaryformula.po.FormulaVar; import com.engine.salary.enums.salaryformula.ReferenceTypeEnum; import com.engine.salary.formlua.core.QlExpress; import com.engine.salary.formlua.entity.parameter.DataType; import com.engine.salary.formlua.entity.standard.ExcelResult; import com.engine.salary.service.FormulaRunService; import com.engine.salary.sys.enums.OpenEnum; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.ql.util.express.DefaultContext; import com.ql.util.express.ExpressRunner; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; import org.springframework.util.StopWatch; import weaver.conn.RecordSet; import weaver.conn.RecordSetDataSource; import weaver.general.BaseBean; import weaver.general.Util; import java.math.BigDecimal; import java.util.HashMap; import java.util.List; import java.util.Map; @Slf4j public class FormulaRunServiceImpl extends Service implements FormulaRunService { private static ExpressRunner runner = new ExpressRunner(true, false); private static final ObjectMapper objectMapper = new ObjectMapper(); private final BaseBean baseBean = new BaseBean(); private final Boolean isLog = "true".equals(baseBean.getPropValue("hrmSalary", "log")); QlExpress express = new QlExpress(); @Override public ExcelResult run(ExpressFormula expressFormula, List formulaVars, DataCollectionEmployee simpleEmployee) { ExcelResult result = new ExcelResult(false, "", ""); if (isLog) { StopWatch stopWatch = new StopWatch(); stopWatch.start("run " + expressFormula.getName()); if (ReferenceTypeEnum.parseByValue(expressFormula.getReferenceType()) == ReferenceTypeEnum.FORMULA) { result = runFormula(expressFormula, formulaVars); } if (ReferenceTypeEnum.parseByValue(expressFormula.getReferenceType()) == ReferenceTypeEnum.SQL) { result = runSQL(expressFormula, formulaVars); } stopWatch.stop(); double totalTimeSeconds = stopWatch.getTotalTimeSeconds(); result.setRunTime(totalTimeSeconds); } else { if (ReferenceTypeEnum.parseByValue(expressFormula.getReferenceType()) == ReferenceTypeEnum.FORMULA) { result = runFormula(expressFormula, formulaVars); } if (ReferenceTypeEnum.parseByValue(expressFormula.getReferenceType()) == ReferenceTypeEnum.SQL) { result = runSQL(expressFormula, formulaVars); } } log.error("express execute fail, {} not in ReferenceTypeEnum ", expressFormula.getReferenceType()); return result; } private ExcelResult runSQL(ExpressFormula expressFormula, List formulaVars) { if (isLog) { log.info("SQL ExpressFormula {}", expressFormula); } ExcelResult excelResult = new ExcelResult(); //解析配置,获取返回值、数据源 String extendParam = expressFormula.getExtendParam(); String sqlReturnKey = ""; String datasourceId = ""; String openDecrypt = ""; String result = ""; try { JsonNode jsonNode = objectMapper.readTree(extendParam); //返回值配置 JsonNode sqlReturnKeyNode = jsonNode.get("sqlReturnKey"); if (sqlReturnKeyNode != null) { sqlReturnKey = sqlReturnKeyNode.asText().trim(); } //数据源配置 JsonNode datasourceNode = jsonNode.get("datasource"); if (datasourceNode != null) { JsonNode datasourceIdNode = datasourceNode.get("datasourceId"); if (datasourceIdNode != null) { datasourceId = datasourceIdNode.asText(); } } //是否需要解密 JsonNode decrypt = jsonNode.get("openDecrypt"); if (decrypt != null) { openDecrypt = decrypt.asText().trim(); } //解析sql String sql = expressFormula.getFormulaRunScript(); for (FormulaVar formulaVar : formulaVars) { sql = sql.replaceAll(formulaVar.getFieldId(), "'" + formulaVar.getContent() + "'"); } if (isLog) { log.info("ExpressFormula sql run {}", sql); } excelResult.setExpress(sql); //外部数据源 if (StringUtils.isNotBlank(datasourceId)) { RecordSetDataSource rs = new RecordSetDataSource(datasourceId); log.error("执行外部sql,{},datasourceId{}", sql, datasourceId); if (rs.executeSql(sql)) { if (rs.next()) { result = rs.getString(sqlReturnKey); } } } else { RecordSet rs = new RecordSet(); if (rs.execute(sql)) { if (rs.next()) { result = rs.getString(sqlReturnKey); } } } if (OpenEnum.OPEN.getValue().equals(openDecrypt)) { result = AESEncryptUtil.decrypt(result); } excelResult.setStatus(true); excelResult.setData(Util.null2String(result)); return excelResult; } catch (Throwable e) { log.error("express run err sql", e); while (e.getCause() != null) { e = e.getCause(); } excelResult.setStatus(false); excelResult.setErrorMsg(e.getMessage()); return excelResult; } } private ExcelResult runFormula(ExpressFormula expressFormula, List formulaVars) { //是否是自定义函数 boolean isCustomFunction = true; String extendParam = expressFormula.getExtendParam(); try { JsonNode jsonNode = objectMapper.readTree(extendParam); //返回值配置 JsonNode isCustomFunctionNode = jsonNode.get("isCustomFunction"); if (isCustomFunctionNode != null) { isCustomFunction = StringUtils.equals(isCustomFunctionNode.asText().trim(), "1"); } } catch (JsonProcessingException e) { log.error("express execute fail, sql extendParam parse fail", e); } if (isLog) { log.info("FORMULA ExpressFormula {} {}", expressFormula.getFormula(), expressFormula.getFormulaRunScript()); } String formula = expressFormula.getFormulaRunScript(); ExcelResult execute = new ExcelResult(); if (isCustomFunction) { try { execute.setExpress(formula); DefaultContext context = new DefaultContext(); formulaVars.forEach(v -> { if (isLog) { log.info("FORMULA formulaVar {} - {}", v.getFieldId(), v.getContent()); } if (DataType.NUMBER.equals(v.getFieldType()) && NumberUtils.isCreatable(v.getContent())) { context.put(v.getFieldId(), new BigDecimal(v.getContent())); } else { context.put(v.getFieldId(), v.getContent()); } }); execute.setExpressContext(context); Object data = runner.execute(formula, context, null, true, false); if (data != null) { execute.setData(data); execute.setStatus(true); } else { execute.setStatus(false); } } catch (Throwable e) { log.error("express run err isCustomFunction", e); while (e.getCause() != null) { e = e.getCause(); } execute.setStatus(false); execute.setErrorMsg(e.getMessage()); } return execute; } else { Map context = new HashMap<>(); formulaVars.forEach(v -> { if (isLog) { log.info("FORMULA formulaVar {} - {}", v.getFieldId(), v.getContent()); } if (DataType.NUMBER.equals(v.getFieldType()) && NumberUtils.isCreatable(v.getContent())) { context.put(v.getFieldId(), new BigDecimal(v.getContent())); } else { context.put(v.getFieldId(), v.getContent()); } }); execute = express.execute(formula, context); return execute; } } }