All Downloads are FREE. Search and download functionalities are using the official Maven repository.

toolgood.algorithm.AlgorithmEngine Maven / Gradle / Ivy

package toolgood.algorithm;

import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.RecognitionException;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import toolgood.algorithm.enums.AreaUnitType;
import toolgood.algorithm.enums.DistanceUnitType;
import toolgood.algorithm.enums.MassUnitType;
import toolgood.algorithm.enums.VolumeUnitType;
import toolgood.algorithm.internals.*;
import toolgood.algorithm.litJson.JsonData;
import toolgood.algorithm.litJson.JsonMapper;
import toolgood.algorithm.math.mathLexer;
import toolgood.algorithm.math.mathParser;
import toolgood.algorithm.math.mathParser.ProgContext;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

public class AlgorithmEngine {
    /**
     * 使用EXCEL索引
     */
    public boolean UseExcelIndex = true;
    /**
     * 最后一个错误
     */
    public String LastError;
    /**
     * 保存到临时文档
     */
    public boolean UseTempDict = false;
    /**
     * 是否忽略大小写
     */
    public final boolean IgnoreCase;
    /**
     * 使用本地时区
     */
    public boolean UseLocalTime = false;
    private ProgContext _context;
    private final Map _tempdict;
    public DistanceUnitType DistanceUnit = DistanceUnitType.M;
    public AreaUnitType AreaUnit = AreaUnitType.M2;
    public VolumeUnitType VolumeUnit = VolumeUnitType.M3;
    public MassUnitType MassUnit = MassUnitType.KG;

    /// 
    /// 默认不带缓存
    /// 
    public AlgorithmEngine() {
        IgnoreCase = false;
        _tempdict = new TreeMap();
    }

    /// 
    /// 带缓存关键字大小写参数
    /// 
    /// 
    public AlgorithmEngine(boolean ignoreCase) {
        IgnoreCase = ignoreCase;
        if (ignoreCase) {
            _tempdict = new TreeMap(String.CASE_INSENSITIVE_ORDER);
        } else {
            _tempdict = new TreeMap();
        }
    }

    private Operand GetDiyParameterInside(String parameter) {
        if (_tempdict.containsKey(parameter)) {
            return _tempdict.get(parameter);
        }
        Operand result = GetParameter(parameter);
        if (UseTempDict) {
            _tempdict.put(parameter, result);
        }
        return result;
    }

    protected Operand GetParameter(final String parameter) {
        return Operand.Error("Parameter [" + parameter + "] is missing.");
    }

    protected Operand ExecuteDiyFunction(final String funcName, final List operands) {
        return Operand.Error("DiyFunction [" + funcName + "] is missing.");
    }

    public void ClearParameters() {
        _tempdict.clear();
    }

    /**
     * 添加自定义参数
     */
    public void AddParameter(final String key, final Operand obj) {
        _tempdict.put(key, obj);
    }

    /**
     * 添加自定义参数
     */
    public void AddParameter(final String key, final boolean obj) {
        _tempdict.put(key, Operand.Create(obj));
    }

    /**
     * 添加自定义参数
     */
    public void AddParameter(final String key, final short obj) {
        _tempdict.put(key, Operand.Create(obj));
    }

    /**
     * 添加自定义参数
     */
    public void AddParameter(final String key, final int obj) {
        _tempdict.put(key, Operand.Create(obj));
    }

    /**
     * 添加自定义参数
     */
    public void AddParameter(final String key, final long obj) {
        _tempdict.put(key, Operand.Create(obj));
    }

    /**
     * 添加自定义参数
     */
    public void AddParameter(final String key, final float obj) {
        _tempdict.put(key, Operand.Create(obj));
    }

    /**
     * 添加自定义参数
     */
    public void AddParameter(final String key, final double obj) {
        _tempdict.put(key, Operand.Create(obj));
    }

    /**
     * 添加自定义参数
     */
    public void AddParameter(final String key, final BigDecimal obj) {
        _tempdict.put(key, Operand.Create(obj));
    }

    /**
     * 添加自定义参数
     */
    public void AddParameter(final String key, final String obj) {
        _tempdict.put(key, Operand.Create(obj));
    }

    /**
     * 添加自定义参数
     */
    public void AddParameter(final String key, final MyDate obj) {
        _tempdict.put(key, Operand.Create(obj));
    }

    /**
     * 添加自定义参数
     */
    public void AddParameter(final String key, final List obj) {
        _tempdict.put(key, Operand.Create(obj));
    }

    /**
     * 添加自定义参数
     */
    public void AddParameterFromJson(final String json) throws Exception {
        if (json.startsWith("{") && json.endsWith("}")) {
            final JsonData jo = (JsonData) JsonMapper.ToObject(json);
            if (jo.IsObject()) {
                for (String item : jo.inst_object.keySet()) {
                    final JsonData v = jo.inst_object.get(item);
                    if (v.IsString())
                        _tempdict.put(item, Operand.Create(v.StringValue()));
                    else if (v.IsBoolean())
                        _tempdict.put(item, Operand.Create(v.BooleanValue()));
                    else if (v.IsDouble())
                        _tempdict.put(item, Operand.Create(v.NumberValue()));
                    else if (v.IsObject())
                        _tempdict.put(item, Operand.Create(v));
                    else if (v.IsArray())
                        _tempdict.put(item, Operand.Create(v));
                    else if (v.IsNull())
                        _tempdict.put(item, Operand.CreateNull());
                }
                return;
            }
        }
        throw new Exception("Parameter is not json String.");
    }

    public boolean Parse(final String exp) throws RecognitionException {
        if (exp == null || exp.equals("")) {
            LastError = "Parameter exp invalid !";
            return false;
        }
        final AntlrCharStream stream = new AntlrCharStream(CharStreams.fromString(exp));
        final mathLexer lexer = new mathLexer(stream);
        final CommonTokenStream tokens = new CommonTokenStream(lexer);
        final mathParser parser = new mathParser(tokens);
        final AntlrErrorListener antlrErrorListener = new AntlrErrorListener();
        parser.removeErrorListeners();
        parser.addErrorListener(antlrErrorListener);
        final ProgContext context = parser.prog();

        if (antlrErrorListener.IsError) {
            _context = null;
            LastError = antlrErrorListener.ErrorMsg;
            return false;
        }
        _context = context;
        return true;
    }

    public Operand Evaluate() throws Exception {
        if (_context == null) {
            LastError = "Please use Parse to compile formula !";
            throw new Exception("Please use Parse to compile formula !");
        }
        final MathVisitor visitor = new MathVisitor();
        visitor.GetParameter = f -> {
            try {
                return GetDiyParameterInside(f);
            } catch (Exception e) {
            }
            return null;
        };
        visitor.excelIndex = UseExcelIndex ? 1 : 0;

        visitor.DiyFunction = f -> {
            return ExecuteDiyFunction(f.Name, f.OperandList);
        };
        visitor.useLocalTime = UseLocalTime;
        visitor.DistanceUnit= DistanceUnit;
        visitor.AreaUnit=AreaUnit;
        visitor.VolumeUnit=VolumeUnit;
        visitor.MassUnit=MassUnit;
        return visitor.visit(_context);
    }

    public BigDecimal TryEvaluate(final String exp, final BigDecimal defvalue) {
        try {
            if (Parse(exp)) {
                Operand obj = Evaluate();
                obj = obj.ToNumber("It can't be converted to number!");
                if (obj.IsError()) {
                    LastError = obj.ErrorMsg();
                    return defvalue;
                }
                return obj.NumberValue();
            }
        } catch (final Exception ex) {
            LastError = ex.getMessage();
        }
        return defvalue;
    }

    public int TryEvaluate(final String exp, final int defvalue) {
        try {
            if (Parse(exp)) {
                Operand obj = Evaluate();
                obj = obj.ToNumber("It can't be converted to number!");
                if (obj.IsError()) {
                    LastError = obj.ErrorMsg();
                    return defvalue;
                }
                return obj.IntValue();
            }
        } catch (final Exception ex) {
            LastError = ex.getMessage();
        }
        return defvalue;
    }

    public double TryEvaluate(final String exp, final double defvalue) {
        try {
            if (Parse(exp)) {
                Operand obj = Evaluate();
                obj = obj.ToNumber("It can't be converted to number!");
                if (obj.IsError()) {
                    LastError = obj.ErrorMsg();
                    return defvalue;
                }
                return obj.DoubleValue();
            }
        } catch (final Exception ex) {
            LastError = ex.getMessage();
        }
        return defvalue;
    }

    public long TryEvaluate(final String exp, final long defvalue) {
        try {
            if (Parse(exp)) {
                Operand obj = Evaluate();
                obj = obj.ToNumber("It can't be converted to number!");
                if (obj.IsError()) {
                    LastError = obj.ErrorMsg();
                    return defvalue;
                }
                return obj.LongValue();
            }
        } catch (final Exception ex) {
            LastError = ex.getMessage();
        }
        return defvalue;
    }

    public String TryEvaluate(final String exp, final String defvalue) {
        try {
            if (Parse(exp)) {
                Operand obj = Evaluate();
                if (obj.IsNull()) {
                    return null;
                }
                obj = obj.ToText("It can't be converted to String!");
                if (obj.IsError()) {
                    LastError = obj.ErrorMsg();
                    return defvalue;
                }
                return obj.TextValue();
            }
        } catch (final Exception ex) {
            LastError = ex.getMessage();
        }
        return defvalue;
    }

    public boolean TryEvaluate(final String exp, final boolean defvalue) {
        try {
            if (Parse(exp)) {
                Operand obj = Evaluate();
                obj = obj.ToBoolean("It can't be converted to boolean!");
                if (obj.IsError()) {
                    LastError = obj.ErrorMsg();
                    return defvalue;
                }
                return obj.BooleanValue();
            }
        } catch (final Exception ex) {
            LastError = ex.getMessage();
        }
        return defvalue;
    }

    public DateTime TryEvaluate(final String exp, final DateTime defvalue) {
        try {
            if (Parse(exp)) {
                Operand obj = Evaluate();
                obj = obj.ToDate("It can't be converted to DateTime!");
                if (obj.IsError()) {
                    LastError = obj.ErrorMsg();
                    return defvalue;
                }
                if (UseLocalTime) {
                    return obj.DateValue().ToDateTime(DateTimeZone.getDefault());
                }
                return obj.DateValue().ToDateTime(DateTimeZone.UTC);
            }
        } catch (final Exception ex) {
            LastError = ex.getMessage();
        }
        return defvalue;
    }

    public MyDate TryEvaluate(final String exp, final MyDate defvalue) {
        try {
            if (Parse(exp)) {
                Operand obj = Evaluate();
                obj = obj.ToDate("It can't be converted to MyDate!");
                if (obj.IsError()) {
                    LastError = obj.ErrorMsg();
                    return defvalue;
                }
                return obj.DateValue();
            }
        } catch (final Exception ex) {
            LastError = ex.getMessage();
        }
        return defvalue;
    }

    /**
     * 获取简化公式
     *
     * @param formula 公式
     */
    public String GetSimplifiedFormula(final String formula) {
        try {
            if (Parse(formula)) {
                final MathSimplifiedFormulaVisitor visitor = new MathSimplifiedFormulaVisitor();
                visitor.GetParameter = f -> {
                    try {
                        return GetDiyParameterInside(f);
                    } catch (Exception e) {
                    }
                    return null;
                };
                visitor.excelIndex = UseExcelIndex ? 1 : 0;
                visitor.DiyFunction = f -> {
                    return ExecuteDiyFunction(f.Name, f.OperandList);
                };
                visitor.useLocalTime = UseLocalTime;
                visitor.DistanceUnit= DistanceUnit;
                visitor.AreaUnit=AreaUnit;
                visitor.VolumeUnit=VolumeUnit;
                visitor.MassUnit=MassUnit;
                Operand obj = visitor.visit(_context);
                obj = obj.ToText("It can't be converted to String!");
                if (obj.IsError()) {
                    LastError = obj.ErrorMsg();
                    return null;
                }
                return obj.TextValue();
            }
        } catch (final Exception ex) {
            LastError = ex.getMessage();
        }
        return null;
    }

    /**
     * 计算公式
     *
     * @param formula   公式
     * @param splitChar 分隔符
     * @return
     */
    public String EvaluateFormula(String formula, Character splitChar) {
        if (formula == null || formula.equals(""))
            return "";
        List splitChars = new ArrayList<>();
        splitChars.add(splitChar);
        return EvaluateFormula(formula, splitChars);
    }

    /**
     * 计算公式
     *
     * @param formula    公式
     * @param splitChars 分隔符
     * @return
     */
    public String EvaluateFormula(String formula, List splitChars) {
        if (formula == null || formula.equals(""))
            return "";
        List sp = CharUtil.SplitFormula(formula, splitChars);

        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < sp.size(); i++) {
            String s = sp.get(i);
            if (s.length() == 1 && splitChars.contains(s.charAt(0))) {
                stringBuilder.append(s);
            } else {
                // TODO 替换此处
                String d = TryEvaluate(s, "");
                stringBuilder.append(d);
            }
        }
        return stringBuilder.toString();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy