• 基于Java的简易表达式解析工具(二)


    之前简单的介绍了这个基于Java表达式解析工具,现在把代码分享给大家,希望帮助到有需要的人们,这个分享代码中依赖了一些其他的类,这些类大家可以根据自己的情况进行导入,无非就是写字符串处理工具类,日期处理的工具类什么的。

    这个Java的表达式解析的工具只用了5个类,而且写得也很简单明了,相信有一些编程经验的可以看懂这些处理的逻辑代码。

    1、第一个类:ExpressionNodeType(表达式各个字符节点的类型枚举类)

    [java] view plain copy
     
     print?
    1. public enum ExpressionNodeType {  
    2.   
    3.     Unknown,  
    4.     Plus,// +  
    5.     Subtract, /// -  
    6.     MultiPly,// *  
    7.     Divide,// /  
    8.     LParentheses,//(  
    9.     RParentheses, /// )  
    10.     Mod,//% (求模,取余)  
    11.     Power,// ^ (次幂)  
    12.     BitwiseAnd, /// & (按位与)  
    13.     BitwiseOr,/// | (按位或)  
    14.     And,// && (逻辑与)  
    15.     Or, /// || (逻辑或)  
    16.     Not,/// ! (逻辑非)  
    17.     Equal,/// == (相等)  
    18.     Unequal,/// != 或 <> (不等于)  
    19.     GT, /// > (大于)  
    20.     LT, /// < (小于)  
    21.     GTOrEqual,/// >= (大于等于)  
    22.     LTOrEqual, /// <= (小于等于)  
    23.     LShift,  /// << (左移位)  
    24.     RShift,/// >> (右移位)  
    25.     Numeric, /// 数值,  
    26.     String,  
    27.     Date,  
    28.     Like,//包含  
    29.     NotLike,//不包含  
    30.     StartWith,//已什么开始  
    31.     EndWith//已什么结尾  
    32.       
    33. }  

    这个类中定义了一些枚举的类型,如加减乘数啊,等于不等于啊,包含不包含啊,如果要进行扩展的话,第一步需要在这里定义一种枚举类型。

    2、第二个类:ExpressionNode(存储表达式运算符或操作数的各个节点的类)

    [java] view plain copy
     
     print?
    1. public class ExpressionNode {  
    2.   
    3.      private String value;  
    4.        
    5.      private ExpressionNodeType type;  
    6.        
    7.      private int pri;  
    8.        
    9.      private ExpressionNode unitaryNode;  
    10.        
    11.      private Object numeric;  
    12.        
    13.     /** 
    14.      *  
    15.      * @param value 操作数或运算符 
    16.      */  
    17.     public ExpressionNode(String value)  
    18.     {  
    19.         this.value = value;  
    20.         this.type = parseNodeType(value);  
    21.         this.pri = getNodeTypePRI(this.type);  
    22.         this.numeric = null;  
    23.     }  
    24.   
    25.      
    26.     public Object getNumeric(){  
    27.         if(this.numeric == null){  
    28.               
    29.              if ((this.type == ExpressionNodeType.String) || (this.type == ExpressionNodeType.Date))  
    30.              {  
    31.                  return this.value;  
    32.              }  
    33.               
    34.              if (this.type != ExpressionNodeType.Numeric){  
    35.                  return 0;  
    36.              }   
    37.              Double num = new Double(this.value);  
    38.              if (this.unitaryNode != null && this.unitaryNode.type == ExpressionNodeType.Subtract)  
    39.              {  
    40.                  num = 0 - num;  
    41.              }  
    42.              this.numeric =  num;  
    43.         }  
    44.         return numeric;  
    45.     }  
    46.       
    47.       
    48.     public void setNumeric(Object numeric) {  
    49.          this.numeric = numeric;  
    50.          this.value = this.numeric.toString();  
    51.     }  
    52.       
    53.     /** 
    54.      * 设置或返回与当前节点相关联的一元操作符节点 
    55.      * @param unitaryNode 
    56.      */  
    57.     public void setUnitaryNode(ExpressionNode unitaryNode) {  
    58.         this.unitaryNode = unitaryNode;  
    59.     }  
    60.   
    61.     /** 
    62.      *  解析节点类型 
    63.      * @param value 
    64.      * @return 
    65.      */  
    66.     private static ExpressionNodeType parseNodeType(String value)  
    67.     {  
    68.         if (StringUtils.isEmpty(value)){  
    69.             return ExpressionNodeType.Unknown;  
    70.         }   
    71.         switch (value)  
    72.         {  
    73.             case "+":  
    74.                 return ExpressionNodeType.Plus;  
    75.             case "-":  
    76.                 return ExpressionNodeType.Subtract;  
    77.             case "*":  
    78.                 return ExpressionNodeType.MultiPly;  
    79.             case "/":  
    80.                 return ExpressionNodeType.Divide;  
    81.             case "%":  
    82.                 return ExpressionNodeType.Mod;  
    83.             case "^":  
    84.                 return ExpressionNodeType.Power;  
    85.             case "(":  
    86.                 return ExpressionNodeType.LParentheses;  
    87.             case ")":  
    88.                 return ExpressionNodeType.RParentheses;  
    89.             case "&":  
    90.                 return ExpressionNodeType.BitwiseAnd;  
    91.             case "|":  
    92.                 return ExpressionNodeType.BitwiseOr;  
    93.             case "&&":  
    94.             case "<并且>":  
    95.             case "并且":  
    96.                 return ExpressionNodeType.And;  
    97.             case "||":  
    98.             case "<或者>":  
    99.             case "或者":  
    100.                 return ExpressionNodeType.Or;  
    101.             case "!":  
    102.                 return ExpressionNodeType.Not;  
    103.             case "==":  
    104.             case "=":  
    105.                 return ExpressionNodeType.Equal;  
    106.             case "!=":  
    107.             case "<>":  
    108.             case "≠":  
    109.                 return ExpressionNodeType.Unequal;  
    110.             case ">":  
    111.                 return ExpressionNodeType.GT;  
    112.             case "<":  
    113.                 return ExpressionNodeType.LT;  
    114.             case ">=":  
    115.             case "≥":     
    116.                 return ExpressionNodeType.GTOrEqual;  
    117.             case "<=":  
    118.             case "≤":     
    119.                 return ExpressionNodeType.LTOrEqual;  
    120.             case "<<":  
    121.                 return ExpressionNodeType.LShift;  
    122.             case ">>":  
    123.                 return ExpressionNodeType.RShift;  
    124.             case "@":  
    125.             case "<包含>":  
    126.             case "包含":  
    127.                 return ExpressionNodeType.Like;  
    128.             case "!@":  
    129.             case "<不包含>":  
    130.             case "不包含":  
    131.                 return ExpressionNodeType.NotLike;  
    132.             case "!!$":  
    133.                 return ExpressionNodeType.StartWith;  
    134.             case "!!@":  
    135.                 return ExpressionNodeType.EndWith;  
    136.              
    137.         }  
    138.         if (isNumerics(value))  
    139.         {  
    140.             return ExpressionNodeType.Numeric;  
    141.         }  
    142.         if (isDatetime(value))  
    143.         {  
    144.             return ExpressionNodeType.Date;  
    145.         }  
    146.         if (value.contains("""))  
    147.         {  
    148.             return ExpressionNodeType.String;  
    149.         }  
    150.         return ExpressionNodeType.Unknown;  
    151.     }  
    152.   
    153.     /** 
    154.      * 获取各节点类型的优先级 
    155.      * @param nodeType 
    156.      * @return 
    157.      */  
    158.     private static int getNodeTypePRI(ExpressionNodeType nodeType)  
    159.     {  
    160.         switch (nodeType)  
    161.         {  
    162.             case LParentheses:  
    163.             case RParentheses:  
    164.                 return 9;  
    165.             //逻辑非是一元操作符,所以其优先级较高  
    166.             case Not:  
    167.                 return 8;  
    168.             case Mod:  
    169.                 return 7;  
    170.             case MultiPly:  
    171.             case Divide:  
    172.             case Power:  
    173.                 return 6;  
    174.             case Plus:  
    175.             case Subtract:  
    176.                 return 5;  
    177.             case LShift:  
    178.             case RShift:  
    179.                 return 4;  
    180.             case BitwiseAnd:  
    181.             case BitwiseOr:  
    182.                 return 3;  
    183.             case Equal:  
    184.             case Unequal:  
    185.             case GT:  
    186.             case LT:  
    187.             case GTOrEqual:  
    188.             case LTOrEqual:  
    189.             case Like:  
    190.             case NotLike:  
    191.             case StartWith:  
    192.             case EndWith:  
    193.                 return 2;  
    194.             case And:  
    195.             case Or:  
    196.                 return 1;  
    197.             default:  
    198.                 return 0;  
    199.         }  
    200.           
    201.     }  
    202.   
    203.     /** 
    204.      * 判断是否为数值 
    205.      * @param op 
    206.      * @return 
    207.      */  
    208.     public static boolean isNumerics(String op)  
    209.     {  
    210.         return op.matches("^[\+\-]?(0|[1-9]\d*|[1-9]\d*\.\d+|0\.\d+)");  
    211.     }  
    212.   
    213.     /** 
    214.      * 判断是否为日期 
    215.      * @param op 
    216.      * @return 
    217.      */  
    218.     public static boolean isDatetime(String op)  
    219.     {  
    220.         op = op.replace(""","").trim();  
    221.         return op.matches("\d{4}\-\d{2}\-\d{2}(\s\d{2}\:\d{2}\:\d{2})?");  
    222.     }  
    223.   
    224.       
    225.     /** 
    226.      * 判断某个字符后是否需要更多的操作符 
    227.      * @param c 
    228.      * @return 
    229.      */  
    230.     public static boolean needMoreOperator(char c)  
    231.     {  
    232.         switch (c)  
    233.         {  
    234.             case '&':  
    235.             case '|':  
    236.             case '=':  
    237.             case '!':  
    238.             case '>':  
    239.             case '<':  
    240.             case '.':   //小数点  
    241.                 return true;  
    242.         }  
    243. //        //数字则需要更多  
    244.         return Character.isDigit(c);  
    245.     }  
    246.   
    247.     /** 
    248.      * 判断两个字符是否是同一类 
    249.      * @param c1 
    250.      * @param c2 
    251.      * @return 
    252.      */  
    253.     public static boolean IsCongener(char c1, char c2)  
    254.     {  
    255.          if ((c1 == '(') || (c2 == '(')){  
    256.              return false;  
    257.          }  
    258.          if ((c1 == ')') || (c2 == ')')){  
    259.              return false;  
    260.          }  
    261.          if ((c1 == '"') || (c2 == '"')){  
    262.              return false;  
    263.          }  
    264.          if (Character.isDigit(c1) || (c1 == '.'))  
    265.          {  
    266.             //c1为数字,则c2也为数字  
    267.              return (Character.isDigit(c2) || (c2 == '.'));  
    268.          }  
    269.          return (!Character.isDigit(c2) && (c2 != '.'));  
    270.     }  
    271.   
    272.     /** 
    273.      * 判断某个字符是否是空白字符 
    274.      * @param c 
    275.      * @return 
    276.      */  
    277.     public static boolean IsWhileSpace(char c)  
    278.     {  
    279.         return c == ' ' || c == ' ';  
    280.     }  
    281.   
    282.     /** 
    283.      * 判断是否是一元操作符节点 
    284.      * @param nodeType 
    285.      * @return 
    286.      */  
    287.     public static boolean IsUnitaryNode(ExpressionNodeType nodeType)  
    288.     {  
    289.         return (nodeType == ExpressionNodeType.Plus || nodeType == ExpressionNodeType.Subtract);  
    290.     }  
    291.   
    292.     public String getValue() {  
    293.         return value;  
    294.     }  
    295.   
    296.     public void setValue(String value) {  
    297.         this.value = value;  
    298.     }  
    299.   
    300.     public ExpressionNodeType getType() {  
    301.         return type;  
    302.     }  
    303.   
    304.     public void setType(ExpressionNodeType type) {  
    305.         this.type = type;  
    306.     }  
    307.   
    308.     public int getPri() {  
    309.         return pri;  
    310.     }  
    311.   
    312.     public void setPri(int pri) {  
    313.         this.pri = pri;  
    314.     }  
    315.   
    316.     public ExpressionNode getUnitaryNode() {  
    317.         return unitaryNode;  
    318.     }  


    当需要解析一个表达式时,会把表达式中的每个字符生生成一个ExpressionNode对象,并存储了这个字符的节点类型,字符后面是否有其他字符等一些信息。

    3、第三个类:ExpressionException(表达式异常类)

    [java] view plain copy
     
     print?
    1. public class ExpressionException extends RuntimeException{  
    2.   
    3.     private static final long serialVersionUID = 1L;  
    4.   
    5.     public ExpressionException() {  
    6.         super();  
    7.     }  
    8.   
    9.     public ExpressionException(String msg) {  
    10.         super(msg);  
    11.     }  
    12.       
    13.     public ExpressionException(String msg, Throwable cause) {  
    14.         super(msg,cause);  
    15.     }  
    16.       
    17.     public ExpressionException(Throwable cause) {  
    18.         super(cause);  
    19.     }  
    20. }  


    4、第四个类:ExpressionParser(负责读取表达式生成ExpressionNode对象的类)

    [java] view plain copy
     
     print?
    1. public class ExpressionParser {  
    2.   
    3.     //当前分析的表达式  
    4.     private String expression;  
    5.       
    6.     //当前读取的位置  
    7.     private int position;  
    8.       
    9.     public String getExpression() {  
    10.         return expression;  
    11.     }  
    12.   
    13.     public void setExpression(String expression) {  
    14.         this.expression = expression;  
    15.     }  
    16.   
    17.     public int getPosition() {  
    18.         return position;  
    19.     }  
    20.   
    21.     public void setPosition(int position) {  
    22.         this.position = position;  
    23.     }  
    24.   
    25.     public ExpressionParser(String expression)  
    26.     {  
    27.         this.expression = expression;  
    28.         this.position = 0;  
    29.     }  
    30.   
    31.     /** 
    32.      *  读取下一个表达式节点,如果读取失败则返回null 
    33.      * @return 
    34.      */  
    35.     public ExpressionNode readNode()  
    36.     {  
    37.         //空格的位置  
    38.         int whileSpacePos = -1;  
    39.         boolean flag = false;  
    40.         StringBuffer buffer = new StringBuffer(10);  
    41.         while (this.position < this.expression.length())  
    42.         {  
    43.             char c = this.expression.charAt(this.position);  
    44.             if (c == '"')  
    45.             {  
    46.                 flag = !flag;  
    47.                 if (!flag)  
    48.                 {  
    49.                     this.position++;  
    50.                     buffer.append(c);  
    51.                     break;  
    52.                 }  
    53.                 if (buffer.length() != 0)  
    54.                 {  
    55.                     break;  
    56.                 }  
    57.             }  
    58.             if (flag)  
    59.             {  
    60.                 this.position++;  
    61.                 buffer.append(c);  
    62.             }  
    63.             else  
    64.             {  
    65.                 if (ExpressionNode.IsWhileSpace(c))  
    66.                 {  
    67.                     if ((whileSpacePos >= 0) && ((this.position - whileSpacePos) > 1))  
    68.                     {  
    69.                         throw new ExpressionException(String.format("表达式"%s"在位置(%s)上的字符非法!", this.getExpression(), this.getPosition()));  
    70.                     }  
    71.                     if (buffer.length() == 0)  
    72.                     {  
    73.                         whileSpacePos = -1;  
    74.                     }  
    75.                     else  
    76.                     {  
    77.                         whileSpacePos = this.position;  
    78.                     }  
    79.                     this.position++;  
    80.                     continue;  
    81.                 }  
    82.                 if ((buffer.length() == 0) || ExpressionNode.IsCongener(c, buffer.charAt(buffer.length() - 1)))  
    83.                 {  
    84.                     this.position++;  
    85.                     buffer.append(c);  
    86.                 }  
    87.                 else  
    88.                 {  
    89.                     break;  
    90.                 }  
    91.                 if (!ExpressionNode.needMoreOperator(c))  
    92.                 {  
    93.                     break;  
    94.                 }  
    95.             }  
    96.         }  
    97.         if (buffer.length() == 0)  
    98.         {  
    99.             return null;  
    100.         }  
    101.         ExpressionNode node = new ExpressionNode(buffer.toString());  
    102.         if (node.getType() == ExpressionNodeType.Unknown)  
    103.         {  
    104.             throw new ExpressionException(String.format("表达式"%s"在位置%s上的字符"%s"非法!", this.getExpression(), this.getPosition() - node.getValue().length(), node.getValue()));  
    105.         }  
    106.         return node;  
    107.     }  
    108.       
    109. }  


    这个类处理将待解析的表达式,解析并创建ExpressionNode对象。

    5、第五个类:ExpressionEvaluator(解析公式并返回结果的类)

    [java] view plain copy
     
     print?
    1. public class ExpressionEvaluator {  
    2.   
    3.      private ExpressionEvaluator()  
    4.      {  
    5.            
    6.      }  
    7.       
    8.      /** 
    9.       * 将算术表达式转换为逆波兰表达式 
    10.       * @param expression 要计算的表达式,如"1+2+3+4" 
    11.       * @return 
    12.       */  
    13.      private static List<ExpressionNode> parseExpression(String expression)  
    14.      {  
    15.          if(StringUtils.isEmpty(expression)){  
    16.              return new ArrayList<ExpressionNode>();  
    17.          }  
    18.   
    19.          List<ExpressionNode> listOperator = new ArrayList<ExpressionNode>(10);  
    20.          Stack<ExpressionNode> stackOperator = new Stack<ExpressionNode>();  
    21.   
    22.          ExpressionParser expParser = new ExpressionParser(expression);  
    23.          ExpressionNode beforeExpNode = null;       //前一个节点              
    24.          ExpressionNode unitaryNode = null;         //一元操作符  
    25.          ExpressionNode expNode;  
    26.   
    27.          //是否需要操作数  
    28.          boolean requireOperand = false;  
    29.   
    30.   
    31.          while ((expNode = expParser.readNode()) != null)  
    32.          {  
    33.              if ( (expNode.getType() == ExpressionNodeType.Numeric) ||   
    34.                      (expNode.getType() == ExpressionNodeType.String) ||   
    35.                      (expNode.getType() == ExpressionNodeType.Date))  
    36.              {  
    37.                  //操作数, 直接加入后缀表达式中  
    38.                  if (unitaryNode != null)  
    39.                  {  
    40.                      //设置一元操作符节点  
    41.                      expNode.setUnitaryNode(unitaryNode);  
    42.                      unitaryNode = null;  
    43.                  }  
    44.   
    45.                  listOperator.add(expNode);  
    46.                  requireOperand = false;  
    47.                  continue;  
    48.              }  
    49.              else if (expNode.getType() == ExpressionNodeType.LParentheses)  
    50.              {  
    51.                  //左括号, 直接加入操作符栈  
    52.                  stackOperator.push(expNode);  
    53.                  continue;  
    54.              }  
    55.              else if (expNode.getType() == ExpressionNodeType.RParentheses)  
    56.              {  
    57.                  //右括号则在操作符栈中反向搜索,直到遇到匹配的左括号为止,将中间的操作符依次加到后缀表达式中。  
    58.                  ExpressionNode lpNode = null;  
    59.                  while (stackOperator.size() > 0)  
    60.                  {  
    61.                      lpNode = stackOperator.pop();  
    62.                      if (lpNode.getType() == ExpressionNodeType.LParentheses) break;  
    63.                      listOperator.add(lpNode);  
    64.                  }  
    65.                  if (lpNode == null || lpNode.getType() != ExpressionNodeType.LParentheses)  
    66.                  {  
    67.                      throw new ExpressionException(String.format("在表达式"%s"中没有与在位置(%s)上")"匹配的"(%s)"字符!", expParser.getExpression(), expParser.getPosition()));  
    68.                  }  
    69.              }  
    70.              else  
    71.              {  
    72.                  if (stackOperator.size() == 0)  
    73.                  {  
    74.                      //第一个节点则判断此节点是否是一元操作符"+,-,!,("中的一个,否则其它都非法  
    75.                      if (listOperator.size() == 0 &&  
    76.                          !(expNode.getType() == ExpressionNodeType.LParentheses || expNode.getType() == ExpressionNodeType.Not))  
    77.                      {  
    78.                          //后缀表达式没有任何数据则判断是否是一元操作数  
    79.                          if (ExpressionNode.IsUnitaryNode(expNode.getType()))  
    80.                          {  
    81.                              unitaryNode = expNode;  
    82.                          }  
    83.                          else  
    84.                          {  
    85.                              //丢失操作数  
    86.                              throw new ExpressionException(String.format("表达式"%s"在位置(%s)上缺少操作数!", expParser.getExpression(), expParser.getPosition()));  
    87.                          }  
    88.                      }  
    89.                      else  
    90.                      {  
    91.                          //直接压入操作符栈  
    92.                          stackOperator.push(expNode);  
    93.                      }  
    94.                      requireOperand = true;          //下一个节点需要操作数  
    95.                      continue;  
    96.                  }  
    97.                  else  
    98.                  {  
    99.                      if (requireOperand)  
    100.                      {  
    101.                          //如果需要操作数则判断当前的是否是"+","-"号(一元操作符),如果是则继续  
    102.                          if (ExpressionNode.IsUnitaryNode(expNode.getType()) && unitaryNode == null)  
    103.                          {  
    104.                              unitaryNode = expNode;  
    105.                          }  
    106.                          else  
    107.                          {  
    108.                              //丢失操作数  
    109.                              throw new ExpressionException(String.format("表达式"%s"在位置({1})上缺少操作数!", expParser.getExpression(), expParser.getPosition()));  
    110.                          }  
    111.                      }  
    112.                      else  
    113.                      {  
    114.                          //对前面的所有操作符进行优先级比较  
    115.                          do  
    116.                          {  
    117.                              //取得上一次的操作符  
    118.                              beforeExpNode = stackOperator.peek();  
    119.   
    120.                              //如果前一个操作符优先级较高,则将前一个操作符加入后缀表达式中  
    121.                              if (beforeExpNode.getType() != ExpressionNodeType.LParentheses && (beforeExpNode.getPri() - expNode.getPri()) >= 0)  
    122.                              {  
    123.                                  listOperator.add(stackOperator.pop());  
    124.                              }  
    125.                              else  
    126.                              {  
    127.                                  break;  
    128.                              }  
    129.   
    130.                          } while (stackOperator.size() > 0);  
    131.   
    132.                          //将操作符压入操作符栈  
    133.                          stackOperator.push(expNode);  
    134.                          requireOperand = true;  
    135.                      }  
    136.                  }  
    137.              }  
    138.          }  
    139.   
    140.          if (requireOperand)  
    141.          {  
    142.              //丢失操作数  
    143.              throw new ExpressionException(String.format("表达式"%s"在位置({1})上缺少操作数!", expParser.getExpression(), expParser.getPosition()));  
    144.          }  
    145.          //清空堆栈  
    146.          while (stackOperator.size() > 0)  
    147.          {  
    148.              //取得操作符  
    149.              beforeExpNode = stackOperator.pop();  
    150.              if (beforeExpNode.getType() == ExpressionNodeType.LParentheses)  
    151.              {  
    152.                  throw new ExpressionException(String.format("表达式"%s"中括号不匹配,丢失右括号!", expParser.getExpression(), expParser.getPosition()));  
    153.              }  
    154.              listOperator.add(beforeExpNode);  
    155.          }  
    156.   
    157.          return listOperator;  
    158.      }  
    159.       
    160.      /** 
    161.       * 对逆波兰表达式进行计算 
    162.       * @param nodes 
    163.       * @return 
    164.       */  
    165.      private static Object CalcExpression(List<ExpressionNode> nodes)  
    166.      {  
    167.          if (nodes == null || nodes.size() == 0) return null;  
    168.   
    169.          if (nodes.size() > 1)  
    170.          {  
    171.              int index = 0;  
    172.              //储存数据  
    173.              ArrayList values = new ArrayList();  
    174.              while (index < nodes.size())  
    175.              {  
    176.                  ExpressionNode node = nodes.get(index);  
    177.                           
    178.                  switch (node.getType())  
    179.                  {  
    180.                      //如果是数字,则将值存入 values 中  
    181.                      case Numeric:  
    182.                      case String:  
    183.                      case Date:  
    184.                          values.add(node.getNumeric());  
    185.                          index++;  
    186.                          break;  
    187.                      default:     
    188.                          //二元表达式,需要二个参数, 如果是Not的话,则只要一个参数  
    189.                          int paramCount = 2;  
    190.                          if (node.getType() == ExpressionNodeType.Not) paramCount = 1;  
    191.                          //计算操作数的值  
    192.                          if (values.size() < paramCount)  
    193.                          {  
    194.                              throw new ExpressionException("缺少操作数");  
    195.                          }  
    196.                          //传入参数  
    197.                          Object[] data = new Object[paramCount];  
    198.                          for (int i = 0; i < paramCount; i++)  
    199.                          {  
    200.                              data[i] = values.get(index - paramCount + i);  
    201.                          }  
    202.                          //将计算结果再存入当前节点  
    203.                          node.setNumeric(calculate(node.getType(), data));  
    204.                          node.setType( ExpressionNodeType.Numeric);  
    205.                          //将操作数节点删除  
    206.                          for (int i = 0; i < paramCount; i++)  
    207.                          {  
    208.                              nodes.remove(index - i - 1);  
    209.                              values.remove(index - i - 1);  
    210.                          }  
    211.                          index -= paramCount;  
    212.                          break;  
    213.                  }  
    214.                    
    215.              }  
    216.          }  
    217.   
    218.          if (nodes.size() != 1)  
    219.          {  
    220.              throw new ExpressionException("缺少操作符或操作数");  
    221.          }  
    222.          switch (nodes.get(0).getType())  
    223.          {  
    224.              case Numeric:  
    225.                  return nodes.get(0).getNumeric();  
    226.   
    227.              case String:  
    228.              case Date:  
    229.                  return nodes.get(0).getNumeric().toString().replace(""", "");  
    230.          }  
    231.          throw new ExpressionException("缺少操作数");  
    232.      }  
    233.        
    234.      /** 
    235.       * 计算节点的值 
    236.       * @param nodeType 节点的类型 
    237.       * @param data 要计算的值,有可能是两位或一位数 
    238.       * @return 
    239.       */  
    240.      private static Object calculate(ExpressionNodeType nodeType, Object[] data)  
    241.      {  
    242.          double d1, d2;  
    243.          boolean  b1, b2;  
    244.          Date time1,time2;  
    245.          Object obj1 = data[0];  
    246.          Object obj2 = data[1];  
    247.          String str1 = obj1.toString();  
    248.          String str2 = obj2.toString();  
    249.            
    250.          boolean dateflag = ExpressionNode.isDatetime(str1) || ExpressionNode.isDatetime(str2);  
    251.          boolean strflag = str1.contains(""") || str2.contains(""");  
    252.          str1 = str1.replace(""", "");  
    253.          str2 = str2.replace(""", "");  
    254.            
    255.          switch (nodeType)  
    256.          {  
    257.              case Plus:  
    258.                  if (!strflag)  
    259.                  {  
    260.                      d1 = ConvertToDecimal(obj1);  
    261.                      d2 = ConvertToDecimal(obj2);  
    262.                      return (d1 + d2);  
    263.                  }  
    264.                  return new StringBuffer(str1 + str2).toString();  
    265.              case Subtract:  
    266.                  d1 = ConvertToDecimal(obj1);  
    267.                  d2 = ConvertToDecimal(obj2);  
    268.                  return d1 - d2;  
    269.              case MultiPly:  
    270.                  d1 = ConvertToDecimal(obj1);  
    271.                  d2 = ConvertToDecimal(obj2);  
    272.                  return d1 * d2;  
    273.              case Divide:  
    274.                  d1 = ConvertToDecimal(obj1);  
    275.                  d2 = ConvertToDecimal(obj2);  
    276.                  if (d2 == 0)throw new RuntimeException();  
    277.                  return d1 / d2;  
    278.              case Power:  
    279.                  d1 = ConvertToDecimal(obj1);  
    280.                  d2 = ConvertToDecimal(obj2);  
    281.                  return Math.pow((double)d1, (double)d2);  
    282.              case Mod:  
    283.                  d1 = ConvertToDecimal(obj1);  
    284.                  d2 = ConvertToDecimal(obj2);  
    285.                  if (d2 == 0) throw new RuntimeException();  
    286.                  return d1 % d2;  
    287.              case BitwiseAnd:  
    288.                  d1 = ConvertToDecimal(obj1);  
    289.                  d2 = ConvertToDecimal(obj2);  
    290.                  return (int)d1 & (int)d2;  
    291.              case BitwiseOr:  
    292.                  d1 = ConvertToDecimal(obj1);  
    293.                  d2 = ConvertToDecimal(obj2);  
    294.                  return (int)d1 | (int)d2;  
    295.              case And:  
    296.                  b1 = ConvertToBool(obj1);  
    297.                  b2 = ConvertToBool(obj2);  
    298.                  return b1 && b2;  
    299.              case Or:  
    300.                  b1 = ConvertToBool(obj1);  
    301.                  b2 = ConvertToBool(obj2);  
    302.                  return b1 || b2;  
    303.              case Not:  
    304.                  b1 = ConvertToBool(obj1);  
    305.                  return !b1;  
    306.              case Equal:  
    307.                  if (!dateflag)  
    308.                  {  
    309.                      if (strflag)  
    310.                      {  
    311.                          return str1.equals(str2);  
    312.                      }  
    313.                      d1 = ConvertToDecimal(obj1);  
    314.                      d2 = ConvertToDecimal(obj2);  
    315.                      return (d1 == d2);  
    316.                  }  
    317.                  time1 = DateUtils.parse(str1);  
    318.                  time2 = DateUtils.parse(str2);  
    319.                    
    320.                  return (time1.getTime() == time2.getTime());  
    321.              case Unequal:  
    322.                  if (!dateflag)  
    323.                  {  
    324.                      if (strflag)  
    325.                      {  
    326.                          return (!str1.equals(str2));  
    327.                      }  
    328.                      d1 = ConvertToDecimal(obj1);  
    329.                      d2 = ConvertToDecimal(obj2);  
    330.                      return (d1 != d2);  
    331.                  }  
    332.                  time1 = DateUtils.parse(str1);  
    333.                  time2 = DateUtils.parse(str2);  
    334.                    
    335.                  return (time1.getTime() != time2.getTime());  
    336.              case GT:  
    337.                    
    338.                  if (!dateflag)  
    339.                  {  
    340.                      d1 = ConvertToDecimal(obj1);  
    341.                      d2 = ConvertToDecimal(obj2);  
    342.                      return (d1 > d2);  
    343.                  }  
    344.                  time1 = DateUtils.parse(str1);  
    345.                  time2 = DateUtils.parse(str2);  
    346.                  return (time1.getTime() > time2.getTime());  
    347.                    
    348.              case LT:  
    349.                    
    350.                  if (!dateflag)  
    351.                  {  
    352.                      d1 = ConvertToDecimal(obj1);  
    353.                      d2 = ConvertToDecimal(obj2);  
    354.                      return (d1 < d2);  
    355.                  }  
    356.                  time1 = DateUtils.parse(str1);  
    357.                  time2 = DateUtils.parse(str2);  
    358.                  return (time1.getTime() < time2.getTime());  
    359.                    
    360.              case GTOrEqual:  
    361.                    
    362.                  if (!dateflag)  
    363.                  {  
    364.                      d1 = ConvertToDecimal(obj1);  
    365.                      d2 = ConvertToDecimal(obj2);  
    366.                      return (d1 >= d2);  
    367.                  }  
    368.                  time1 = DateUtils.parse(str1);  
    369.                  time2 = DateUtils.parse(str2);  
    370.                  return (time1.getTime() >= time2.getTime());  
    371.                    
    372.              case LTOrEqual:  
    373.                  if (!dateflag)  
    374.                  {  
    375.                      d1 = ConvertToDecimal(obj1);  
    376.                      d2 = ConvertToDecimal(obj2);  
    377.                      return (d1 <= d2);  
    378.                  }  
    379.                  time1 = DateUtils.parse(str1);  
    380.                  time2 = DateUtils.parse(str2);  
    381.                  return (time1.getTime() <= time2.getTime());  
    382.              case LShift:  
    383.                  d1 = ConvertToDecimal(obj1);  
    384.                  d2 = ConvertToDecimal(obj2);  
    385.                  return (long)d1 << (int)d2;  
    386.                    
    387.              case RShift:  
    388.                  d1 = ConvertToDecimal(obj1);  
    389.                  d2 = ConvertToDecimal(obj2);  
    390.                  return (long)d1 >> (int)d2;  
    391.              case Like:  
    392.                  if (!strflag)  
    393.                  {  
    394.                      return false;  
    395.                  }  
    396.                  return str1.contains(str2);  
    397.              case NotLike:  
    398.                  if (!strflag)  
    399.                  {  
    400.                      return false;  
    401.                  }  
    402.                  return !str1.contains(str2);  
    403.              case StartWith:  
    404.                  if (!strflag)  
    405.                  {  
    406.                      return false;  
    407.                  }  
    408.                  return str1.startsWith(str2);  
    409.              case EndWith:  
    410.                  if (!strflag)  
    411.                  {  
    412.                      return false;  
    413.                  }  
    414.                  return str1.endsWith(str2);        
    415.          }  
    416.            
    417.          return 0;  
    418.      }  
    419.       
    420.      /** 
    421.       * 某个值转换为bool值 
    422.       * @param value 
    423.       * @return 
    424.       */  
    425.      private static Boolean ConvertToBool(Object value)  
    426.      {  
    427.          if (value instanceof Boolean){  
    428.              return (Boolean)value;  
    429.          }  
    430.          else{  
    431.              return value != null;  
    432.          }  
    433.      }  
    434.   
    435.      /** 
    436.       * 将某个值转换为decimal值 
    437.       * @param value 
    438.       * @return 
    439.       */  
    440.      private static Double ConvertToDecimal(Object value)  
    441.      {  
    442.          if (value instanceof Boolean)  
    443.          {  
    444.              return ((Boolean)value ? 1d : 0d);  
    445.          }  
    446.          else  
    447.          {  
    448.              return Double.parseDouble(value.toString());  
    449.          }  
    450.      }  
    451.       
    452.      /** 
    453.       *  
    454.       * @param expression 要计算的表达式,如"1+2+3+4" 
    455.       * @return 返回计算结果,如果带有逻辑运算符则返回true/false,否则返回数值 
    456.       */  
    457.      public static Object eval(String expression)  
    458.      {  
    459.          return CalcExpression(parseExpression(expression));  
    460.      }  
    461.        
    462.      public static Object evalThreeOperand(String expression)  
    463.      {  
    464.          int index = expression.indexOf("?");  
    465.          if (index > -1)  
    466.          {  
    467.              String str = expression.substring(0, index);  
    468.              String str2 = expression.substring(index + 1);  
    469.              index = str2.indexOf(":");  
    470.               
    471.              if ( Boolean.parseBoolean((CalcExpression(parseExpression(str))).toString()))  
    472.              {  
    473.                  return eval(str2.substring(0, index));  
    474.              }  
    475.              return eval(str2.substring(index + 1));  
    476.          }  
    477.          return CalcExpression(parseExpression(expression));  
    478.      }  
    479.        
    480. }  


    这个类是最重要的一个类,parseExpression方法会将待解析的表达式转变为ExpressionNode的集合,calculate方法会将两个值进行各种运算操作,也是在这个方法中,我们填写扩展的一些方法。

    这个工具的介绍就这些了,希望可以帮助到有需要的人。

  • 相关阅读:
    package.json 笔记
    TypeScript 笔记
    RxJS 笔记
    angular 使用Redux
    ngrx 笔记
    Node 的使用
    imoocLinux环境变量配置文件笔记
    imooc正则表达式学习笔记
    js定时器和linux命令locate
    linux修改PATH环境
  • 原文地址:https://www.cnblogs.com/csguo/p/7614869.html
Copyright © 2020-2023  润新知