Java 表达式解析(非原创)

因项目需要,在网上找来一套表达式解析方法,由于原来的方法太过于零散,不利于移植,现在整理在同一文件内;

文件中包含5个内部类,源码如下:

   1 import java.util.ArrayList;
   2 import java.util.Date;
   3 import java.util.List;
   4 import java.util.Stack;
   5
   6 /**
   7  * @项目名称: sunson_pams
   8  * @类名称: FormulaUtils
   9  * @类描述: 非原创(慎用)
  10  * @创建人: 唐泽齐
  11  * @创建时间: 2017年12月15日 上午9:47:23
  12  * @修改人: 唐泽齐
  13  * @修改时间: 2017年12月15日 上午9:47:23
  14  * @修改备注:
  15  * @version: 1.0
  16  */
  17 public class FormulaUtils {
  18
  19     /**
  20      * 表达式解析
  21      */
  22     public static ExpressionEvaluator ExpressionEvaluator;
  23
  24     public FormulaUtils() {
  25         ExpressionEvaluator = new ExpressionEvaluator();
  26     };
  27
  28     /**
  29      * 表达式各个字符节点的类型枚举类
  30      *
  31      * @项目名称: sunson_pams
  32      * @类名称: ExpressionNodeType
  33      * @类描述:
  34      * @创建人: 唐泽齐
  35      * @创建时间: 2017年12月15日 上午9:49:48
  36      * @修改人: 唐泽齐
  37      * @修改时间: 2017年12月15日 上午9:49:48
  38      * @修改备注:
  39      * @version: 1.0
  40      */
  41     public enum ExpressionNodeType {
  42
  43         Unknown, Plus, // +
  44         Subtract, /// -
  45         MultiPly, // *
  46         Divide, // /
  47         LParentheses, // (
  48         RParentheses, /// )
  49         Mod, // % (求模,取余)
  50         Power, // ^ (次幂)
  51         BitwiseAnd, /// & (按位与)
  52         BitwiseOr, /// | (按位或)
  53         And, // && (逻辑与)
  54         Or, /// || (逻辑或)
  55         Not, /// ! (逻辑非)
  56         Equal, /// == (相等)
  57         Unequal, /// != 或 <> (不等于)
  58         GT, /// > (大于)
  59         LT, /// < (小于)
  60         GTOrEqual, /// >= (大于等于)
  61         LTOrEqual, /// <= (小于等于)
  62         LShift, /// << (左移位)
  63         RShift, /// >> (右移位)
  64         Numeric, /// 数值,
  65         String, Date, Like, // 包含
  66         NotLike, // 不包含
  67         StartWith, // 已什么开始
  68         EndWith// 已什么结尾
  69
  70     }
  71
  72     /**
  73      * 存储表达式运算符或操作数的各个节点的类
  74      *
  75      * @项目名称: sunson_pams
  76      * @类名称: ExpressionNode
  77      * @类描述:
  78      * @创建人: 唐泽齐
  79      * @创建时间: 2017年12月15日 上午9:50:50
  80      * @修改人: 唐泽齐
  81      * @修改时间: 2017年12月15日 上午9:50:50
  82      * @修改备注:
  83      * @version: 1.0
  84      */
  85     public static class ExpressionNode {
  86
  87         private String value;
  88
  89         private ExpressionNodeType type;
  90
  91         private int pri;
  92
  93         private ExpressionNode unitaryNode;
  94
  95         private Object numeric;
  96
  97         /**
  98          *
  99          * @param value
 100          *            操作数或运算符
 101          */
 102         public ExpressionNode(String value) {
 103             this.value = value;
 104             this.type = parseNodeType(value);
 105             this.pri = getNodeTypePRI(this.type);
 106             this.numeric = null;
 107         }
 108
 109         public Object getNumeric() {
 110             if (this.numeric == null) {
 111
 112                 if ((this.type == ExpressionNodeType.String) || (this.type == ExpressionNodeType.Date)) {
 113                     return this.value;
 114                 }
 115
 116                 if (this.type != ExpressionNodeType.Numeric) {
 117                     return 0;
 118                 }
 119                 Double num = new Double(this.value);
 120                 if (this.unitaryNode != null && this.unitaryNode.type == ExpressionNodeType.Subtract) {
 121                     num = 0 - num;
 122                 }
 123                 this.numeric = num;
 124             }
 125             return numeric;
 126         }
 127
 128         public void setNumeric(Object numeric) {
 129             this.numeric = numeric;
 130             this.value = this.numeric.toString();
 131         }
 132
 133         /**
 134          * 设置或返回与当前节点相关联的一元操作符节点
 135          *
 136          * @param unitaryNode
 137          */
 138         public void setUnitaryNode(ExpressionNode unitaryNode) {
 139             this.unitaryNode = unitaryNode;
 140         }
 141
 142         /**
 143          * 解析节点类型
 144          *
 145          * @param value
 146          * @return
 147          */
 148         private ExpressionNodeType parseNodeType(String value) {
 149             if (StringUtils.isEmpty(value)) {
 150                 return ExpressionNodeType.Unknown;
 151             }
 152             switch (value) {
 153             case "+":
 154                 return ExpressionNodeType.Plus;
 155             case "-":
 156                 return ExpressionNodeType.Subtract;
 157             case "*":
 158                 return ExpressionNodeType.MultiPly;
 159             case "/":
 160                 return ExpressionNodeType.Divide;
 161             case "%":
 162                 return ExpressionNodeType.Mod;
 163             case "^":
 164                 return ExpressionNodeType.Power;
 165             case "(":
 166                 return ExpressionNodeType.LParentheses;
 167             case ")":
 168                 return ExpressionNodeType.RParentheses;
 169             case "&":
 170                 return ExpressionNodeType.BitwiseAnd;
 171             case "|":
 172                 return ExpressionNodeType.BitwiseOr;
 173             case "&&":
 174             case "<并且>":
 175             case "并且":
 176                 return ExpressionNodeType.And;
 177             case "||":
 178             case "<或者>":
 179             case "或者":
 180                 return ExpressionNodeType.Or;
 181             case "!":
 182                 return ExpressionNodeType.Not;
 183             case "==":
 184             case "=":
 185                 return ExpressionNodeType.Equal;
 186             case "!=":
 187             case "<>":
 188             case "≠":
 189                 return ExpressionNodeType.Unequal;
 190             case ">":
 191                 return ExpressionNodeType.GT;
 192             case "<":
 193                 return ExpressionNodeType.LT;
 194             case ">=":
 195             case "≥":
 196                 return ExpressionNodeType.GTOrEqual;
 197             case "<=":
 198             case "≤":
 199                 return ExpressionNodeType.LTOrEqual;
 200             case "<<":
 201                 return ExpressionNodeType.LShift;
 202             case ">>":
 203                 return ExpressionNodeType.RShift;
 204             case "@":
 205             case "<包含>":
 206             case "包含":
 207                 return ExpressionNodeType.Like;
 208             case "[email protected]":
 209             case "<不包含>":
 210             case "不包含":
 211                 return ExpressionNodeType.NotLike;
 212             case "!!$":
 213                 return ExpressionNodeType.StartWith;
 214             case "[email protected]":
 215                 return ExpressionNodeType.EndWith;
 216
 217             }
 218             if (isNumerics(value)) {
 219                 return ExpressionNodeType.Numeric;
 220             }
 221             if (isDatetime(value)) {
 222                 return ExpressionNodeType.Date;
 223             }
 224             if (value.contains("\"")) {
 225                 return ExpressionNodeType.String;
 226             }
 227             return ExpressionNodeType.Unknown;
 228         }
 229
 230         /**
 231          * 获取各节点类型的优先级
 232          *
 233          * @param nodeType
 234          * @return
 235          */
 236         private int getNodeTypePRI(ExpressionNodeType nodeType) {
 237             switch (nodeType) {
 238             case LParentheses:
 239             case RParentheses:
 240                 return 9;
 241             // 逻辑非是一元操作符,所以其优先级较高
 242             case Not:
 243                 return 8;
 244             case Mod:
 245                 return 7;
 246             case MultiPly:
 247             case Divide:
 248             case Power:
 249                 return 6;
 250             case Plus:
 251             case Subtract:
 252                 return 5;
 253             case LShift:
 254             case RShift:
 255                 return 4;
 256             case BitwiseAnd:
 257             case BitwiseOr:
 258                 return 3;
 259             case Equal:
 260             case Unequal:
 261             case GT:
 262             case LT:
 263             case GTOrEqual:
 264             case LTOrEqual:
 265             case Like:
 266             case NotLike:
 267             case StartWith:
 268             case EndWith:
 269                 return 2;
 270             case And:
 271             case Or:
 272                 return 1;
 273             default:
 274                 return 0;
 275             }
 276
 277         }
 278
 279         /**
 280          * 判断是否为数值
 281          *
 282          * @param op
 283          * @return
 284          */
 285         public boolean isNumerics(String op) {
 286             return op.matches("^[\\+\\-]?(0|[1-9]\\d*|[1-9]\\d*\\.\\d+|0\\.\\d+)");
 287         }
 288
 289         /**
 290          * 判断是否为日期
 291          *
 292          * @param op
 293          * @return
 294          */
 295         public static boolean isDatetime(String op) {
 296             op = op.replace("\"", "").trim();
 297             return op.matches("\\d{4}\\-\\d{2}\\-\\d{2}(\\s\\d{2}\\:\\d{2}\\:\\d{2})?");
 298         }
 299
 300         /**
 301          * 判断某个字符后是否需要更多的操作符
 302          *
 303          * @param c
 304          * @return
 305          */
 306         public boolean needMoreOperator(char c) {
 307             switch (c) {
 308             case ‘&‘:
 309             case ‘|‘:
 310             case ‘=‘:
 311             case ‘!‘:
 312             case ‘>‘:
 313             case ‘<‘:
 314             case ‘.‘: // 小数点
 315                 return true;
 316             }
 317             // //数字则需要更多
 318             return Character.isDigit(c);
 319         }
 320
 321         /**
 322          * 判断两个字符是否是同一类
 323          *
 324          * @param c1
 325          * @param c2
 326          * @return
 327          */
 328         public boolean IsCongener(char c1, char c2) {
 329             if ((c1 == ‘(‘) || (c2 == ‘(‘)) {
 330                 return false;
 331             }
 332             if ((c1 == ‘)‘) || (c2 == ‘)‘)) {
 333                 return false;
 334             }
 335             if ((c1 == ‘"‘) || (c2 == ‘"‘)) {
 336                 return false;
 337             }
 338             if (Character.isDigit(c1) || (c1 == ‘.‘)) {
 339                 // c1为数字,则c2也为数字
 340                 return (Character.isDigit(c2) || (c2 == ‘.‘));
 341             }
 342             return (!Character.isDigit(c2) && (c2 != ‘.‘));
 343         }
 344
 345         /**
 346          * 判断某个字符是否是空白字符
 347          *
 348          * @param c
 349          * @return
 350          */
 351         public boolean IsWhileSpace(char c) {
 352             return c == ‘ ‘ || c == ‘\t‘;
 353         }
 354
 355         /**
 356          * 判断是否是一元操作符节点
 357          *
 358          * @param nodeType
 359          * @return
 360          */
 361         public static boolean IsUnitaryNode(ExpressionNodeType nodeType) {
 362             return (nodeType == ExpressionNodeType.Plus || nodeType == ExpressionNodeType.Subtract);
 363         }
 364
 365         public String getValue() {
 366             return value;
 367         }
 368
 369         public void setValue(String value) {
 370             this.value = value;
 371         }
 372
 373         public ExpressionNodeType getType() {
 374             return type;
 375         }
 376
 377         public void setType(ExpressionNodeType type) {
 378             this.type = type;
 379         }
 380
 381         public int getPri() {
 382             return pri;
 383         }
 384
 385         public void setPri(int pri) {
 386             this.pri = pri;
 387         }
 388
 389         public ExpressionNode getUnitaryNode() {
 390             return unitaryNode;
 391         }
 392     }
 393
 394     /**
 395      * 表达式异常类
 396      *
 397      * @项目名称: sunson_pams
 398      * @类名称: ExpressionException
 399      * @类描述:
 400      * @创建人: 唐泽齐
 401      * @创建时间: 2017年12月15日 上午9:52:13
 402      * @修改人: 唐泽齐
 403      * @修改时间: 2017年12月15日 上午9:52:13
 404      * @修改备注:
 405      * @version: 1.0
 406      */
 407     public static class ExpressionException extends RuntimeException {
 408
 409         /**
 410          *
 411          */
 412         private static final long serialVersionUID = 3136681292988750961L;
 413
 414         public ExpressionException() {
 415             super();
 416         }
 417
 418         public ExpressionException(String msg) {
 419             super(msg);
 420         }
 421
 422         public ExpressionException(String msg, Throwable cause) {
 423             super(msg, cause);
 424         }
 425
 426         public ExpressionException(Throwable cause) {
 427             super(cause);
 428         }
 429     }
 430
 431     /**
 432      * 负责读取表达式生成ExpressionNode对象的类
 433      *
 434      * @项目名称: sunson_pams
 435      * @类名称: ExpressionParser
 436      * @类描述:
 437      * @创建人: 唐泽齐
 438      * @创建时间: 2017年12月15日 上午9:52:59
 439      * @修改人: 唐泽齐
 440      * @修改时间: 2017年12月15日 上午9:52:59
 441      * @修改备注:
 442      * @version: 1.0
 443      */
 444     public static class ExpressionParser {
 445
 446         // 当前分析的表达式
 447         private String expression;
 448
 449         // 当前读取的位置
 450         private int position;
 451
 452         public String getExpression() {
 453             return expression;
 454         }
 455
 456         public void setExpression(String expression) {
 457             this.expression = expression;
 458         }
 459
 460         public int getPosition() {
 461             return position;
 462         }
 463
 464         public void setPosition(int position) {
 465             this.position = position;
 466         }
 467
 468         public ExpressionParser(String expression) {
 469             this.expression = expression;
 470             this.position = 0;
 471         }
 472
 473         /**
 474          * 读取下一个表达式节点,如果读取失败则返回null
 475          *
 476          * @return
 477          */
 478         public ExpressionNode readNode() {
 479             ExpressionNode s = new ExpressionNode(null);
 480             // 空格的位置
 481             int whileSpacePos = -1;
 482             boolean flag = false;
 483             StringBuffer buffer = new StringBuffer(10);
 484             while (this.position < this.expression.length()) {
 485                 char c = this.expression.charAt(this.position);
 486                 if (c == ‘"‘) {
 487                     flag = !flag;
 488                     if (!flag) {
 489                         this.position++;
 490                         buffer.append(c);
 491                         break;
 492                     }
 493                     if (buffer.length() != 0) {
 494                         break;
 495                     }
 496                 }
 497                 if (flag) {
 498                     this.position++;
 499                     buffer.append(c);
 500                 } else {
 501                     if (s.IsWhileSpace(c)) {
 502                         if ((whileSpacePos >= 0) && ((this.position - whileSpacePos) > 1)) {
 503                             throw new ExpressionException(
 504                                     String.format("表达式\"%s\"在位置(%s)上的字符非法!", this.getExpression(), this.getPosition()));
 505                         }
 506                         if (buffer.length() == 0) {
 507                             whileSpacePos = -1;
 508                         } else {
 509                             whileSpacePos = this.position;
 510                         }
 511                         this.position++;
 512                         continue;
 513                     }
 514                     if ((buffer.length() == 0) || s.IsCongener(c, buffer.charAt(buffer.length() - 1))) {
 515                         this.position++;
 516                         buffer.append(c);
 517                     } else {
 518                         break;
 519                     }
 520                     if (!s.needMoreOperator(c)) {
 521                         break;
 522                     }
 523                 }
 524             }
 525             if (buffer.length() == 0) {
 526                 return null;
 527             }
 528             ExpressionNode node = new ExpressionNode(buffer.toString());
 529             if (node.getType() == ExpressionNodeType.Unknown) {
 530                 throw new ExpressionException(String.format("表达式\"%s\"在位置%s上的字符\"%s\"非法!", this.getExpression(),
 531                         this.getPosition() - node.getValue().length(), node.getValue()));
 532             }
 533             return node;
 534         }
 535
 536     }
 537
 538     /**
 539      * 解析公式并返回结果的类
 540      *
 541      * @项目名称: sunson_pams
 542      * @类名称: ExpressionEvaluator
 543      * @类描述:
 544      * @创建人: 唐泽齐
 545      * @创建时间: 2017年12月15日 上午9:56:08
 546      * @修改人: 唐泽齐
 547      * @修改时间: 2017年12月15日 上午9:56:08
 548      * @修改备注:
 549      * @version: 1.0
 550      */
 551     public static class ExpressionEvaluator {
 552
 553         private ExpressionEvaluator() {
 554
 555         }
 556
 557         /**
 558          * 将算术表达式转换为逆波兰表达式
 559          *
 560          * @param expression
 561          *            要计算的表达式,如"1+2+3+4"
 562          * @return
 563          */
 564         private static  List<ExpressionNode> parseExpression(String expression) {
 565             if (StringUtils.isEmpty(expression)) {
 566                 return new ArrayList<ExpressionNode>();
 567             }
 568
 569             List<ExpressionNode> listOperator = new ArrayList<ExpressionNode>(10);
 570             Stack<ExpressionNode> stackOperator = new Stack<ExpressionNode>();
 571
 572             ExpressionParser expParser = new ExpressionParser(expression);
 573             ExpressionNode beforeExpNode = null; // 前一个节点
 574             ExpressionNode unitaryNode = null; // 一元操作符
 575             ExpressionNode expNode;
 576             // 是否需要操作数
 577             boolean requireOperand = false;
 578
 579             while ((expNode = expParser.readNode()) != null) {
 580                 if ((expNode.getType() == ExpressionNodeType.Numeric)
 581                         || (expNode.getType() == ExpressionNodeType.String)
 582                         || (expNode.getType() == ExpressionNodeType.Date)) {
 583                     // 操作数, 直接加入后缀表达式中
 584                     if (unitaryNode != null) {
 585                         // 设置一元操作符节点
 586                         expNode.setUnitaryNode(unitaryNode);
 587                         unitaryNode = null;
 588                     }
 589
 590                     listOperator.add(expNode);
 591                     requireOperand = false;
 592                     continue;
 593                 } else if (expNode.getType() == ExpressionNodeType.LParentheses) {
 594                     // 左括号, 直接加入操作符栈
 595                     stackOperator.push(expNode);
 596                     continue;
 597                 } else if (expNode.getType() == ExpressionNodeType.RParentheses) {
 598                     // 右括号则在操作符栈中反向搜索,直到遇到匹配的左括号为止,将中间的操作符依次加到后缀表达式中。
 599                     ExpressionNode lpNode = null;
 600                     while (stackOperator.size() > 0) {
 601                         lpNode = stackOperator.pop();
 602                         if (lpNode.getType() == ExpressionNodeType.LParentheses)
 603                             break;
 604                         listOperator.add(lpNode);
 605                     }
 606                     if (lpNode == null || lpNode.getType() != ExpressionNodeType.LParentheses) {
 607                         throw new ExpressionException(String.format("在表达式\"%s\"中没有与在位置(%s)上\")\"匹配的\"(%s)\"字符!",expParser.getExpression(), expParser.getPosition()));
 608                     }
 609                 } else {
 610                     if (stackOperator.size() == 0) {
 611                         // 第一个节点则判断此节点是否是一元操作符"+,-,!,("中的一个,否则其它都非法
 612                         if (listOperator.size() == 0 && !(expNode.getType() == ExpressionNodeType.LParentheses
 613                                 || expNode.getType() == ExpressionNodeType.Not)) {
 614                             // 后缀表达式没有任何数据则判断是否是一元操作数
 615                             if (ExpressionNode.IsUnitaryNode(expNode.getType())) {
 616                                 unitaryNode = expNode;
 617                             } else {
 618                                 // 丢失操作数
 619                                 throw new ExpressionException(String.format("表达式\"%s\"在位置(%s)上缺少操作数!",
 620                                         expParser.getExpression(), expParser.getPosition()));
 621                             }
 622                         } else {
 623                             // 直接压入操作符栈
 624                             stackOperator.push(expNode);
 625                         }
 626                         requireOperand = true; // 下一个节点需要操作数
 627                         continue;
 628                     } else {
 629                         if (requireOperand) {
 630                             // 如果需要操作数则判断当前的是否是"+","-"号(一元操作符),如果是则继续
 631                             if (ExpressionNode.IsUnitaryNode(expNode.getType()) && unitaryNode == null) {
 632                                 unitaryNode = expNode;
 633                             } else {
 634                                 // 丢失操作数
 635                                 throw new ExpressionException(String.format("表达式\"%s\"在位置({1})上缺少操作数!",
 636                                         expParser.getExpression(), expParser.getPosition()));
 637                             }
 638                         } else {
 639                             // 对前面的所有操作符进行优先级比较
 640                             do {
 641                                 // 取得上一次的操作符
 642                                 beforeExpNode = stackOperator.peek();
 643
 644                                 // 如果前一个操作符优先级较高,则将前一个操作符加入后缀表达式中
 645                                 if (beforeExpNode.getType() != ExpressionNodeType.LParentheses
 646                                         && (beforeExpNode.getPri() - expNode.getPri()) >= 0) {
 647                                     listOperator.add(stackOperator.pop());
 648                                 } else {
 649                                     break;
 650                                 }
 651
 652                             } while (stackOperator.size() > 0);
 653
 654                             // 将操作符压入操作符栈
 655                             stackOperator.push(expNode);
 656                             requireOperand = true;
 657                         }
 658                     }
 659                 }
 660             }
 661
 662             if (requireOperand) {
 663                 // 丢失操作数
 664                 throw new ExpressionException(
 665                         String.format("表达式\"%s\"在位置({1})上缺少操作数!", expParser.getExpression(), expParser.getPosition()));
 666             }
 667             // 清空堆栈
 668             while (stackOperator.size() > 0) {
 669                 // 取得操作符
 670                 beforeExpNode = stackOperator.pop();
 671                 if (beforeExpNode.getType() == ExpressionNodeType.LParentheses) {
 672                     throw new ExpressionException(String.format("表达式\"%s\"中括号不匹配,丢失右括号!", expParser.getExpression(),
 673                             expParser.getPosition()));
 674                 }
 675                 listOperator.add(beforeExpNode);
 676             }
 677
 678             return listOperator;
 679         }
 680
 681         /**
 682          * 对逆波兰表达式进行计算
 683          *
 684          * @param nodes
 685          * @return
 686          */
 687         @SuppressWarnings({ "rawtypes", "unchecked", "incomplete-switch" })
 688         private static  Object CalcExpression(List<ExpressionNode> nodes) {
 689             if (nodes == null || nodes.size() == 0)
 690                 return null;
 691
 692             if (nodes.size() > 1) {
 693                 int index = 0;
 694                 // 储存数据
 695                 ArrayList values = new ArrayList();
 696                 while (index < nodes.size()) {
 697                     ExpressionNode node = nodes.get(index);
 698
 699                     switch (node.getType()) {
 700                     // 如果是数字,则将值存入 values 中
 701                     case Numeric:
 702                     case String:
 703                     case Date:
 704                         values.add(node.getNumeric());
 705                         index++;
 706                         break;
 707                     default:
 708                         // 二元表达式,需要二个参数, 如果是Not的话,则只要一个参数
 709                         int paramCount = 2;
 710                         if (node.getType() == ExpressionNodeType.Not)
 711                             paramCount = 1;
 712                         // 计算操作数的值
 713                         if (values.size() < paramCount) {
 714                             throw new ExpressionException("缺少操作数");
 715                         }
 716                         // 传入参数
 717                         Object[] data = new Object[paramCount];
 718                         for (int i = 0; i < paramCount; i++) {
 719                             data[i] = values.get(index - paramCount + i);
 720                         }
 721                         // 将计算结果再存入当前节点
 722                         node.setNumeric(calculate(node.getType(), data));
 723                         node.setType(ExpressionNodeType.Numeric);
 724                         // 将操作数节点删除
 725                         for (int i = 0; i < paramCount; i++) {
 726                             nodes.remove(index - i - 1);
 727                             values.remove(index - i - 1);
 728                         }
 729                         index -= paramCount;
 730                         break;
 731                     }
 732
 733                 }
 734             }
 735
 736             if (nodes.size() != 1) {
 737                 throw new ExpressionException("缺少操作符或操作数");
 738             }
 739             switch (nodes.get(0).getType()) {
 740             case Numeric:
 741                 return nodes.get(0).getNumeric();
 742
 743             case String:
 744             case Date:
 745                 return nodes.get(0).getNumeric().toString().replace("\"", "");
 746             }
 747             throw new ExpressionException("缺少操作数");
 748         }
 749
 750         /**
 751          * 计算节点的值
 752          *
 753          * @param nodeType
 754          *            节点的类型
 755          * @param data
 756          *            要计算的值,有可能是两位或一位数
 757          * @return
 758          */
 759         @SuppressWarnings("incomplete-switch")
 760         private static  Object calculate(ExpressionNodeType nodeType, Object[] data) {
 761             double d1, d2;
 762             boolean b1, b2;
 763             Date time1, time2;
 764             Object obj1 = data[0];
 765             Object obj2 = data[1];
 766             String str1 = obj1.toString();
 767             String str2 = obj2.toString();
 768
 769             boolean dateflag = ExpressionNode.isDatetime(str1) || ExpressionNode.isDatetime(str2);
 770             boolean strflag = str1.contains("\"") || str2.contains("\"");
 771             str1 = str1.replace("\"", "");
 772             str2 = str2.replace("\"", "");
 773
 774             switch (nodeType) {
 775             case Plus:
 776                 if (!strflag) {
 777                     d1 = ConvertToDecimal(obj1);
 778                     d2 = ConvertToDecimal(obj2);
 779                     return (d1 + d2);
 780                 }
 781                 return new StringBuffer(str1 + str2).toString();
 782             case Subtract:
 783                 d1 = ConvertToDecimal(obj1);
 784                 d2 = ConvertToDecimal(obj2);
 785                 return d1 - d2;
 786             case MultiPly:
 787                 d1 = ConvertToDecimal(obj1);
 788                 d2 = ConvertToDecimal(obj2);
 789                 return d1 * d2;
 790             case Divide:
 791                 d1 = ConvertToDecimal(obj1);
 792                 d2 = ConvertToDecimal(obj2);
 793                 if (d2 == 0)
 794                     throw new RuntimeException();
 795                 return d1 / d2;
 796             case Power:
 797                 d1 = ConvertToDecimal(obj1);
 798                 d2 = ConvertToDecimal(obj2);
 799                 return Math.pow((double) d1, (double) d2);
 800             case Mod:
 801                 d1 = ConvertToDecimal(obj1);
 802                 d2 = ConvertToDecimal(obj2);
 803                 if (d2 == 0)
 804                     throw new RuntimeException();
 805                 return d1 % d2;
 806             case BitwiseAnd:
 807                 d1 = ConvertToDecimal(obj1);
 808                 d2 = ConvertToDecimal(obj2);
 809                 return (int) d1 & (int) d2;
 810             case BitwiseOr:
 811                 d1 = ConvertToDecimal(obj1);
 812                 d2 = ConvertToDecimal(obj2);
 813                 return (int) d1 | (int) d2;
 814             case And:
 815                 b1 = ConvertToBool(obj1);
 816                 b2 = ConvertToBool(obj2);
 817                 return b1 && b2;
 818             case Or:
 819                 b1 = ConvertToBool(obj1);
 820                 b2 = ConvertToBool(obj2);
 821                 return b1 || b2;
 822             case Not:
 823                 b1 = ConvertToBool(obj1);
 824                 return !b1;
 825             case Equal:
 826                 if (!dateflag) {
 827                     if (strflag) {
 828                         return str1.equals(str2);
 829                     }
 830                     d1 = ConvertToDecimal(obj1);
 831                     d2 = ConvertToDecimal(obj2);
 832                     return (d1 == d2);
 833                 }
 834                 time1 = DateUtils.parseDate(str1);
 835                 time2 = DateUtils.parseDate(str2);
 836
 837                 return (time1.getTime() == time2.getTime());
 838             case Unequal:
 839                 if (!dateflag) {
 840                     if (strflag) {
 841                         return (!str1.equals(str2));
 842                     }
 843                     d1 = ConvertToDecimal(obj1);
 844                     d2 = ConvertToDecimal(obj2);
 845                     return (d1 != d2);
 846                 }
 847                 time1 = DateUtils.parseDate(str1);
 848                 time2 = DateUtils.parseDate(str2);
 849
 850                 return (time1.getTime() != time2.getTime());
 851             case GT:
 852
 853                 if (!dateflag) {
 854                     d1 = ConvertToDecimal(obj1);
 855                     d2 = ConvertToDecimal(obj2);
 856                     return (d1 > d2);
 857                 }
 858                 time1 = DateUtils.parseDate(str1);
 859                 time2 = DateUtils.parseDate(str2);
 860                 return (time1.getTime() > time2.getTime());
 861
 862             case LT:
 863
 864                 if (!dateflag) {
 865                     d1 = ConvertToDecimal(obj1);
 866                     d2 = ConvertToDecimal(obj2);
 867                     return (d1 < d2);
 868                 }
 869                 time1 = DateUtils.parseDate(str1);
 870                 time2 = DateUtils.parseDate(str2);
 871                 return (time1.getTime() < time2.getTime());
 872
 873             case GTOrEqual:
 874
 875                 if (!dateflag) {
 876                     d1 = ConvertToDecimal(obj1);
 877                     d2 = ConvertToDecimal(obj2);
 878                     return (d1 >= d2);
 879                 }
 880                 time1 = DateUtils.parseDate(str1);
 881                 time2 = DateUtils.parseDate(str2);
 882                 return (time1.getTime() >= time2.getTime());
 883
 884             case LTOrEqual:
 885                 if (!dateflag) {
 886                     d1 = ConvertToDecimal(obj1);
 887                     d2 = ConvertToDecimal(obj2);
 888                     return (d1 <= d2);
 889                 }
 890                 time1 = DateUtils.parseDate(str1);
 891                 time2 = DateUtils.parseDate(str2);
 892                 return (time1.getTime() <= time2.getTime());
 893             case LShift:
 894                 d1 = ConvertToDecimal(obj1);
 895                 d2 = ConvertToDecimal(obj2);
 896                 return (long) d1 << (int) d2;
 897
 898             case RShift:
 899                 d1 = ConvertToDecimal(obj1);
 900                 d2 = ConvertToDecimal(obj2);
 901                 return (long) d1 >> (int) d2;
 902             case Like:
 903                 if (!strflag) {
 904                     return false;
 905                 }
 906                 return str1.contains(str2);
 907             case NotLike:
 908                 if (!strflag) {
 909                     return false;
 910                 }
 911                 return !str1.contains(str2);
 912             case StartWith:
 913                 if (!strflag) {
 914                     return false;
 915                 }
 916                 return str1.startsWith(str2);
 917             case EndWith:
 918                 if (!strflag) {
 919                     return false;
 920                 }
 921                 return str1.endsWith(str2);
 922             }
 923
 924             return 0;
 925         }
 926
 927         /**
 928          * 某个值转换为bool值
 929          *
 930          * @param value
 931          * @return
 932          */
 933         private static  Boolean ConvertToBool(Object value) {
 934             if (value instanceof Boolean) {
 935                 return (Boolean) value;
 936             } else {
 937                 return value != null;
 938             }
 939         }
 940
 941         /**
 942          * 将某个值转换为decimal值
 943          *
 944          * @param value
 945          * @return
 946          */
 947         private static  Double ConvertToDecimal(Object value) {
 948             if (value instanceof Boolean) {
 949                 return ((Boolean) value ? 1d : 0d);
 950             } else {
 951                 return Double.parseDouble(value.toString());
 952             }
 953         }
 954
 955         /**
 956          *
 957          * @param expression
 958          *            要计算的表达式,如"1+2+3+4"
 959          * @return 返回计算结果,如果带有逻辑运算符则返回true/false,否则返回数值
 960          */
 961         public Object eval(String expression) {
 962             return CalcExpression(parseExpression(expression));
 963         }
 964
 965         public  Object evalThreeOperand(String expression) {
 966             int index = expression.indexOf("?");
 967             if (index > -1) {
 968                 String str = expression.substring(0, index);
 969                 String str2 = expression.substring(index + 1);
 970                 index = str2.indexOf(":");
 971
 972                 if (Boolean.parseBoolean((CalcExpression(parseExpression(str))).toString())) {
 973                     return eval(str2.substring(0, index));
 974                 }
 975                 return eval(str2.substring(index + 1));
 976             }
 977             return CalcExpression(parseExpression(expression));
 978         }
 979
 980     }
 981
 982 //    /**
 983 //     * 测试
 984 //     *
 985 //     * @方法名:main
 986 //     * @参数 @param args
 987 //     * @返回类型 void
 988 //     */
 989 //    public static void main(String[] args) {
 990 //        String s1 = "1+2+3+4";
 991 //        System.out.println(ExpressionEvaluator.eval(s1));
 992 //
 993 //        String s2 = "(20 - 6) < 3";
 994 //        System.out.println(ExpressionEvaluator.eval(s2));
 995 //
 996 //        String s3 = "(3 + 1) == 4 && 5 > (2 + 3)";
 997 //        System.out.println(ExpressionEvaluator.eval(s3));
 998 //
 999 //        String s4 = "\"hello\" == \"hello\" && 3 != 4";
1000 //        System.out.println(ExpressionEvaluator.eval(s4));
1001 //
1002 //        String s5 = "\"helloworld\" @ \"hello\" &&  \"helloworld\" [email protected] \"word\" ";
1003 //        System.out.println(ExpressionEvaluator.eval(s5));
1004 //
1005 //    }
1006
1007 }
时间: 2024-10-24 16:26:55

Java 表达式解析(非原创)的相关文章

使用Jsoup实现java爬虫(非原创)

1,查看页面源代码,使用css或者JQuery选择器方式或元素节点选择 例如: 或者写成:Elements elements1 = Jsoup.connect("http://jb.999ask.com/jibing/ks/neike").get().select("ul.jbList li a"); 文档的对象模型: 文档由多个Elements和TextNodes组成 (以及其它辅助nodes:详细可查看:nodes package tree). 其继承结构如下:

java正则表达式验证非原创

1 /** 2 * 3 */ 4 package com.ssh.util; 5 6 import java.util.regex.Matcher; 7 import java.util.regex.Pattern; 8 9 /** 10 * @author leorain 11 * 12 */ 13 public class ValidateUtil { 14 /** 15 * 手机号验证 16 * 17 * @param str 18 * @return 验证通过返回true 19 */ 2

Java项目打包&lt;非原创&gt;

发布打war包dos命令:jar cvf name.war . war包是带jsp页面,jar包不带jsp页面的. 在JDK的bin目录下提供了打包程序jar.exe.如果要展开helloapp.war文件,命令为: jar xvf helloapp.war 假定有一个Web应用:C:\myHomemyHome/WEB-INF/……myHome/files/……myHome/image/……myHome/src/……myHome/index.jsp在命令行窗口下执行如下命令:C:\>cd myH

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

之前简单的介绍了这个基于Java表达式解析工具,现在把代码分享给大家,希望帮助到有需要的人们,这个分享代码中依赖了一些其他的类,这些类大家可以根据自己的情况进行导入,无非就是写字符串处理工具类,日期处理的工具类什么的. 这个Java的表达式解析的工具只用了5个类,而且写得也很简单明了,相信有一些编程经验的可以看懂这些处理的逻辑代码. 1.第一个类:ExpressionNodeType(表达式各个字符节点的类型枚举类) public enum ExpressionNodeType { Unknow

一个简单的Java模板工具类(二)—简单表达式解析实现

以前写过一个, 用正则比较不高效, 所以用表达式解析方式又实现了一个, 练手. 以前的: http://my.oschina.net/haogrgr/blog/222349 现在的: import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; /**  * 非常非常简单的模板实现  *   * @author desheng.tu  * @date 2015年

Java中使用Groovy实现自定义表达式解析

Groovy作为一种JVM-Based语言,目前普及程度正在提高.本文演示一下在Java类中,通过继承GDK的groovy.lang.Script类如何支持自定义表达式解析功能. 输入: 表示一行数据的某个map结构.在实际应用中,产生这种结构的最常见场景可能是通过JDBC访问数据库.通过调用WebService服务得到的某行结果集等. 目标设定: 假设我们希望对输入数据进行某个运算.此处示例中,我们模拟oracle中最常用的nvl函数. 处理过程:  首先,通过继承groovy.lang.Sc

Java Interface 是常量存放的最佳地点吗?(转帖学习,非原创)

Java Interface 是常量存放的最佳地点吗?(转帖学习,非原创) 由于java interface中声明的字段在编译时会自动加上static final的修饰符,即声明为常量.因而interface通常是存放常量的最佳地点.然而在java的实际应用时却会产生一些问题. 问题的起因有两个,第一,是我们所使用的常量并不是一成不变的,而是相对于变量不能赋值改变.例如我们在一个工程初期定义常量∏=3.14,而由于计算精度的提高我们可能会重新定义∏=3.14159,此时整个项目对此常量的引用都应

Java基础:非阻塞式IO

转载请注明出处:jiq?钦's technical Blog 引言 JDK1.4中引入了NIO,即New IO,目的在于提高IO速度.特别注意JavaNIO不完全是非阻塞式IO(No-Blocking IO),因为其中部分通道(如FileChannel)只能运行在阻塞模式下,而其他的通道可以在阻塞式和非阻塞式之间进行选择. 尽管这样,我们还是习惯将Java NIO看作是非阻塞式IO,而前面介绍的面向流(字节/字符)的IO类库则是非阻塞的,详细来看,两者区别如下: IO NIO 面向流(Strea

Java Nio 十一、Java NIO:非堵塞服务器

最后更新时间:2015-10-23 甚至如果你理解JAVA NIO的非堵塞特点的工作方式(Selector,Channel,Buffer等等),而设计一个非堵塞服务器也是难得.相对堵塞IO来说,非堵塞IO包含几个挑战.这个非堵塞服务器教程将会讨论非堵塞服务器的主要挑战,并且对于他们描述一些潜在的解决方案. 关于设计一个非堵塞服务器发现一些好的信息是难得.因此在这个教程中提供的解决方案是基于我自己的工作经验和想法.如果你有一些另类的或者更好的想法,我将会很高兴的听到关于这些想法.你可以写一个评论在