package com.vci.ubcs.code.service.impl;
|
|
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
import com.vci.ubcs.code.mapper.CommonsMapper;
|
import com.vci.ubcs.starter.web.constant.VciSystemVarConstants;
|
import com.vci.ubcs.starter.web.toolmodel.DateConverter;
|
import com.vci.ubcs.starter.web.util.Md5;
|
import com.vci.ubcs.starter.web.util.VciDateUtil;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.stereotype.Service;
|
import org.springframework.util.CollectionUtils;
|
|
import javax.annotation.Resource;
|
import java.lang.reflect.Method;
|
import java.math.BigDecimal;
|
import java.time.LocalDate;
|
import java.time.Period;
|
import java.time.format.DateTimeFormatter;
|
import java.util.*;
|
import java.util.concurrent.TimeUnit;
|
|
/**
|
* 公式处理
|
* @author weidy
|
* @date 2022-02-11
|
*
|
*/
|
@Service
|
public class FormulaServiceImpl {
|
|
/**
|
* 日志文件
|
*/
|
private Logger logger = LoggerFactory.getLogger(getClass());
|
/**
|
* 通用查询
|
*/
|
@Resource
|
CommonsMapper commonsMapper;
|
|
// /**
|
// * 业务数据服务
|
// */
|
// @Autowired
|
// private WebBoServiceI boService;
|
|
/**
|
* 是否运行完成
|
*/
|
private Boolean formulaBlag = true;
|
/**
|
* 运算符
|
*/
|
public static List<String> lc = new ArrayList<String>();
|
|
static {
|
lc.add("+");
|
lc.add("-");
|
lc.add("*");
|
lc.add("/");
|
}
|
|
/**
|
* 逻辑运算符
|
*/
|
public static List<String> lj = new ArrayList<String>();
|
static {
|
lj.add(">");
|
lj.add("<");
|
lj.add("=");
|
lj.add("!");
|
}
|
|
/**
|
* 函数,int数组注释,第一个标识:0自带函数 1自定义函数;第二个标识:参数个数
|
*/
|
public static Map<String, int[]> funMap = new HashMap<String, int[]>();
|
// int数组注释,第一个标识:0自带函数 1自定义函数;第二个标识:参数个数
|
static {
|
// 自带函数,可利用反射机制
|
funMap.put("abs", new int[] { 0, 1 });
|
funMap.put("acos", new int[] { 0, 1 });
|
funMap.put("asin", new int[] { 0, 1 });
|
funMap.put("atan", new int[] { 0, 1 });
|
funMap.put("cbrt", new int[] { 0, 1 });
|
funMap.put("ceil", new int[] { 0, 1 });
|
funMap.put("cos", new int[] { 0, 1 });
|
funMap.put("cosh", new int[] { 0, 1 });
|
funMap.put("exp", new int[] { 0, 1 });
|
funMap.put("expm1", new int[] { 0, 1 });
|
funMap.put("floor", new int[] { 0, 1 });
|
funMap.put("log", new int[] { 0, 1 });
|
funMap.put("log10", new int[] { 0, 1 });
|
funMap.put("log1p", new int[] { 0, 1 });
|
funMap.put("random", new int[] { 0, 0 });
|
funMap.put("rint", new int[] { 0, 1 });
|
funMap.put("round", new int[] { 0, 1 });
|
funMap.put("signum", new int[] { 0, 1 });
|
funMap.put("sin", new int[] { 0, 1 });
|
funMap.put("sinh", new int[] { 0, 1 });
|
funMap.put("sqrt", new int[] { 0, 1 });
|
funMap.put("tan", new int[] { 0, 1 });
|
funMap.put("tanh", new int[] { 0, 1 });
|
funMap.put("max", new int[] { 0, 2 });
|
funMap.put("min", new int[] { 0, 2 });
|
|
// 自定义函数
|
funMap.put("if", new int[] { 1, 3 });
|
funMap.put("sum", new int[] { 1, 2 });
|
funMap.put("sub", new int[] { 1, 2 });
|
funMap.put("mul", new int[] { 1, 2 });
|
funMap.put("div", new int[] { 1, 2 });
|
funMap.put("mod", new int[] { 1, 2 });
|
funMap.put("toInt", new int[] { 1, 1 });
|
funMap.put("toDouble", new int[] { 1, 1 });
|
funMap.put("doubleRound", new int[] { 1, 2 });
|
funMap.put("zeroIfNull", new int[] { 1, 1 });
|
funMap.put("endsWith", new int[] { 1, 2 });
|
funMap.put("startsWith", new int[] { 1, 2 });
|
funMap.put("charAt", new int[] { 1, 2 });
|
funMap.put("equalsIgnoreCase", new int[] { 1, 2 });
|
funMap.put("indexOf", new int[] { 1, 2 });
|
funMap.put("isEmpty", new int[] { 1, 1 });
|
funMap.put("lastIndexOf", new int[] { 1, 2 });
|
funMap.put("leftStr", new int[] { 1, 2 });
|
funMap.put("length", new int[] { 1, 1 });
|
funMap.put("mid", new int[] { 1, 3 });
|
funMap.put("right", new int[] { 1, 2 });
|
funMap.put("rightStr", new int[] { 1, 2 });
|
funMap.put("tolowercase", new int[] { 1, 1 });
|
funMap.put("touppercase", new int[] { 1, 1 });
|
funMap.put("trimzero", new int[] { 1, 1 });
|
funMap.put("compareDate", new int[] { 1, 2 });
|
funMap.put("nowDate", new int[] { 1, 0 });
|
funMap.put("chinaDate", new int[] { 1, 1 });
|
funMap.put("dateDdd", new int[] { 1, 2 });
|
funMap.put("dateBalanceYear",new int[] {1,3});
|
funMap.put("dateBalanceDay",new int[] {1,2});
|
funMap.put("dateformat", new int[] { 1, 2 });
|
funMap.put("nowDatetime", new int[] { 1, 0 });
|
funMap.put("dayOf", new int[] { 1, 1 });
|
funMap.put("nowMon", new int[] { 1, 1 });
|
funMap.put("monOf", new int[] { 1, 1 });
|
funMap.put("nowTime", new int[] { 1, 0 });
|
funMap.put("nowYear", new int[] { 1, 0 });
|
funMap.put("yearOf", new int[] { 1, 1 });
|
funMap.put("getChineseCurrency", new int[] { 1, 1 });
|
funMap.put("setThmark", new int[] { 1, 1 });
|
funMap.put("toChinese", new int[] { 1, 1 });
|
funMap.put("getcolvalue", new int[] { 1, 5 });
|
funMap.put("MD5", new int[]{1,1});
|
funMap.put("getValueByMethod", new int[]{1,3});
|
}
|
|
/**
|
* 公式初始化转换
|
*
|
* @param str 公式的内容
|
* @return 转换后的内容
|
*/
|
private String strCast(String str) {
|
// str = str.toLowerCase();// 去除空格,变小写
|
if (str == null ? true : str.length() == 0) {
|
return "0";
|
}
|
str = str.trim();
|
if (!checkFormula(str)) {
|
formulaError();
|
return str;
|
}
|
str = str.replaceAll(",", ",");
|
str = str.replaceAll("\\+-", "-");
|
str = str.replaceAll("-\\+", "-");
|
//str = str.replaceAll(" ", "");
|
return str;
|
}
|
|
/**
|
* 检查公式中括号出现次数是否正确
|
*
|
* @param formulaStr 公式的内容
|
* @return true 表示校验成功
|
*/
|
private boolean checkFormula(String formulaStr) {
|
formulaBlag = true;
|
int count = 0;
|
for (int i = 0; i < formulaStr.length(); i++) {
|
String s = String.valueOf(formulaStr.charAt(i));
|
if ("(".equals(s)) {
|
count++;
|
} else if (")".equals(s)) {
|
count--;
|
}
|
if (count < 0) {
|
formulaBlag = false;
|
break;
|
}
|
}
|
formulaBlag = count == 0;
|
return formulaBlag;
|
}
|
|
/**
|
* 分割函数
|
*
|
* @param str 字符串
|
* @param bs 分割符
|
* @return 转换后的内容
|
*/
|
private String[] spliteFun(String str, String bs) {
|
List<String> list = new ArrayList<String>();
|
String bds = "";
|
int bracket = 0;
|
int len = str.length();
|
for (int i = 0; i < len; i++) {
|
String s = String.valueOf(str.charAt(i));
|
if ("(".equals(s)) {
|
bracket++;
|
} else if (")".equals(s)) {
|
bracket--;
|
}
|
|
if (bracket == 0 && bs.equals(s)) {
|
list.add(bds);
|
bds = "";
|
continue;
|
}
|
|
bds += s;
|
}
|
|
list.add(bds);
|
|
String[] ss = new String[list.size()];
|
for (int i = 0; i < list.size(); i++) {
|
ss[i] = list.get(i);
|
}
|
|
return ss;
|
}
|
|
/**
|
* 用户自定义函数
|
*
|
* @param str 字符串
|
* @param funStr 函数的内容
|
* @return
|
*/
|
private String customFun(String str, String funStr) {
|
String reval = "false";
|
String[] gss = spliteFun(str, ",");
|
//每一个参数,我都应该去看看是否还有()。这说明里面是方法
|
for (int i = 0; i < gss.length; i++) {
|
String record = gss[i];
|
if(StringUtils.isNotBlank(record) && record.contains("(") && record.contains(")")){
|
gss[i] = calculate(gss[i]);
|
}
|
}
|
if ("if".equals(funStr)) {
|
//logger.debug("第一个参数:" + gss[0]);
|
if (compare(gss[0])) {
|
reval = calculate(gss[1]);
|
} else {
|
reval = calculate(gss[2]);
|
}
|
} else if ("sum".equals(funStr)) {
|
BigDecimal ln = new BigDecimal(gss[0]);
|
BigDecimal rn = new BigDecimal(gss[1]);
|
reval = ln.add(rn).doubleValue() + "";
|
} else if ("sub".equals(funStr)) {
|
BigDecimal ln = new BigDecimal(gss[0]);
|
BigDecimal rn = new BigDecimal(gss[1]);
|
reval = ln.subtract(rn).doubleValue() + "";
|
} else if ("mul".equals(funStr)) {
|
BigDecimal ln = new BigDecimal(gss[0]);
|
BigDecimal rn = new BigDecimal(gss[1]);
|
reval = ln.multiply(rn).doubleValue() + "";
|
} else if ("div".equals(funStr)) {
|
BigDecimal ln = new BigDecimal(gss[0]);
|
BigDecimal rn = new BigDecimal(gss[1]);
|
if (rn.doubleValue() == 0) {
|
formulaError();
|
//reval = "0";
|
return reval;
|
} else {
|
reval = ln.divide(rn, 10, BigDecimal.ROUND_HALF_UP) + "";
|
}
|
|
} else if ("mod".equals(funStr)) {
|
int rn = Integer.parseInt(gss[1]);
|
if (rn == 0) {
|
formulaError();
|
|
return reval;
|
}
|
int ln = Integer.parseInt(gss[0]);
|
reval = (ln % rn) + "";
|
} else if ("toInt".equals(funStr)) {
|
reval = (int) Math.floor(new Double(calculate(gss[0]))) + "";
|
} else if("toDouble".equals(funStr)){
|
reval = new Double(calculate(gss[0])) + "";
|
}else if("MD5".equals(funStr)){
|
reval = Md5.md5(calculate(gss[0]));
|
}else if ("doubleRound".equals(funStr)) {
|
try {
|
BigDecimal b = new BigDecimal(calculate(gss[0]));
|
reval = b.setScale(Integer.parseInt(gss[1]),
|
BigDecimal.ROUND_HALF_UP).doubleValue()
|
+ "";
|
} catch (Exception e) {
|
e.printStackTrace();
|
formulaError();
|
}
|
|
} else if ("zeroIfNull".equals(funStr)) {
|
logger.debug(gss[0]);
|
if ("null".equals(gss[0]) || gss[0].trim().length() == 0) {
|
reval = "0";
|
return reval;
|
}
|
reval = gss[0];
|
} else if ("endsWith".equals(funStr)) {
|
reval = "false";
|
if (gss[0].endsWith(gss[1])) {
|
reval = "true";
|
}
|
|
} else if ("startsWith".equals(funStr)) {
|
reval = "false";
|
if (gss[0].startsWith(gss[1])) {
|
reval = "true";
|
}
|
} else if ("charAt".equals(funStr)) {
|
try {
|
reval = String.valueOf(gss[0].charAt(Integer.parseInt(gss[1])));
|
} catch (Exception e) {
|
e.printStackTrace();
|
formulaError();
|
reval = "";
|
}
|
|
} else if ("equalsignoreCase".equals(funStr)) {
|
if (gss[0].equalsIgnoreCase(gss[1])) {
|
reval = "true";
|
}
|
} else if ("indexOf".equals(funStr)) {
|
reval = gss[0].indexOf(gss[1]) + "";
|
} else if ("isEmpty".equals(funStr)) {
|
if (gss[0].trim().length() == 0 || "".equals(gss[0])
|
|| "null".equals(gss[0])) {
|
reval = "true";
|
}
|
} else if ("lastIndexOf".equals(funStr)) {
|
reval = gss[0].lastIndexOf(gss[1]) + "";
|
} else if ("leftStr".equals(funStr)) {
|
reval = gss[0].substring(0, Integer.parseInt(gss[1]));
|
} else if ("length".equals(funStr)) {
|
reval = gss[0].length() + "";
|
} else if ("right".equals(funStr)) {
|
reval = String.valueOf(gss[0].charAt(gss[0].length()
|
- Integer.parseInt(gss[1])));
|
|
} else if ("rightStr".equals(funStr)) {
|
reval = gss[0]
|
.substring(gss[0].length() - Integer.parseInt(gss[1]));
|
} else if ("mid".equals(funStr)) {
|
try {
|
reval = gss[0].substring(Integer.parseInt(gss[1]),
|
Integer.parseInt(gss[2]));
|
}catch (Exception e) {
|
e.printStackTrace();
|
formulaError();
|
reval = "";
|
}
|
|
} else if ("tolowercase".equals(funStr)) {
|
reval = gss[0].toLowerCase();
|
} else if ("touppercase".equals(funStr)) {
|
reval = gss[0].toUpperCase();
|
} else if ("trimZero".equals(funStr)) {
|
int len = gss[0].length() - 1;
|
for (int i = len; i >= 0; i--) {
|
if (gss[0].charAt(i) == '0') {
|
gss[0] = gss[0].substring(0, gss[0].length() - 1);
|
} else {
|
reval = gss[0];
|
break;
|
}
|
}
|
} else if ("compareDate".equals(funStr)) {
|
if (gss[0].indexOf("date") != -1) {
|
gss[0] = calculate(gss[0]);
|
}
|
if (gss[1].indexOf("date") != -1) {
|
gss[1] = calculate(gss[1]);
|
}
|
gss[0] = gss[0].replaceAll("`", "-");
|
gss[1] = gss[1].replaceAll("`", "-");
|
String result;
|
try {
|
result = VciDateUtil.compareDate(gss[0], gss[1]);
|
if ("=".equals(result)) {
|
reval = "true";
|
}
|
;
|
} catch (Exception e) {
|
e.printStackTrace();
|
formulaError();
|
}
|
|
} else if ("nowDate".equals(funStr)) {
|
reval = VciDateUtil.getNowString("yyyy-MM-dd");
|
} else if ("chinaDate".equals(funStr)) {
|
try {
|
if (gss[0].indexOf("date") != -1) {
|
gss[0] = calculate(gss[0]);
|
}
|
gss[0] = gss[0].replaceAll("`", "-");
|
reval = VciDateUtil.getChinaDate(gss[0]);
|
return reval;
|
} catch (Exception e) {
|
e.printStackTrace();
|
formulaError();
|
}
|
} else if ("dateAdd".equals(funStr)) {
|
try {
|
if (gss[0].indexOf("date") != -1) {
|
gss[0] = calculate(gss[0]);
|
}
|
gss[0] = gss[0].replaceAll("`", "-");
|
DateConverter dateConverter = new DateConverter();
|
dateConverter.setAsText(gss[0]);
|
Date date = VciDateUtil.getDateAddDay(dateConverter.getValue(),
|
Integer.parseInt(gss[1]));
|
reval = VciDateUtil.date2Str(date, VciDateUtil.DateTimeFormat);
|
return reval;
|
} catch (Exception e) {
|
e.printStackTrace();
|
formulaError();
|
}
|
} else if("dateBalanceYear".equals(funStr)) {
|
//求时间的差额
|
//3个参数,对比的源值,对比的目标值,是否进一
|
String sourceDate = gss[0];
|
String targetDate = gss[1];
|
boolean remainderType = "true".equalsIgnoreCase(gss[2]) ? true : false;
|
DateConverter dateConverter = new DateConverter();
|
dateConverter.setAsText(sourceDate);
|
Date sDate = dateConverter.getValue();
|
Date tDate = new Date();
|
if (StringUtils.isBlank(targetDate)) {
|
dateConverter.setAsText(targetDate);
|
tDate = dateConverter.getValue();
|
}
|
|
Period p = Period.between(LocalDate.parse(VciDateUtil.date2Str(sDate, VciDateUtil.DateTimeMillFormat), DateTimeFormatter.ofPattern(VciDateUtil.DateTimeMillFormat)),
|
LocalDate.parse(VciDateUtil.date2Str(tDate, VciDateUtil.DateTimeMillFormat), DateTimeFormatter.ofPattern(VciDateUtil.DateTimeMillFormat)));
|
reval = String.valueOf((remainderType && (p.getMonths() > 0 || p.getDays() > 0)) ? (p.getYears() + 1) : p.getYears());
|
//月份相差是没办法计算
|
}else if("dateBalanceDay".equals(funStr)){
|
String sourceDate = gss[0];
|
String targetDate = gss[1];
|
DateConverter dateConverter = new DateConverter();
|
dateConverter.setAsText(sourceDate);
|
Date sDate = dateConverter.getValue();
|
Date tDate = new Date();
|
if (StringUtils.isNotBlank(targetDate)) {
|
dateConverter.setAsText(targetDate);
|
tDate = dateConverter.getValue();
|
}
|
reval = String.valueOf(TimeUnit.DAYS.convert(Math.abs(sDate.getTime()-tDate.getTime()),TimeUnit.MILLISECONDS));
|
}else if ("dateformat".equals(funStr)) {
|
if (gss[0].indexOf("date") != -1) {
|
gss[0] = calculate(gss[0]);
|
}
|
gss[0] = gss[0].replaceAll("`", "-");
|
gss[1] = gss[1].replaceAll("`", "-");
|
Date date;
|
try {
|
if("''".equalsIgnoreCase(gss[0])) {
|
gss[0] = VciDateUtil.getNowString();
|
}
|
DateConverter dateConverter =new DateConverter();
|
dateConverter.setAsText(gss[0]);
|
date = dateConverter.getValue();
|
reval = VciDateUtil.date2Str(date, gss[1].replace("&"," "));
|
return reval;
|
} catch (Exception e) {
|
e.printStackTrace();
|
formulaError();
|
}
|
|
} else if ("nowDatetime".equals(funStr)) {
|
reval = VciDateUtil.getNowString();
|
} else if ("dayOf".equals(funStr)) {
|
if (gss[0].indexOf("date") != -1) {
|
gss[0] = calculate(gss[0]);
|
}
|
gss[0] = gss[0].replaceAll("`", "-");
|
try {
|
Date date = VciDateUtil.str2Date(gss[0], "yyyy-MM-dd");
|
reval = date.getDate() + "";
|
return reval;
|
} catch (Exception e) {
|
e.printStackTrace();
|
formulaError();
|
}
|
} else if ("nowNon".equals(funStr)) {
|
try {
|
reval = VciDateUtil.getNowString("MM");
|
return reval;
|
} catch (Exception e) {
|
e.printStackTrace();
|
formulaError();
|
}
|
} else if ("monOf".equals(funStr)) {
|
if (gss[0].indexOf("date") != -1) {
|
gss[0] = calculate(gss[0]);
|
}
|
gss[0] = gss[0].replaceAll("`", "-");
|
try {
|
Date date = VciDateUtil.str2Date(gss[0], "yyyy-MM-dd");
|
reval = date.getMonth() + "";
|
return reval;
|
} catch (Exception e) {
|
e.printStackTrace();
|
formulaError();
|
}
|
} else if ("nowTime".equals(funStr)) {
|
reval = VciDateUtil.getNowString("HH:mm:ss");
|
return reval;
|
} else if ("nowYear".equals(funStr)) {
|
reval = VciDateUtil.getNowString("yyyy");
|
return reval;
|
} else if ("yearOf".equals(funStr)) {
|
if (gss[0].indexOf("date") != -1) {
|
gss[0] = calculate(gss[0]);
|
}
|
gss[0] = gss[0].replaceAll("`", "-");
|
try {
|
Date date = VciDateUtil.str2Date(gss[0], "yyyy-MM-dd");
|
reval = date.getYear() + 1900 + "";
|
return reval;
|
} catch (Exception e) {
|
e.printStackTrace();
|
formulaError();
|
}
|
} else if ("getChineseCurrency".equals(funStr)) {
|
gss[0] = calculate(gss[0]);
|
reval = toChineseCurrency(gss[0]);
|
} else if ("setThmark".equals(funStr)) {
|
String numstr = "";
|
|
String[] number = gss[0].split("\\.");
|
//logger.debug(number[0]);
|
for (int i = number[0].length() - 1; i >= 0; i--) {
|
if (i % 3 == 2 && i < number[0].length() - 1) {
|
numstr += ",";
|
}
|
numstr += number[0].charAt(i);
|
}
|
reval = "";
|
for (int i = numstr.toCharArray().length - 1; i >= 0; i--) {
|
reval += numstr.toCharArray()[i];
|
}
|
if (gss[0].indexOf(".") != -1) {
|
reval += "." + number[1];
|
}
|
|
} else if ("toChinese".equals(funStr)) {
|
gss[0] = calculate(gss[0]);
|
//logger.debug(gss[0]);
|
reval = toChinese(gss[0]);
|
} else if ("getcolvalue".equals(funStr)) {
|
if (gss[0].trim().length() == 0 || gss[1].trim().length() == 0
|
|| gss[2].trim().length() == 0
|
|| gss[3].trim().length() == 0
|
|| gss[4].trim().length() == 0) {
|
formulaError();
|
return reval;
|
}
|
reval = getColValue(gss[0], gss[1], gss[2], gss[3], gss[4]);
|
}else if("getValueByMethod".equalsIgnoreCase(funStr)){
|
if (gss[0].trim().length() == 0 || gss[1].trim().length() == 0
|
|| gss[2].trim().length() == 0) {
|
formulaError();
|
return reval;
|
}
|
reval = getValueByMethod(gss[0], gss[1], gss[2]);
|
}
|
|
return reval;
|
}
|
|
// 逻辑表达式判断
|
private boolean compare(String str) {
|
if ("true".equals(calculate(str))) {
|
return true;
|
} else if ("false".equals(calculate(str))) {
|
return false;
|
}
|
boolean flag = false;
|
boolean bs = false;
|
int len = str.length();
|
int bracket = 0;
|
String ljbds = "";
|
double d_left = 0;
|
double d_right = 0;
|
for (int i = 0; i < len; i++) {
|
String s = String.valueOf(str.charAt(i));
|
if ("(".equals(s)) {
|
bracket++;
|
} else if (")".equals(s)) {
|
bracket--;
|
}
|
|
if (bracket == 0 && lj.contains(s)) {
|
for (int j = i; j < len; j++) {
|
String ts = String.valueOf(str.charAt(j));
|
if (lj.contains(ts)) {
|
ljbds += ts;
|
} else {
|
bs = true;
|
break;
|
}
|
}
|
}
|
if (bs) {
|
break;
|
}
|
}
|
//logger.debug("逻辑表达式:" + ljbds);
|
String[] s = str.split(ljbds);
|
//logger.debug("左边:" + (s[0]));
|
//logger.debug("右边:" + (s[1]));
|
if (isNumber(calculate(s[0])) && isNumber(calculate(s[1]))) {
|
d_left = new Double(calculate(s[0]));
|
d_right = new Double(calculate(s[1]));
|
} else {
|
formulaError();
|
return false;
|
}
|
|
if ("<".equals(ljbds)) {
|
if (d_left < d_right) {
|
return true;
|
}
|
} else if (">".equals(ljbds)) {
|
if (d_left > d_right) {
|
return true;
|
}
|
} else if ("=".equals(ljbds)) {
|
if (d_left == d_right) {
|
return true;
|
}
|
} else if (">=".equals(ljbds)) {
|
if (d_left >= d_right) {
|
return true;
|
}
|
} else if ("<=".equals(ljbds)) {
|
if (d_left <= d_right) {
|
return true;
|
}
|
} else if ("<>".equals(ljbds) || "!=".equals(ljbds)) {
|
if (d_left != d_right) {
|
return true;
|
}
|
} else {
|
formulaError();
|
}
|
return flag;
|
}
|
|
/**
|
* 使用公式计算结果
|
* @param dataMap 本场景变量的值
|
* @param calculateString 公式的内容
|
* @return 执行后的值
|
*/
|
public String getValueByFormula(Map<String,String> dataMap,String calculateString){
|
final String[] finalRule = new String[]{calculateString};
|
if(!CollectionUtils.isEmpty(dataMap)){
|
dataMap.forEach((key,value)->{
|
if(value == null){
|
value = "";
|
}
|
finalRule[0] = finalRule[0].replace("${" + key + "}",value);
|
});
|
}
|
return calculate(finalRule[0]);
|
}
|
|
/**
|
* 递归调用运算,注意变量需要自行替换
|
*
|
* @param str
|
* @return
|
*/
|
public String calculate(String str) {
|
str = this.strCast(str);
|
if (!formulaBlag) {
|
//logger.debug("公式不正确");
|
return str;
|
}
|
boolean onlyFunction = str.length()>2 && str.startsWith("->");
|
if(onlyFunction){
|
str = str.substring(2);
|
}
|
//需要替换系统变量
|
Map<String, String> systemVarValueMap = VciSystemVarConstants.getSystemVarValueMap();
|
if(!CollectionUtils.isEmpty(systemVarValueMap)){
|
final String[] finalStr = new String[]{str};
|
systemVarValueMap.forEach((key,value)->{
|
if(value == null){
|
value = "";
|
}
|
finalStr[0] = finalStr[0].replace( key,value);
|
});
|
str = finalStr[0];
|
}
|
String reval = "";
|
String bds = "";
|
int bracket = 0;// 对应括号个数
|
int pos = 0;
|
boolean title = false;
|
// 如果以负数开头,先去掉负号
|
if (str.substring(0, 1).equals("-")) {
|
str = str.substring(1);
|
title = true;
|
}
|
|
int len = str.length();
|
for (int i = 0; i < len; i++) {
|
String s = String.valueOf(str.charAt(i));
|
pos = i;
|
bracket = 0;
|
if (!lc.contains(s)) {// 如果没遇到运算符
|
if ("(".equals(s)) {// 如果遇到左括号
|
if (funMap.containsKey(bds)) {// 如果左括号前是函数
|
for (int j = i + 1; j < len; j++) {// 从左括号后开始循环
|
pos++;// 累计移动字符位数
|
String ts = String.valueOf(str.charAt(j));// 单个字符
|
// reval+=ts;
|
if ("(".equals(ts))// 如果是左括号累计
|
{
|
bracket++;
|
} else if (")".equals(ts)) {// 如果是右括号进行减少
|
bracket--;
|
if (bracket == -1) {// 如果是-1,标识括号结束
|
reval = reval.substring(0, reval.length()
|
- bds.length());// 重新获得去掉函数头的表达式
|
reval += this.funCalculate(
|
str.substring(i + 1, j), bds);// 表达式加上函数结果,形成新表达式
|
i = pos;// 计数器增加
|
bds = "";// 函数头清空
|
break;// 退出本次循环
|
}
|
}
|
}
|
} else if ("".equals(bds) || lc.contains(bds)) {// 如果是普通运算
|
//logger.debug("普通运算");
|
for (int j = i + 1; j < len; j++) {
|
pos++;
|
String ts = String.valueOf(str.charAt(j));
|
if ("(".equals(ts)) {
|
bracket++;
|
} else if (")".equals(ts)) {
|
bracket--;
|
if (bracket == -1) {
|
logger.debug("当前计算的字符串为:"
|
+ str.substring(i + 1, pos));
|
reval += calculate(str
|
.substring(i + 1, pos));
|
i = pos;
|
bds = "";
|
break;
|
}
|
}
|
}
|
} else {
|
logger.debug("没有此函数");
|
formulaError();
|
}
|
} else {// 累加总表达式和最后一个运算数(或函数)
|
bds += s;
|
reval += s;
|
}
|
} else {// 遇到运算符最后一个运算数(或函数)清空
|
bds = "";
|
reval += s;
|
}
|
}
|
// 如果为负数 在前面加负号
|
if (title) {
|
reval = "0-" + reval;
|
}
|
if(onlyFunction){
|
|
return reval;
|
}
|
String result = basicOperation(reval);
|
logger.debug("计算结果" + result);
|
return result;
|
}
|
|
/**
|
* 函数运算
|
*
|
* @param gs
|
* @param funStr
|
* @return
|
*/
|
private String funCalculate(String gs, String funStr) {
|
String rval = "0";
|
logger.debug("函数名:" + funStr);
|
if (funMap.containsKey(funStr)) {
|
int[] csi = funMap.get(funStr);
|
try {
|
if (csi[0] == 0) {// java内部函数,通过反射调用
|
Class[] cs = new Class[csi[1]];
|
Object[] objs = new Object[csi[1]];
|
String[] gss = splitParameter(gs);
|
for (int i = 0; i < csi[1]; i++) {
|
cs[i] = double.class;
|
objs[i] = new Double(calculate(gss[i]));
|
}
|
Class cls = Class.forName("java.lang.Math");
|
Method m = cls.getMethod(funStr, cs);
|
logger.debug("方法名:" + m);
|
rval = String.valueOf(m.invoke(cls, objs));
|
} else if (csi[0] == 1) {// 自定义函数
|
rval = customFun(gs, funStr);
|
}
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
}
|
|
return rval;
|
}
|
|
// 公式里的参数分割
|
public static String[] splitParameter(String str) {
|
int len = str.length();
|
boolean flag = true;
|
String tstr = "";
|
|
for (int i = 0; i < len; i++) {
|
String s = String.valueOf(str.charAt(i));
|
if ("(".equals(s)) {
|
flag = false;
|
} else if (")".equals(s)) {
|
flag = true;
|
}
|
if (flag && ",".equals(s)) {
|
tstr += "@";
|
} else {
|
tstr += s;
|
}
|
}
|
return tstr.split("@");
|
|
}
|
|
/**
|
* 四则运算表达式处理
|
*
|
* @param gs
|
* @return
|
*/
|
private String basicOperation(String gs) {
|
gs = gs + "+0"; // 因为下面的计算是遇到符号才进行,所以多加入一个计算符号,不影响值.
|
if(gs.indexOf("-")>-1){//包含有-号或者是负数
|
if(gs.startsWith("-")) {
|
gs = "0" + gs;
|
}
|
// if(gs.indexOf("-")>0&&lc.contains(gs.substring(gs.indexOf("-")-1,gs.indexOf("-")))){//紧挨着旁边就是运算符,怎么办啊
|
// //gs = gs.substring(0,gs.indexOf("-")-1) + "(0" + gs.substring(gs.indexOf("-"))
|
// }
|
}
|
String c1 = "";// 第一个运算符号
|
String c2 = "";// 第二个运算符号
|
String s1 = "";// 第一个运算数
|
String s2 = "";// 第二个运算数
|
String s3 = "";// 第三个运算数
|
|
int len = gs.length();
|
for (int i = 0; i < len; i++) {
|
String s = String.valueOf(gs.charAt(i));// 获得该位置字符并转换成字符串做比较
|
if (lc.contains(s)) { // 如果是运算符号
|
if (c1.length() == 0)// 如果第一个运算符号为空,加入
|
{
|
c1 = s;
|
} else if (c2.length() == 0) {// 否则,如果第二个运算符号为空,加入
|
c2 = s;// 第二个运算符号
|
if ("+".equals(c2) || "-".equals(c2)) {// 如果第二个运算符号级别低,那么进行计算
|
if(s2.trim().length()>0){
|
s1 = this.operation(s1, c1, s2);// 第一个和第二个数计算
|
c1 = c2;// 保存第二个运算符,其他为空
|
c2 = "";
|
s2 = "";
|
}else{//s2还没出现
|
s2=this.calculate(gs.substring(i));
|
s1 = this.operation(s1, c1, s2);
|
break;
|
}
|
}
|
} else {// 上述都保存过
|
if ("+".equals(s) || "-".equals(s)) {// 如果第三个运算符级别低,进行运算
|
s2 = this.operation(s2, c2, s3);// 先算第二三个数,保存至第二个
|
s1 = this.operation(s1, c1, s2);// 再算第一二个,保存至第一个
|
c1 = s;// 保存当前运算符,其他为空
|
s2 = "";
|
c2 = "";
|
s3 = "";
|
} else {// 如果第三个运算符级别高
|
s2 = this.operation(s2, c2, s3);// 先算第二三个数,保存至第二个
|
c2 = s;// 前面不动,保存运算符
|
s3 = "";
|
}
|
}
|
} else if (s1.length() > 0 && c1.length() > 0 && c2.length() == 0) {// 如果第一个数,第一个运算符已保存,第二个运算符未保存,保存第二哥数
|
s2 += s;
|
} else if (c1.length() == 0) {// 如果没有运算符,保存第一个数
|
s1 += s;
|
} else if (s1.length() > 0 && s2.length() > 0 && c1.length() > 0
|
&& c2.length() > 0) {// 如果第一二个数和运算符都有,保存第三个数
|
s3 += s;
|
}
|
}
|
return s1;
|
}
|
|
/**
|
* 基本四则运算
|
*
|
* @param c1
|
* 运算数1
|
* @param s1
|
* 运算符(加减乘除)
|
* @param c2
|
* 运算数2
|
* @return
|
*/
|
private String operation(String c1, String s1, String c2) {
|
String reval = "0";
|
String c22 = "";
|
try {
|
for (int i = 0; i < c2.length(); i++) {
|
String s = String.valueOf(c2.charAt(i));
|
if (lj.contains(s)) {
|
break;
|
}
|
c22 += s;
|
}
|
if (isNumber(c1) && isNumber(c22)) {
|
BigDecimal ln = new BigDecimal(c1.trim());
|
BigDecimal rn = new BigDecimal(c2.trim());
|
if ("+".equals(s1)) {
|
return ln.add(rn).doubleValue() + "";
|
} else if ("-".equals(s1)) {
|
return ln.subtract(rn).doubleValue() + "";
|
} else if ("*".equals(s1)) {
|
return ln.multiply(rn).doubleValue() + "";
|
} else if ("/".equals(s1)) {
|
if (rn.doubleValue() == 0) {
|
return reval;
|
}
|
else {
|
return ln.divide(rn, 10, BigDecimal.ROUND_HALF_UP) + "";
|
}
|
}
|
} else {
|
this.formulaError();
|
return c1+s1+c2;
|
}
|
|
} catch (Exception e) {
|
this.formulaError();
|
e.printStackTrace();
|
} finally {
|
}
|
|
return reval;
|
}
|
|
private Boolean isNumber(String str) {
|
return StringUtils.isNotBlank(str) && str.matches("(-)?([1-9]+[0-9]*|0)(\\.[\\d]+)?");
|
}
|
|
private String formulaError() {
|
formulaBlag = false;
|
//logger.debug("公式验证失败,请重新输入");
|
return "fail";
|
}
|
|
public String toChineseCurrency(String value) {
|
String doubleValue = this.calculate("doubleround(" + value + ",2)");
|
String fushu = "";
|
if (doubleValue.indexOf("-") == 0) {
|
fushu = "负";
|
doubleValue = doubleValue.substring(1);
|
// formulaError();
|
// return "";
|
}
|
char[] hunit = { '拾', '佰', '仟' }; // 段内位置表示
|
char[] vunit = { '万', '亿' }; // 段名表示
|
char[] digit = { '零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖' }; // 数字表示
|
//double midVal = (Double.parseDouble(doubleValue) * 100); // 转化成整形
|
//String valStr = String.valueOf(midVal); // 转化成字符串
|
//String head = valStr.substring(0, valStr.length() - 2); // 取整数部分
|
//String rail = valStr.substring(valStr.length() - 2); // 取小数部分
|
String head = "";
|
String rail = "00";
|
if(doubleValue.indexOf(".")>-1){
|
head = doubleValue.substring(0,doubleValue.indexOf("."));
|
rail = doubleValue.substring(doubleValue.indexOf(".")+1);
|
if(rail.trim().length() == 1) {
|
rail += "0";//必须要保证有分
|
}
|
}
|
else {
|
head = doubleValue;
|
}
|
String prefix = ""; // 整数部分转化的结果
|
String suffix = ""; // 小数部分转化的结果
|
// 处理小数点后面的数
|
if (rail.equals("00")) { // 如果小数部分为0
|
suffix = "整";
|
} else {
|
suffix = digit[rail.charAt(0) - '0'] + "角"
|
+ digit[rail.charAt(1) - '0'] + "分"; // 否则把角分转化出来
|
}
|
// 处理小数点前面的数
|
char[] chDig = head.toCharArray(); // 把整数部分转化成字符数组
|
char zero = '0'; // 标志'0'表示出现过0
|
byte zeroSerNum = 0; // 连续出现0的次数
|
for (int i = 0; i < chDig.length; i++) { // 循环处理每个数字
|
int idx = (chDig.length - i - 1) % 4; // 取段内位置
|
int vidx = (chDig.length - i - 1) / 4; // 取段位置
|
if (chDig[i] == '0') { // 如果当前字符是0
|
zeroSerNum++; // 连续0次数递增
|
if (zero == '0') { // 标志
|
zero = digit[0];
|
} else if (idx == 0 && vidx > 0 && zeroSerNum < 4) {
|
prefix += vunit[vidx - 1];
|
zero = '0';
|
}
|
continue;
|
}
|
zeroSerNum = 0; // 连续0次数清零
|
if (zero != '0') { // 如果标志不为0,则加上,例如万,亿什么的
|
prefix += zero;
|
zero = '0';
|
}
|
prefix += digit[chDig[i] - '0']; // 转化该数字表示
|
if (idx > 0) {
|
prefix += hunit[idx - 1];
|
}
|
if (idx == 0 && vidx > 0) {
|
prefix += vunit[vidx - 1]; // 段结束位置应该加上段名如万,亿
|
}
|
}
|
|
if (prefix.length() > 0) {
|
prefix += '圆'; // 如果整数部分存在,则有圆的字样
|
}
|
return fushu + prefix + suffix; // 返回正确表示
|
}
|
|
private String toChinese(String value) {
|
if (!isNumber(value)) {
|
this.formulaError();
|
return "";
|
}
|
String fu = "";
|
// 如果是负数前面加负
|
if (value.indexOf("-") == 0) {
|
value = value.substring(1);
|
fu += "负";
|
}
|
char[] hunit = { '拾', '佰', '仟' }; // 段内位置表示
|
char[] vunit = { '万', '亿' }; // 段名表示
|
char[] digit = { '零', '一', '二', '三', '四', '五', '六', '七', '八', '九' }; // 数字表示
|
String head = "";
|
String rail = "";
|
String prefix = ""; // 整数部分转化的结果
|
String suffix = ""; // 小数部分转化的结果
|
if (value.indexOf(".") != -1 && value.indexOf(".") < value.length() - 1) {
|
String[] number = value.split("\\.");
|
head = number[0]; // 取整数部分
|
rail = number[1];
|
suffix += "点";
|
} else {
|
head = value;
|
}
|
// 处理小数点后面的数
|
for (int i = 0; i < rail.length(); i++) {
|
suffix += digit[rail.charAt(i) - '0'];
|
}
|
|
// 处理小数点前面的数
|
char[] chDig = head.toCharArray(); // 把整数部分转化成字符数组
|
char zero = '0'; // 标志'0'表示出现过0
|
byte zeroSerNum = 0; // 连续出现0的次数
|
for (int i = 0; i < chDig.length; i++) { // 循环处理每个数字
|
int idx = (chDig.length - i - 1) % 4; // 取段内位置
|
int vidx = (chDig.length - i - 1) / 4; // 取段位置
|
if (chDig[i] == '0') { // 如果当前字符是0
|
zeroSerNum++; // 连续0次数递增
|
if (zero == '0') { // 标志
|
zero = digit[0];
|
} else if (idx == 0 && vidx > 0 && zeroSerNum < 4) {
|
prefix += vunit[vidx - 1];
|
zero = '0';
|
}
|
continue;
|
}
|
zeroSerNum = 0; // 连续0次数清零
|
if (zero != '0') { // 如果标志不为0,则加上,例如万,亿什么的
|
prefix += zero;
|
zero = '0';
|
}
|
prefix += digit[chDig[i] - '0']; // 转化该数字表示
|
if (idx > 0) {
|
prefix += hunit[idx - 1];
|
}
|
if (idx == 0 && vidx > 0) {
|
prefix += vunit[vidx - 1]; // 段结束位置应该加上段名如万,亿
|
}
|
}
|
return fu + prefix + suffix; // 返回正确表示
|
}
|
|
private String getColValue(String servername, String tableName,
|
String fieldname, String pkfield, String pkvalue) {
|
//暂时不支持server的方式
|
String sql = "select " + fieldname.trim() + " from " + tableName.trim() + " where " + pkfield + " = '" + pkvalue+"'";
|
// Map<String,String> param = new HashMap<String, String>();
|
// param.put(pkfield, pkvalue);
|
String str = "";
|
try{
|
List data = commonsMapper.selectById(sql);
|
if(data != null || data.size() > 0) {
|
str = (String) ((HashMap) data.get(0)).get(fieldname.trim());
|
}
|
}catch(Exception e){
|
|
}
|
return str;
|
|
}
|
|
private String getValueByMethod(String serviceName,String methods,String paramsString){
|
//暂时不支持通过方法来获取值
|
return paramsString;
|
}
|
|
public static void main(String[] args) {
|
|
}
|
|
}
|