Explorar o código

线元线元管理、解析器

yangyj %!s(int64=3) %!d(string=hai) anos
pai
achega
3650a70fa6
Modificáronse 100 ficheiros con 7089 adicións e 0 borrados
  1. 123 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/Mileage.java
  2. 25 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/MileagePart.java
  3. 76 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/Mileagexy.java
  4. 1239 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/utils/MileageUtill.java
  5. 459 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/utils/NumberUtil.java
  6. 28 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/MileageVo.java
  7. 4 0
      blade-service/blade-business/pom.xml
  8. 297 0
      blade-service/blade-business/src/main/java/org/springblade/business/controller/MileageController.java
  9. 11 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/MileagePartMapper.java
  10. 32 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/MileagePartMapper.xml
  11. 17 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/MileagexyMapper.java
  12. 49 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/MileagexyMapper.xml
  13. 58 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/MileagePartService.java
  14. 173 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/MileagexyService.java
  15. 179 0
      blade-service/blade-business/src/main/java/org/springblade/business/utils/FunctionMain.java
  16. 5 0
      blade-service/blade-manager/pom.xml
  17. 15 0
      blade-service/blade-manager/src/main/java/com/jfireel/exception/IllegalFormatException.java
  18. 15 0
      blade-service/blade-manager/src/main/java/com/jfireel/exception/UnParsedException.java
  19. 124 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/Expression.java
  20. 14 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/CalculateNode.java
  21. 102 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/MethodNode.java
  22. 9 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/QuestionNode.java
  23. 123 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/BracketNode.java
  24. 52 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/ClassPropertyNode.java
  25. 217 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/CompileObjectMethodNode.java
  26. 44 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/DivisionNode.java
  27. 32 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/DoubleAmpNode.java
  28. 33 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/DoubleBarNode.java
  29. 37 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/EnumNode.java
  30. 33 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/EqualNode.java
  31. 25 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/GtEqNode.java
  32. 26 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/GtNode.java
  33. 48 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/KeywordNode.java
  34. 26 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/LtEqNode.java
  35. 27 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/LtNode.java
  36. 34 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/MinusNode.java
  37. 35 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/MutliNode.java
  38. 33 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/NotEqualNode.java
  39. 46 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/NumberNode.java
  40. 101 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/ObjectPropertyNode.java
  41. 36 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/OperatorNode.java
  42. 38 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/OperatorResultNode.java
  43. 26 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/PercentNode.java
  44. 47 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/PlusNode.java
  45. 57 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/QuestionNodeImpl.java
  46. 146 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/ReflectMethodNode.java
  47. 108 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/StaticObjectMethodNode.java
  48. 36 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/StringNode.java
  49. 38 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/SymBolNode.java
  50. 37 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/TypeNode.java
  51. 36 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/VariableNode.java
  52. 10 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/Invoker.java
  53. 22 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/CommaParser.java
  54. 32 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/ConstantStringParser.java
  55. 35 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/EnumParser.java
  56. 38 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/IdentifierParser.java
  57. 22 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/LeftBracketParser.java
  58. 22 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/LeftParenParser.java
  59. 49 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/MethodParser.java
  60. 40 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/NodeParser.java
  61. 68 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/NumberParser.java
  62. 33 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/OperatorParser.java
  63. 43 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/PropertyParser.java
  64. 42 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/RightBracketParser.java
  65. 59 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/RightParenParser.java
  66. 16 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/SkipIgnoredToken.java
  67. 45 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/TypeParser.java
  68. 20 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/token/DefaultKeyWord.java
  69. 5 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/token/KeyWord.java
  70. 58 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/token/Operator.java
  71. 42 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/token/Symbol.java
  72. 34 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/token/Token.java
  73. 5 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/token/TokenType.java
  74. 77 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/util/CharType.java
  75. 31 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/util/Functional.java
  76. 15 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/util/Functions.java
  77. 177 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/util/OperatorResultUtil.java
  78. 91 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/util/number/DivisionUtil.java
  79. 89 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/util/number/EqUtil.java
  80. 89 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/util/number/GtUtil.java
  81. 89 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/util/number/LtUtil.java
  82. 91 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/util/number/MultiplyUtil.java
  83. 91 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/util/number/PlusUtil.java
  84. 91 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/util/number/RemainderUtil.java
  85. 91 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/util/number/SubtractUtil.java
  86. 9 0
      blade-service/blade-manager/src/main/java/com/jfireel/template/ScanMode.java
  87. 108 0
      blade-service/blade-manager/src/main/java/com/jfireel/template/Template.java
  88. 21 0
      blade-service/blade-manager/src/main/java/com/jfireel/template/execution/Execution.java
  89. 6 0
      blade-service/blade-manager/src/main/java/com/jfireel/template/execution/InvokerOnExecute.java
  90. 8 0
      blade-service/blade-manager/src/main/java/com/jfireel/template/execution/WithBodyExecution.java
  91. 40 0
      blade-service/blade-manager/src/main/java/com/jfireel/template/execution/impl/ElseExecution.java
  92. 52 0
      blade-service/blade-manager/src/main/java/com/jfireel/template/execution/impl/ElseIfExecution.java
  93. 35 0
      blade-service/blade-manager/src/main/java/com/jfireel/template/execution/impl/ExpressionExecution.java
  94. 63 0
      blade-service/blade-manager/src/main/java/com/jfireel/template/execution/impl/ForEachExecution.java
  95. 85 0
      blade-service/blade-manager/src/main/java/com/jfireel/template/execution/impl/IfExecution.java
  96. 29 0
      blade-service/blade-manager/src/main/java/com/jfireel/template/execution/impl/StringExecution.java
  97. 11 0
      blade-service/blade-manager/src/main/java/com/jfireel/template/parser/Invoker.java
  98. 116 0
      blade-service/blade-manager/src/main/java/com/jfireel/template/parser/Parser.java
  99. 58 0
      blade-service/blade-manager/src/main/java/com/jfireel/template/parser/impl/ElseParser.java
  100. 55 0
      blade-service/blade-manager/src/main/java/com/jfireel/template/parser/impl/EndBraceParser.java

+ 123 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/Mileage.java

@@ -0,0 +1,123 @@
+
+package org.springblade.business.entity;
+
+
+import lombok.Data;
+import org.springblade.business.utils.MileageUtill;
+import org.springblade.business.utils.NumberUtil;
+
+import java.io.Serializable;
+
+
+@Data
+public class Mileage implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	private String projId;		// projId
+	private String orgId;		// orgId
+	private String notes;		// notes
+	private String code;		// 名称
+
+	private Double value=0.0;		// 里程
+
+	private Double x=0.0;		// x
+	private Double y=0.0;
+
+	private Double r=0.0;         //半径
+	private Integer orderNum=0;     //顺序
+	private Integer type=0;     //类型 0 起点  1交点  2终点
+	private Double angle=0.0;     //方位角
+	private Double corner=0.0;     //转角
+	private String swing="右转";     //转向
+	private Double ls1=0.0;         //第一缓和线
+	private Double ls2=0.0;         //第二缓和线
+	private Double l=0.0;           //曲线长
+	private Double lc=0.0;          //圆曲线长
+	private Double t1=0.0;          //切线长1
+	private Double t2=0.0;          //切线长2
+	private Double d=0.0;          //切线差
+	private Double p1=0.0;          //
+	private Double q1=0.0;          //
+	private Double p2=0.0;          //
+	private Double q2=0.0;          //
+	private Double b01=0.0;
+	private Double b02=0.0;
+	private Double ljd=0.0;       //上个点到该点的长
+
+	private Double zh=0.0;    //直缓点
+	private Double zhx=0.0;		// x
+	private Double zhy=0.0;
+	private Double hy=0.0;    //缓圆点
+	private Double yh=0.0;//圆缓点
+	private Double hz=0.0;//缓直点
+	private Double hzx=0.0;		// x
+	private Double hzy=0.0;
+	private Double qz=0.0;//曲中点
+	private Double dlq=0.0;//   断链前里程
+	private Double dlh=0.0;//断链后里程
+
+	private Double b=0.0;//偏移  (只用于显示)
+	private Double jj=90.0;//夹角  (只用于显示)
+	private String ids;
+	private String partNo;		// piand
+	private String partId;		// piand
+
+	private String valueup;		// 里程
+	private String xup;		// x
+	private String yup;
+	private String rup;
+	private String ls1up;         //第一缓和线
+	private String ls2up;         //第二缓和线
+	private String dlqup;//   断链前里程
+	private String dlhup;//断链后里程
+
+
+
+	public Mileage() {}
+
+	public Mileage(Double value, Double x, Double y, Integer orderNum, int type) {
+		this.value = value;
+		this.x = x;
+		this.y = y;
+		this.orderNum = orderNum;
+		this.type = type;
+	}
+	public Mileage(String code, Double x, Double y, Double r, int orderNum, Integer type, Double ls1, Double ls2, Double dlq, Double dlh) {
+		this.code = code;
+
+		this.x = x;
+		this.y = y;
+		this.r = r;
+		this.orderNum = orderNum;
+		this.type = type;
+		this.ls1 = ls1;
+		this.ls2 = ls2;
+		this.dlq = dlq;
+		this.dlh = dlh;
+	}
+
+	public String getValueStr() {
+		return MileageUtill.convertToMileage(value);
+	}
+
+	public String getXxStr() {
+		return NumberUtil.forcibleFormat(x,3);
+	}
+
+	public String getYyStr() {
+		return NumberUtil.forcibleFormat(y,3);
+	}
+
+	public String getAngleStr() {
+		return MileageUtill.convertToSexagesimal(angle);
+	}
+
+	public String getCornerStr() {
+		return MileageUtill.convertToSexagesimal(corner);
+	}
+
+	public int compareTo(Mileage o) {
+		return Integer.parseInt(NumberUtil.forcibleFormat(this.value*10-o.getValue()*10,0));
+	}
+}

+ 25 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/MileagePart.java

@@ -0,0 +1,25 @@
+package org.springblade.business.entity;
+
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.core.tenant.mp.TenantEntity;
+
+import java.lang.annotation.Documented;
+
+/**
+ * @author yangyj
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+@TableName("t_om_mileage_part")
+public class MileagePart  extends TenantEntity {
+    private static final long serialVersionUID = 1L;
+    private String name;
+    private String prefix;
+    private String remark;
+    private String contractId;
+    private String projectId;
+    private Integer sort;
+}

+ 76 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/Mileagexy.java

@@ -0,0 +1,76 @@
+/**
+ * Copyright &copy; 2012-2016 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
+ */
+package org.springblade.business.entity;
+
+
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.business.utils.MileageUtill;
+import org.springblade.business.utils.NumberUtil;
+import org.springblade.core.tenant.mp.TenantEntity;
+import javax.validation.constraints.Size;
+
+
+
+/**
+ * @author yangyj
+ */
+@Data
+@TableName("t_om_mileagexy")
+@EqualsAndHashCode(callSuper = true)
+public class Mileagexy   extends TenantEntity {
+	private static final long serialVersionUID = 491147543091757213L;
+	private String projectId;		// projId
+	private String notes;		// notes
+	private String code;		// 编号
+	private Double value;		// 里程
+	private Double x=0.0;		// x
+	private Double y=0.0;		// y
+	private Double r=0.0;		// 半径
+	private Double r2=0.0;		// 半径
+	private String swing="";		// 转向
+	private Double l=0.0;		// 长度
+	private Double valueEnd=0.0;		// 结束里程
+	private Integer orderNum=0;		// 顺序
+	private Integer type=0;		// 类型 0 z,1 y,2 rh,3 ch
+	private Double angle=0.0;		// 方位角
+	private Integer du=0;		// 度
+	private Integer fen=0;		// 分
+	private Double miao=0.0;		// 秒
+	private Double dlq=0.0;		// 断链前里程
+	private Double dlh=0.0;		// 断链后里程
+	private String ids;
+	private String partNo;		// 片段前缀
+	private String partId;		// 片段所属id t_pf_mileage_part
+	private String contractId;
+
+
+	public String getValueStr() {
+		return MileageUtill.convertToMileage(value);
+	}
+
+
+	public String getValueEndStr() {
+		return MileageUtill.convertToMileage(valueEnd);
+	}
+
+	public String getXxStr() {
+		return NumberUtil.forcibleFormat(x,3);
+	}
+
+	public String getYyStr() {
+		return NumberUtil.forcibleFormat(y,3);
+	}
+
+	public String getAngleStr() {
+		return MileageUtill.convertToSexagesimal(angle);
+	}
+
+	public int compareTo(Mileagexy o) {
+		return Integer.parseInt(NumberUtil.forcibleFormat(this.value*10-o.getValue()*10,0));
+	}
+
+}

+ 1239 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/utils/MileageUtill.java

@@ -0,0 +1,1239 @@
+package org.springblade.business.utils;
+
+
+
+
+import org.springblade.business.entity.Mileage;
+import org.springblade.business.entity.Mileagexy;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class MileageUtill {
+    private static final String prefix = "K";
+    private static final int precision = 8;
+    private static final int precision_1 = 3;
+    private static final int spacing_precision = 3;
+    private static final double spacing = 0.001;
+    /**主线*/
+    public static final String MASTER_PART = "NO1";
+
+
+    /******************交点法***********开始
+     /**
+     * 初始化里程信息数据
+     * @param mileages
+     * @return
+     */
+    public static List<Mileage> initMileages(List<Mileage> mileages) {
+        if (mileages == null && mileages.size() < 2) {
+            return mileages;
+        }
+
+        for (int i = 0; i < mileages.size() - 1; i++) {
+            //首先点到的点长 和 方位角
+            initMileage(mileages.get(i), mileages.get(i + 1));
+        }
+        for (int i = 0; i < mileages.size() - 1; i++) {
+            //再计算曲线要素及主点坐标
+            initMileage2(mileages.get(i), mileages.get(i + 1));
+        }
+        //优化曲线首尾相连
+        initMileage4(mileages);
+
+        return mileages;
+    }
+
+    /**
+     * 计算坐标
+     */
+    public static double[] azimuthZb(double lc, double b,double jj, List<Mileage> mileages) {
+        double[] res = null;
+        List<Mileage> list=null;
+        for(int i=1;i<10;i++) {
+           list=new ArrayList<>();
+            String partNo="NO"+i;
+            for(Mileage m:mileages){
+                if(partNo.equals(m.getPartNo())){
+                    list.add(m);
+                }
+            }
+            if(list.size()>2){
+                res=azimuthZbNew(lc,b,jj,list);
+               if(res!=null){
+                   break;
+               }
+            }
+
+        }
+        return res;
+    }
+    /**
+     * 计算坐标
+     */
+    private static double[] azimuthZbNew(double lc, double b,double jj, List<Mileage> mileages) {
+        double[] res = null;
+        double[] zzres = null;
+        double[] xy;
+        double l;
+        int type = 0;
+        double A;
+
+        for (int i = 1; i < mileages.size() - 1; i++) {
+
+            Mileage q = mileages.get(i - 1);
+            Mileage j = mileages.get(i);
+            Mileage z = mileages.get(i + 1);
+            if (j.getSwing().equals("左转")) {
+                type = 1;
+            } else {
+                type = 0;
+            }
+            double qd = 0;
+            double qx = 0, qy = 0;
+            if (i == 1) {
+                qd = q.getValue();
+                qx = q.getX();
+                qy = q.getY();
+            } else {
+                qd = q.getHz();
+                qx = q.getHzx();
+                qy = q.getHzy();
+            }
+            double zd = z.getValue();
+            if (qd < lc && lc <= j.getZh()) {//在起点至zh上(直线上)
+
+
+                    zzres = azimuthZb(qx, qy, lc - qd, q.getAngle());
+                A = q.getAngle() + jj;
+                res = azimuthZb(zzres[0], zzres[1], b, A);
+//                    if (b > 0) {
+//                        A = q.getAngle() + jj;
+//                    } else {
+//                        A = q.getAngle() - jj;
+//                    }
+//                    if (A >= 360) {
+//                        A = A - 360;
+//                    }
+//                    if (A < 0) {
+//                        A = A + 360;
+//                    }
+//
+//                    if (b > 0) {
+//                        res = azimuthZb(zzres[0], zzres[1], b, A);
+//                    } else {
+//                        res = azimuthZb(zzres[0], zzres[1], -b, A);
+//                    }
+
+            } else if (j.getZh() < lc && lc <= j.getHy()) {//在zh至hy上(第一缓和线上)
+                xy = azimuthZbhhqx1(j.getR(), lc - j.getZh(), j.getLs1());
+
+                    l = lc - j.getZh();
+                    double b01 = (l * l / (2 * j.getR() * j.getLs1())) * (180 / Math.PI);
+                    if (type == 1) {
+                        b01 = -b01;
+                    }
+//                    if (b > 0) {
+//                        A = q.getAngle() + b01 + jj;
+//                    } else {
+//                        A = q.getAngle() + b01 - jj;
+//                    }
+//                    if (A >= 360) {
+//                        A = A - 360;
+//                    }
+//                    if (A < 0) {
+//                        A = A + 360;
+//                    }
+
+                    zzres = azimuthZbqx(j.getZhx(), j.getZhy(), q.getAngle(), xy[0], xy[1], type);
+                A = q.getAngle() + b01 + jj;
+                res = azimuthZb(zzres[0], zzres[1], b, A);
+//                    if (b > 0) {
+//                        res = azimuthZb(zzres[0], zzres[1], b, A);
+//                    } else {
+//                        res = azimuthZb(zzres[0], zzres[1], -b, A);
+//                    }
+
+            } else if (j.getHy() < lc && lc <= j.getYh()) {//在hy至yh上(圆曲线上)
+                xy = azimuthZbyqx(j.getR(), lc - j.getZh(), j.getLs1());
+
+                    l = lc - j.getZh();
+
+                    double g = ((l - j.getLs1()) / j.getR() + j.getB01()) * (180 / Math.PI);
+
+                    if (type == 1) {
+                        g = -g;
+                    }
+//                    if (b > 0) {
+//                        A = q.getAngle() + g + jj;
+//                    } else {
+//                        A = q.getAngle() + g - jj;
+//                    }
+//                    if (A >= 360) {
+//                        A = A - 360;
+//                    }
+//                    if (A < 0) {
+//                        A = A + 360;
+//                    }
+                    zzres = azimuthZbqx(j.getZhx(), j.getZhy(), q.getAngle(), xy[0], xy[1], type);
+                A = q.getAngle() + g + jj;
+                res = azimuthZb(zzres[0], zzres[1], b, A);
+//                    if (b > 0) {
+//                        res = azimuthZb(zzres[0], zzres[1], b, A);
+//                    } else {
+//                        res = azimuthZb(zzres[0], zzres[1], -b, A);
+//                    }
+
+
+//            }else if(j.getHy()<lc&&lc<=j.getQz()) {//在hy至qz上(圆曲线上)
+//            }else if(j.getQz()<lc&&lc<=j.getYh()) {//在qz至yh上(圆曲线上)
+//                }
+//
+
+            } else if (j.getYh() < lc && lc <= j.getHz()) {//在yh至hz上(第二缓和线上)
+                xy = azimuthZbhhqx1(j.getR(), lc - j.getHz(), j.getLs2());
+
+                    l = lc - j.getHz();
+                    // double b01=l/(2*j.getR())*(180/Math.PI);
+                    double b01 = (l * l / (2 * j.getR() * j.getLs2())) * (180 / Math.PI);
+                    if (type == 1) {
+                        b01 = -b01;
+                    }
+
+//                    if (b > 0) {
+//                        A = j.getAngle() - b01 + jj;
+//                    } else {
+//                        A = j.getAngle() - b01 - jj;
+//                    }
+//                    if (A >= 360) {
+//                        A = A - 360;
+//                    }
+//                    if (A < 0) {
+//                        A = A + 360;
+//                    }
+                    zzres = azimuthZbqx(j.getHzx(), j.getHzy(), j.getAngle(), xy[0], -xy[1], type);
+                A = j.getAngle() - b01 + jj;
+                res = azimuthZb(zzres[0], zzres[1], b, A);
+//                    if (b > 0) {
+//                        res = azimuthZb(zzres[0], zzres[1], b, A);
+//                    } else {
+//                        res = azimuthZb(zzres[0], zzres[1], -b, A);
+//                    }
+
+
+            } else if (j.getHz() < lc && lc <= zd) {//在hz至终点上(直线上)
+                if(j.getDlq()!=0&&lc>j.getDlq()){
+                    lc=lc-(j.getDlh()-j.getDlq());
+                }
+
+                    zzres = azimuthZb(j.getHzx(), j.getHzy(), lc - j.getHz(), j.getAngle());
+                A = j.getAngle() + jj;
+                res = azimuthZb(zzres[0], zzres[1], b, A);
+//                    if (b > 0) {
+//                        A = j.getAngle() + jj;
+//                    } else {
+//                        A = j.getAngle() - jj;
+//                    }
+//                    if (A > 360) {
+//                        A = A - 360;
+//                    }
+//                    if (A < 0) {
+//                        A = A + 360;
+//                    }
+//                    if (b > 0) {
+//                        res = azimuthZb(zzres[0], zzres[1], b, A);
+//                    } else {
+//                        res = azimuthZb(zzres[0], zzres[1], -b, A);
+//                    }
+                }
+
+        }
+        return res;
+    }
+
+
+    /**
+     * 初始化里程数据
+     */
+    private static void initMileage0(Mileage mileage) {
+        int type = mileage.getType();
+        Double value = mileage.getValue();
+        Double x = mileage.getX();
+        Double y = mileage.getY();
+        Integer orderNum = mileage.getOrderNum();
+        String code = mileage.getCode();
+        Double r = mileage.getR();
+        Double ls1 = mileage.getLs1();
+        Double ls2 = mileage.getLs2();
+        Double dlq = mileage.getDlq();
+        Double dlh = mileage.getDlh();
+
+        if (type == 1) {
+            mileage = new Mileage(code, x, y, r, orderNum, type, ls1, ls2, dlq, dlh);
+        } else {
+            if (type == 2) {
+                value = 0.0;
+            }
+            mileage = new Mileage(value, x, y, orderNum, type);
+        }
+    }
+
+    /**
+     * 初始化里程数据 点到点的长,方位角,交点坐标
+     */
+    private static void initMileage(Mileage mileage, Mileage nextMileage) {
+
+        double x1 = mileage.getX();
+        double y1 = mileage.getY();
+        double x2 = nextMileage.getX();
+        double y2 = nextMileage.getY();
+
+
+        double dx, dy, angle = 0;
+        dx = x2 - x1;
+        dy = y2 - y1;
+
+
+        //计算方位角
+        double yx = dy / dx;
+        if (yx < 0) {
+            yx = -yx;
+        }
+
+        angle = Math.atan(yx);
+        angle = angle * (180 / Math.PI);
+        if (dx > 0 && dy >= 0) {
+        } else if (dx < 0 && dy >= 0) {
+            angle = 180 - angle;
+        } else if (dx < 0 && dy < 0) {
+            angle = 180 + angle;
+        } else if (dx > 0 && dy < 0) {
+            angle = 360 - angle;
+        }else if (dx == 0 && dy > 0) {
+            angle = 90;
+        }else if (dx == 0 && dy < 0) {
+            angle = 270;
+        }
+
+        if(angle!=0) {
+            angle = NumberUtil.round(angle, precision);
+        }
+        mileage.setAngle(angle);
+
+        //计算点到点的距离
+        if (dx < 0) {
+            dx = -dx;
+        }
+        if (dy < 0) {
+            dy = -dy;
+        }
+        double l = Math.sqrt(dx * dx + dy * dy);
+        l = NumberUtil.round(l, precision);
+        nextMileage.setLjd(l);
+        nextMileage.setValue(mileage.getValue() + l);
+//        nextMileage.setValue(mileage.getValue()+NumberUtil.round(l,precision));
+
+    }
+
+    /**
+     * 初始化里程数据 曲线要素,转角
+     */
+    private static void initMileage2(Mileage mileage, Mileage nextMileage) {
+        double ACorner=nextMileage.getAngle() - mileage.getAngle();
+
+        if(ACorner>180){
+            ACorner= ACorner-360;
+        }
+        if(-ACorner>180){
+            ACorner= ACorner+360;
+        }
+        nextMileage.setCorner(ACorner);
+
+        double R = mileage.getR();
+        double ls1 = mileage.getLs1();
+        double ls2 = mileage.getLs2();
+
+        double A = mileage.getCorner();
+        double T1 = 0, L = 0, D = 0, Lc = 0, T2 = 0, b01 = 0, b02 = 0, p1 = 0, q1 = 0, p2 = 0, q2 = 0;
+
+        //计算曲线要素
+        /**
+         *   //书本算法
+
+         b01=ls1/(2*R);
+         b02=ls2/(2*R);
+         p1=ls1*ls1/(24*R);
+         p2=ls2*ls2/(24*R);
+         q1=(ls1/2)-(ls1*ls1*ls1/(240*R*R));
+         q2=(ls2/2)-ls2*ls2*ls2/(240*R*R);
+
+         if(A<0){
+         A=-A;
+         mileage.setSwing("左转");
+         }else{
+         mileage.setSwing("右转");
+         }
+         mileage.setCorner(A);
+         A=A* Math.PI/180;
+         T1=(R+p1)*Math.tan(A/2)+q1;
+         T1= NumberUtil.round(T1,precision);
+         T2=(R+p2)*Math.tan(A/2)+q2;
+         T2= NumberUtil.round(T2,precision);
+         */
+        if (A < 0) {
+            A = -A;
+            mileage.setSwing("左转");
+        } else {
+            mileage.setSwing("右转");
+        }
+        mileage.setCorner(A);
+        if (R != 0) {
+
+            b01 = ls1 / (2 * R);
+            b01 = NumberUtil.round(b01, precision);
+            b02 = ls2 / (2 * R);
+            b02 = NumberUtil.round(b02, precision);
+            p1 = ls1 / 2 - (Math.pow(ls1, 3) / (240 * R * R)) + (Math.pow(ls1, 5) / (34560 * Math.pow(R, 4)));
+            p1 = NumberUtil.round(p1, precision);
+            p2 = ls2 / 2 - (Math.pow(ls2, 3) / (240 * R * R)) + (Math.pow(ls2, 5) / (34560 * Math.pow(R, 4)));
+            p2 = NumberUtil.round(p2, precision);
+            q1 = Math.pow(ls1, 2) / (24 * R) - (Math.pow(ls1, 4) / (2688 * Math.pow(R, 3))) + (Math.pow(ls1, 6) / (506880 * Math.pow(R, 5)));
+            q1 = NumberUtil.round(q1, precision);
+            q2 = Math.pow(ls2, 2) / (24 * R) - (Math.pow(ls2, 4) / (2688 * Math.pow(R, 3))) + (Math.pow(ls2, 6) / (506880 * Math.pow(R, 5)));
+            q2 = NumberUtil.round(q2, precision);
+
+
+            A = A * Math.PI / 180;
+            T1 = p1 + (R + q2 - (R + q1) * Math.cos(A)) / Math.sin(A);
+            T1 = NumberUtil.round(T1, precision);
+            T2 = p2 + (R + q1 - (R + q2) * Math.cos(A)) / Math.sin(A);
+            T2 = NumberUtil.round(T2, precision);
+            if (T1 < 0) {
+                T1 = -T1;
+            }
+            if (T2 < 0) {
+                T2 = -T2;
+            }
+            Lc = R * (A - b01 - b02);
+//        Lc=R*A-(ls1/2)-(ls2/2);
+            Lc = NumberUtil.round(Lc, precision);
+            L = Lc + ls1 + ls2;
+            L = NumberUtil.round(L, precision);
+
+            D = T1 + T2 - L;
+            D = NumberUtil.round(D, precision);
+        }
+        mileage.setT1(T1);
+        mileage.setT2(T2);
+        mileage.setB01(b01);
+        mileage.setB02(b02);
+        mileage.setQ1(q1);
+        mileage.setQ2(q2);
+        mileage.setP1(p1);
+        mileage.setP2(p2);
+        mileage.setL(L);
+        mileage.setLc(Lc);
+        mileage.setD(D);
+        initMileage3(mileage, nextMileage);
+    }
+
+    /****
+     * 计算主点里程  计算下一交点(终点)里程桩号
+     * @param mileage
+     * @param nextMileage
+     */
+
+    private static void initMileage3(Mileage mileage, Mileage nextMileage) {
+        //计算主点里程
+        double hy = 0, yh = 0, hz = 0, qz = 0, dl = 0;
+        double zh = mileage.getValue() - mileage.getT1();
+        dl = mileage.getDlh() - mileage.getDlq();
+        zh = NumberUtil.round(zh, precision);
+        hy = zh + mileage.getLs1();
+        hy = NumberUtil.round(hy, precision);
+        yh = hy + mileage.getLc();
+        yh = NumberUtil.round(yh, precision);
+        hz = yh + mileage.getLs2();
+        hz = NumberUtil.round(hz, precision);
+        qz = hz - mileage.getL() / 2;
+        //计算下一交点(终点)里程桩号
+        double nextValue = hz + nextMileage.getLjd() - mileage.getT2() + dl;
+        mileage.setZh(zh);
+        mileage.setHy(hy);
+        mileage.setYh(yh);
+        mileage.setHz(hz);
+        mileage.setQz(qz);
+
+//        nextValue= NumberUtil.round(nextValue,precision);
+        nextMileage.setValue(nextValue);
+
+    }
+
+    /***
+     * 计算zh,hz的坐标
+     * @param mileages
+     */
+    private static void initMileage4(List<Mileage> mileages) {
+        for (int i = 1; i < mileages.size() - 1; i++) {
+            double[] xy = new double[2];
+            Mileage q = mileages.get(i - 1);
+            Mileage j = mileages.get(i);
+            //去掉小于spacing的首尾相连
+            double cj;
+            cj = j.getZh() - q.getHz();
+            cj = NumberUtil.round(cj, spacing_precision);
+            if (cj < 0) {
+                cj = -cj;
+            }
+            if (cj < spacing) {
+                j.setValue(q.getHz() + j.getT1());
+
+                for (int ii = i; ii < mileages.size() - 1; ii++) {
+                    initMileage3(mileages.get(ii), mileages.get(ii + 1));
+                }
+
+            }
+            if (j.getType() == 1) {
+
+
+                xy = azimuthZb(j.getX(), j.getY(), -j.getT1(), q.getAngle());
+                j.setZhx(xy[0]);
+                j.setZhy(xy[1]);
+
+                xy = azimuthZb(j.getX(), j.getY(), j.getT2(), j.getAngle());
+                j.setHzx(xy[0]);
+                j.setHzy(xy[1]);
+            }
+        }
+    }
+    /**************交点法******结束***/
+
+    /******************线元法***********开始**/
+    /**
+     * 初始化线元里程信息数据
+     *
+     * @param mileagexys
+     * @return
+     */
+    public static List<Mileagexy> initMileagexys(List<Mileagexy> mileagexys, int oderNum) {
+        for (int i = 0; i < mileagexys.size() - 1; i++) {
+            if (mileagexys.get(i).getOrderNum() >= oderNum) {
+                initMileagexy(mileagexys.get(i), mileagexys.get(i + 1));
+            }
+        }
+        return mileagexys;
+    }
+
+    /**
+     * 线元法坐标计算
+     * @param lc
+     * @param b
+     * @param jj
+     * @param mileagexys
+     * @return
+     */
+    public static double[] azimuthZbXy(double lc, double b,double jj, List<Mileagexy> mileagexys) {
+        double[] res = null;
+
+        for (Mileagexy mileagexy : mileagexys) {
+            if (mileagexy.getValue() <= lc && (mileagexy.getValueEnd()+0.0000000000001) >= lc) {
+                double angle=mileagexy.getAngle();
+                double l = lc - mileagexy.getValue();
+                int type = mileagexy.getType();
+                int sw = 0;
+                if ("左转".equals(mileagexy.getSwing())) {
+                    sw = 1;
+                } else {
+                    sw = 0;
+                }
+                if (type == 0) {
+                    if(mileagexy.getDlq()!=0&&lc>mileagexy.getDlq()){
+                           l=lc-(mileagexy.getDlh()-mileagexy.getDlq())- mileagexy.getValue();
+                    }
+                    res = azimuthZb(mileagexy.getX(), mileagexy.getY(), l, mileagexy.getAngle());
+
+                } else if (type == 1) {
+                    if(mileagexy.getDlq()!=0&&lc>mileagexy.getDlq()){
+                        l=lc-(mileagexy.getDlh()-mileagexy.getDlq())- mileagexy.getValue();
+                    }
+                    double[] xy = azimuthZbyqx(mileagexy.getR(), l, 0);
+                    double g = (l / mileagexy.getR()) * (180 / Math.PI);
+                    res = azimuthZbqx(mileagexy.getX(), mileagexy.getY(), mileagexy.getAngle(), xy[0], xy[1], sw);
+                    if (sw == 1) {
+                        g = -g;
+                    }
+                    angle=angle+g;
+
+                } else if (type == 2) {
+                    if(mileagexy.getDlq()!=0&&lc>mileagexy.getDlq()){
+                        l=lc-(mileagexy.getDlh()-mileagexy.getDlq())- mileagexy.getValue();
+                    }
+                    double b01 = (l * l / (2 * mileagexy.getR() * mileagexy.getL())) * (180 / Math.PI);
+                    double[] xy = azimuthZbhhqx1(mileagexy.getR(), l, mileagexy.getL());
+                    res = azimuthZbqx(mileagexy.getX(), mileagexy.getY(), mileagexy.getAngle(), xy[0], xy[1], sw);
+                    if (sw == 1) {
+                        b01 = -b01;
+                    }
+                    angle=angle+b01;
+
+                } else if (type == 3) {
+                    if(mileagexy.getDlq()!=0&&lc>mileagexy.getDlq()){
+                        l=lc-(mileagexy.getDlh()-mileagexy.getDlq())- mileagexy.getValueEnd();
+                    }else {
+                    l =   lc-mileagexy.getValueEnd();
+                    }
+                    double[] xy1 = azimuthZbhhqx1(mileagexy.getR(), l, mileagexy.getL());
+                    double[] xy2 = azimuthZbhhqx1(mileagexy.getR(), mileagexy.getL(), mileagexy.getL());
+                    double b03 = (l * l / (2 * mileagexy.getR() * mileagexy.getL())) * (180 / Math.PI);
+                    double b02 = (mileagexy.getL() / (2 * mileagexy.getR())) * (180 / Math.PI);
+                    double a = mileagexy.getAngle() + b02;
+                    if(sw==1){
+                        a = mileagexy.getAngle() - b02;
+                        b03= -b03;
+                    }
+                    double[] resend = azimuthZbqx(mileagexy.getX(), mileagexy.getY(), a, xy2[0], -xy2[1], sw);
+                    res = azimuthZbqx(resend[0], resend[1], a, xy1[0], -xy1[1], sw);
+                    angle=a - b03;
+
+                } else if (type == 4) {
+                    double c = (mileagexy.getL() * mileagexy.getR() * mileagexy.getR2()) / (mileagexy.getR() - mileagexy.getR2());
+                    double ls = c / mileagexy.getR2();
+                    double lp = ls - mileagexy.getL();
+                    l = l + lp;
+                    double[] xy = azimuthZbhhqx1((mileagexy.getR2()), l, ls);
+                    double b03 = ((lp * lp) / (2 * mileagexy.getR2() * ls)) * (180 / Math.PI);
+                    double b01 = ((l * l) / (2 * mileagexy.getR2() * ls)) * (180 / Math.PI);
+                    if (sw == 1) {
+                        b01 = -b01;
+                        b03 = -b03;
+                    }
+                    double[] hzres;
+                    double[] hzxy = azimuthZbhhqx1((mileagexy.getR2()), lp, ls);
+                    hzres = azimuthZbqx(mileagexy.getX(), mileagexy.getY(), mileagexy.getAngle() - b03, -hzxy[0], -hzxy[1], sw);
+                    res = azimuthZbqx(hzres[0], hzres[1], mileagexy.getAngle() - b03, xy[0], xy[1], sw);
+                    angle=angle- b03 + b01;
+                }
+                if (res != null) {
+                     res = azimuthZb(res[0], res[1], b, angle + jj);
+
+                }
+            }
+        }
+
+        return res;
+    }
+
+    public static void initMileagexy(Mileagexy mileagexy, Mileagexy nextMileagexy) {
+        initMileagexyValueEnd(mileagexy);
+        int type = mileagexy.getType();
+
+        int sw = 0;
+        if ("左转".equals(mileagexy.getSwing())) {
+            sw = 1;
+        } else {
+            sw = 0;
+        }
+        if (type == 0) {
+
+            double[] res = azimuthZb(mileagexy.getX(), mileagexy.getY(), mileagexy.getL(), mileagexy.getAngle());
+            nextMileagexy.setValue(mileagexy.getValueEnd());
+            nextMileagexy.setX(NumberUtil.round(res[0], precision));
+            nextMileagexy.setY(NumberUtil.round(res[1], precision));
+            initMileagexyAngle(nextMileagexy,mileagexy.getAngle());
+            nextMileagexy.setOrderNum(mileagexy.getOrderNum() + 1);
+            initMileagexyValueEnd(nextMileagexy);
+
+        } else if (type == 2 || type == 3) {
+            double[] res;
+            double[] xy = azimuthZbhhqx1(mileagexy.getR(), mileagexy.getL(), mileagexy.getL());
+            // double b01=(mileagexy.getL()/(2*mileagexy.getR()))*(180/Math.PI);
+            double b01 = ((mileagexy.getL() * mileagexy.getL()) / (2 * mileagexy.getR() * mileagexy.getL())) * (180 / Math.PI);
+            if (type == 2) {
+                res = azimuthZbqx(mileagexy.getX(), mileagexy.getY(), mileagexy.getAngle(), xy[0], xy[1], sw);
+            } else {
+                double a = mileagexy.getAngle() + b01;
+                if(sw==1){
+                    a = mileagexy.getAngle() - b01;
+                }
+//                    String[] ang=convertToSexagesimal1(a);
+//                    a=Double.valueOf(ang[0])+(Double.valueOf(ang[1])/60)+(Double.valueOf(ang[2])/3600);
+                res = azimuthZbqx(mileagexy.getX(), mileagexy.getY(), a, xy[0], -xy[1], sw);
+            }
+            nextMileagexy.setValue(mileagexy.getValueEnd());
+            nextMileagexy.setX(NumberUtil.round(res[0], precision));
+            nextMileagexy.setY(NumberUtil.round(res[1], precision));
+
+
+            if (sw == 1) {
+                b01 = -b01;
+            }
+            double angle=(mileagexy.getAngle() + b01);
+            initMileagexyAngle(nextMileagexy,angle);
+            nextMileagexy.setOrderNum(mileagexy.getOrderNum() + 1);
+            initMileagexyValueEnd(nextMileagexy);
+        } else if (type == 4) {
+            double[] res;
+            double c = (mileagexy.getL() * mileagexy.getR() * mileagexy.getR2()) / (mileagexy.getR() - mileagexy.getR2());
+            double l = c / mileagexy.getR2();
+            double lp = l - mileagexy.getL();
+            double[] xy = azimuthZbhhqx1((mileagexy.getR2()), l, l);
+            double b02 = (l / (2 * (mileagexy.getR2()))) * (180 / Math.PI);
+            double b03 = ((lp * lp) / (2 * mileagexy.getR2() * l)) * (180 / Math.PI);
+            double b01 = b02 - b03;
+            double[] hzres;
+            double[] hzxy = azimuthZbhhqx1((mileagexy.getR2()), lp, l);
+            double ang=mileagexy.getAngle() - b03;
+            if (sw == 1) {
+                ang=mileagexy.getAngle() +b03;
+            }
+            hzres = azimuthZbqx(mileagexy.getX(), mileagexy.getY(), ang, -hzxy[0], -hzxy[1], sw);
+            res = azimuthZbqx(hzres[0], hzres[1], ang, xy[0], xy[1], sw);
+            nextMileagexy.setValue(mileagexy.getValueEnd());
+            nextMileagexy.setX(NumberUtil.round(res[0], precision));
+            nextMileagexy.setY(NumberUtil.round(res[1], precision));
+
+
+            if (sw == 1) {
+                b01 = -b01;
+            }
+            double angle=(mileagexy.getAngle() + b01);
+            initMileagexyAngle(nextMileagexy,angle);
+            nextMileagexy.setOrderNum(mileagexy.getOrderNum() + 1);
+            initMileagexyValueEnd(nextMileagexy);
+        } else if (type == 1) {
+            double[] xy = azimuthZbyqx(mileagexy.getR(), mileagexy.getL(), 0);
+            double[] res = azimuthZbqx(mileagexy.getX(), mileagexy.getY(), mileagexy.getAngle(), xy[0], xy[1], sw);
+            nextMileagexy.setValue(mileagexy.getValueEnd());
+            nextMileagexy.setX(NumberUtil.round(res[0], precision));
+            nextMileagexy.setY(NumberUtil.round(res[1], precision));
+            double g = (mileagexy.getL() / mileagexy.getR()) * (180 / Math.PI);
+            if (sw == 1) {
+                g = -g;
+            }
+            double angle=(mileagexy.getAngle() + g);
+            initMileagexyAngle(nextMileagexy,angle);
+            nextMileagexy.setOrderNum(mileagexy.getOrderNum() + 1);
+            initMileagexyValueEnd(nextMileagexy);
+        }
+
+    }
+
+    public static void initMileagexyAngle(Mileagexy nextMileagexy,double angle) {
+        if (angle >= 360) {
+            angle = angle - 360;
+        }
+        if (angle < 0) {
+            angle = angle + 360;
+        }
+        String[] ang = convertToSexagesimal1(angle);
+        if(nextMileagexy.getType()==0) {
+            if(nextMileagexy.getAngle()==0.0) {
+                nextMileagexy.setAngle(angle);
+                nextMileagexy.setDu(Integer.valueOf(ang[0]));
+                nextMileagexy.setFen(Integer.valueOf(ang[1]));
+                nextMileagexy.setMiao(Double.valueOf(ang[2]));
+            }
+        }else{
+            nextMileagexy.setAngle(angle);
+            nextMileagexy.setDu(Integer.valueOf(ang[0]));
+            nextMileagexy.setFen(Integer.valueOf(ang[1]));
+            nextMileagexy.setMiao(Double.valueOf(ang[2]));
+        }
+    }
+
+    public static void initMileagexyValueEnd(Mileagexy mileagexy) {
+        double dl=0.0;
+//        if(mileagexy.getType()==0){
+            dl=mileagexy.getDlh()-mileagexy.getDlq();
+//        }
+        mileagexy.setValueEnd(mileagexy.getValue()+mileagexy.getL()+dl);
+        double fen = Double.valueOf(mileagexy.getFen());
+        fen=fen/60;
+        double miao = mileagexy.getMiao() / 3600;
+        mileagexy.setAngle(mileagexy.getDu()+fen+miao);
+}
+
+    /**************线元法******结束***/
+
+    /**计算直线坐标
+     *
+     */
+    private static double[] azimuthZb(double x1, double y1,double d,double a){
+
+        double x=0,y=0;
+        double[] res=new double[3];
+        a=a* Math.PI/180;
+        x= x1+d*Math.cos(a);
+        //  x= NumberUtil.round(x,precision);
+        y= y1+d*Math.sin(a);
+        // y= NumberUtil.round(y,precision);
+        // System.out.println(NumberUtil.format(y,3));
+        res[0]=x;
+        res[1]=y;
+        res[2]=a/(Math.PI/180)-90 ;
+
+        return res;
+    }
+    /**计算曲线坐标
+     *8-1-23
+     */
+    private static double[] azimuthZbqx(double x1, double y1,double a,double xx,double yy,int type) {
+        double x = 0, y = 0;
+        double[] res = new double[2];
+        a = a * Math.PI / 180;
+        if (type==1) {
+            yy=-yy;
+        }
+        x = x1 + xx * Math.cos(a) - yy * Math.sin(a);
+        // x = NumberUtil.round(x, precision);
+
+        y = y1 + xx * Math.sin(a) + yy * Math.cos(a);
+
+        // y= NumberUtil.round(y,precision);
+        // System.out.println(NumberUtil.format(y,3));
+        res[0]=x;
+        res[1]=y;
+
+        return res;
+    }
+
+    /**计算缓和曲线支距法坐标
+     *
+     */
+    private static double[] azimuthZbhhqx(double r, double l,double ls){
+        double x=0,y=0;
+        double[] res=new double[2];
+
+        x= l-Math.pow(l, 5)/(40*Math.pow(r, 2)*Math.pow(ls, 2));
+        //   x= NumberUtil.round(x,precision);
+        y= Math.pow(l, 3)/(6*r*ls);
+        //  y= NumberUtil.round(y,precision);
+        // System.out.println(NumberUtil.format(y,3));
+        res[0]=x;
+        res[1]=y;
+
+        return res;
+    }
+    private static double[] azimuthZbhhqx1(double r, double l,double ls){
+        double x=0,y=0;
+        double[] res=new double[2];
+
+        x= l-Math.pow(l, 5)/(40*Math.pow(r, 2)*Math.pow(ls, 2))+Math.pow(l, 9)/(3456*Math.pow(r, 4)*Math.pow(ls, 4));
+        //   x= NumberUtil.round(x,precision);
+        y= Math.pow(l, 3)/(6*r*ls)-Math.pow(l, 7)/(336*Math.pow(r, 3)*Math.pow(ls, 3))+Math.pow(l, 11)/(42240*Math.pow(r, 5)*Math.pow(ls, 5));
+        //  y= NumberUtil.round(y,precision);
+        // System.out.println(NumberUtil.format(y,3));
+        res[0]=x;
+        res[1]=y;
+
+        return res;
+    }
+    /**计算圆曲线支距法坐标
+     *
+     */
+    private static double[] azimuthZbyqx(double r, double l,double ls){
+        double x=0,y=0,b0=0,p=0,q=0,g=0;
+        double[] res=new double[2];
+        b0=ls/(2*r);
+        p=ls*ls/(24*r);
+        q=ls/2-ls*ls*ls/(240*r*r);
+        g=(l-ls)/r+b0;
+        x= r*Math.sin(g)+q;
+        // x= NumberUtil.round(x,precision);
+        y= r*(1-Math.cos(g))+p;
+        // y= NumberUtil.round(y,precision);
+        // System.out.println(NumberUtil.format(y,3));
+        res[0]=x;
+        res[1]=y;
+
+        return res;
+    }
+
+    /**
+     *  转换度数
+     */
+    public static String convertToSexagesimal(double num){
+        double numm=num;
+        if(numm<0){
+            numm=-numm;
+        }
+        int du=(int)Math.floor(Math.abs(numm));    //获取整数部分
+
+        double temp=(numm-du)*60;
+
+        int fen=(int)Math.floor(temp); //获取整数部分
+        String fenstr=String.valueOf(fen);
+        if(fen<10){
+            fenstr="0"+String.valueOf(fen);
+        }
+        double miao=(temp-fen)*60;
+        miao= NumberUtil.round(miao,2);
+        String miaostr=String.valueOf(miao);
+        if(miao<10){
+            miaostr="0"+String.valueOf(miao);
+        }
+        if(num<0) {
+            return "-" + du + "°" + fenstr + "′" + miaostr + "″";
+        }
+
+        return du+"°"+fenstr+"′"+miaostr+"″";
+
+
+
+    }
+    /**
+     *  转换度数
+     */
+    public static String[] convertToSexagesimal1(double num){
+        double numm=num;
+        if(numm<0){
+            numm=-numm;
+        }
+        int du=(int)Math.floor(Math.abs(numm));    //获取整数部分
+
+        double temp=(numm-du)*60;
+
+        int fen=(int)Math.floor(temp); //获取整数部分
+
+        double miao=(temp-fen)*60;
+        miao= NumberUtil.round(miao,4);
+
+        String[] res=new String[3];
+        res[0]=String.valueOf(du);
+        res[1]=String.valueOf(fen);
+        res[2]=String.valueOf(miao);
+        return res;
+
+
+
+    }
+
+
+    /**
+     *  转换里程
+     */
+    public static String convertToMileage(double num){
+        double numm=num;
+        if(numm<0){
+            numm=-numm;
+        }
+        double numn = numm/1000;
+
+        int du=(int)Math.floor(Math.abs(numn));    //获取整数部分
+
+        double temp=(num-(du*1000));
+
+        int fen=(int)Math.floor(temp); //获取整数部分
+        String fenstr=String.valueOf(fen);
+        if(fen<100){
+            fenstr="0"+String.valueOf(fen);
+        }
+        if(fen<10){
+            fenstr="00"+String.valueOf(fen);
+        }
+
+        int miao=(int)Math.floor((NumberUtil.round(temp-fen,precision_1))*Math.pow(10, precision_1)); //获取整数部分
+        if(miao==0){
+            if(num<0) {
+                return "-"+prefix+du+"+"+fenstr;
+            }
+            return prefix+du+"+"+fenstr;
+        }else{
+            String miaotr=String.valueOf(miao);
+            if(miao<100){
+                miaotr="0"+String.valueOf(miao);
+            }
+            if(miao<10){
+                miaotr="00"+String.valueOf(miao);
+            }
+            if(num<0) {
+                return "-"+prefix+du+"+"+fenstr+"."+miaotr;
+            }
+            return prefix+du+"+"+fenstr+"."+miaotr;
+        }
+
+
+
+
+    }
+
+    /**
+     *
+     * 生成逐桩坐标
+     * @param lc 桩距
+     * @param b  偏移
+     * @param mileages
+     * @return
+     */
+    public static List<Mileage> azimuthZzZb(double kslc,double jslc,double lc, double b,List<Mileage> mileages) {
+
+        List<Mileage> relist=new ArrayList<>();
+        if(mileages.size()<=2){
+            return relist;
+        }
+
+        int qd=(int)(kslc/100);
+        qd=qd*100;
+
+        double l=(jslc-qd );
+        if(l>0) {
+            if (lc < l) {
+
+                int c = (int) (l % lc == 0 ? (l / lc) : (l / lc) + 1);
+                for (int ii = 0; ii < c; ii++) {
+                    putZzMileages0(qd + (ii * lc), b, mileages, null, relist, 0);
+
+                }
+
+            }
+        }
+            for (Mileage mleage :mileages) {
+               if(mleage.getType()==1){
+                   if(mleage.getZh()>=kslc&&mleage.getZh()<=jslc) {
+                       putZzMileages0(mleage.getZh(), b, mileages, null, relist, 0);
+                   }
+                   if(mleage.getHy()>=kslc&&mleage.getHy()<=jslc) {
+                       putZzMileages0(mleage.getHy(),b,mileages,null,relist,0);
+                   }
+                   if(mleage.getYh()>=kslc&&mleage.getYh()<=jslc) {
+                       putZzMileages0(mleage.getYh(),b,mileages,null,relist,0);
+                   }
+                   if(mleage.getHz()>=kslc&&mleage.getHz()<=jslc) {
+                       putZzMileages0(mleage.getHz(),b,mileages,null,relist,0);
+                   }
+                   if(mleage.getQz()>=kslc&&mleage.getQz()<=jslc) {
+                       putZzMileages0(mleage.getQz(),b,mileages,null,relist,0);
+                   }
+
+               }
+            }
+        putZzMileages0(jslc,b,mileages,null,relist,0);
+
+        return relist;
+    }
+    /**
+     * 线元法
+     * 生成逐桩坐标
+     * @param lc 桩距
+     * @param b  偏移
+     * @param mileagexys
+     * @return
+     */
+    public static List<Mileage> azimuthZzZbXy(double kslc,double jslc,double lc, double b,List<Mileagexy> mileagexys) {
+        List<Mileage> relist=new ArrayList<>();
+        if(mileagexys.size()<1){
+          return  relist;
+        }
+       // Collections.sort(mileagexys); // 按桩号排序
+//        int qd=(int)(kslc/100);
+//        qd=qd*100;
+        double qd =kslc;
+        double l=jslc-qd;
+        if(l>0) {
+            if (lc < l) {
+                /**
+                 * 生成桩点数量,如果不能整除则+1
+                 */
+                int c = (int) (l % lc == 0 ? (l / lc) : (l / lc) + 1);
+                for (int ii = 0; ii < c; ii++) {
+                    putZzMileages0(qd + (ii * lc), b, null, mileagexys, relist, 1);
+
+                }
+
+            }
+        }
+
+        for(Mileagexy mileagexy:mileagexys){
+         if(mileagexy.getValue()>=kslc&&mileagexy.getValue()<=jslc) {
+             putZzMileages0(mileagexy.getValue(), b, null, mileagexys, relist, 1);
+         }
+
+        }
+        putZzMileages0(jslc, b, null, mileagexys, relist, 1);
+
+        return relist;
+    }
+    private static void putZzMileages0(double lc,double b,List<Mileage> zhlist,List<Mileagexy> zhlistXY,List<Mileage> relist,int type){
+
+        for(Mileage m:relist){
+            if(lc==m.getValue()&&b==m.getB()){
+                return;
+            }
+        }
+        putZzMileages(lc, 0.0, zhlist, zhlistXY, relist, type);
+        if (b != 0) {
+            putZzMileages(lc, -b, zhlist, zhlistXY, relist, type);
+            putZzMileages(lc, b, zhlist, zhlistXY, relist, type);
+        }
+    }
+
+    private static void putZzMileages(double lc,double b,List<Mileage> zhlist,List<Mileagexy> zhlistXY,List<Mileage> relist,int type){
+
+        double[] xy=null;
+        if(type==0) {
+            xy = azimuthZb(lc, b, 90, zhlist);
+        }else{
+            xy = azimuthZbXy(lc, b, 90, zhlistXY);
+        }
+        if(xy!=null) {
+            Mileage zzMileage = new Mileage(lc, xy[0], xy[1], 0, 0);
+            zzMileage.setB(b);
+            relist.add(zzMileage);
+        }
+    }
+
+    public static String[] azimuthLC(double x, double y,double jj, Mileage mileage,List<Mileage> mileages,List<Mileagexy> mileagexys,double ty) {
+        String[] res = new String[2];
+        double dx, dy,angle;
+        dx = x - mileage.getX();
+        dy = y -mileage.getY() ;
+        //计算方位角
+        double yx = dy / dx;
+        double yx1 = dy / dx;
+        if (yx < 0) {
+            yx = -yx;
+        }
+
+        angle = Math.atan(yx);
+        angle = angle * (180 / Math.PI);
+        if (dx > 0 && dy >= 0) {
+        } else if (dx < 0 && dy >= 0) {
+            angle = 180 - angle;
+        } else if (dx < 0 && dy < 0) {
+            angle = 180 + angle;
+        } else if (dx > 0 && dy < 0) {
+            angle = 360 - angle;
+        }else if (dx == 0 && dy > 0) {
+            angle = 90;
+        }else if (dx == 0 && dy < 0) {
+            angle = 270;
+        }
+        double ab = Math.sqrt(dx * dx + dy * dy);
+        double bc= dy/Math.sin((mileage.getAngle()+jj)* Math.PI/180);
+        double bd= dx/Math.cos((mileage.getAngle()+jj)* Math.PI/180);
+
+        double lcc= ab*Math.sin((angle-mileage.getAngle()-jj)* Math.PI/180);
+        if((angle-mileage.getAngle()-jj)<ty){
+            if(lcc<0){
+                lcc=lcc*-1;
+            }
+
+        }else{
+            if(ty<0&&lcc>0){
+                lcc=lcc*-1;
+            }
+            if(ty>0&&lcc<0){
+                lcc=lcc*-1;
+            }
+        }
+        ty=angle-mileage.getAngle()-jj;
+        double aaa=  NumberUtil.round(bd, 5)*100000-NumberUtil.round(bc, 5)*100000;
+        if(aaa<0){
+            aaa=-aaa;
+        }
+        double aa=  NumberUtil.round(ab, 5)*100000-NumberUtil.round(bc, 5)*100000;
+        if(bc<0){
+            aa= NumberUtil.round(ab, 5)*100000+NumberUtil.round(bc, 5)*100000;
+        }
+
+        if(aa<0){
+        aa=-aa;
+        }
+
+        if((aa<10&&aaa<10)||(aaa==0)){
+            res[0]= String.valueOf(NumberUtil.round(mileage.getValue(),4));
+            if(bc>0&&bc<0.001){
+                res[1]="0.0001";
+            }else{
+                res[1]= String.valueOf(NumberUtil.round(bc,4));
+            }
+    }else{
+            if(ab>20){
+                lcc=ab;
+            }
+
+            double  lc=NumberUtil.round(mileage.getValue(), 4)+lcc;
+                double[] acm =null;
+            if(mileages!=null){
+                acm = azimuthZb(lc,0,jj,mileages)  ;
+            }else{
+                acm = azimuthZbXy(lc,0,jj,mileagexys)  ;
+            }
+
+                if(acm==null){
+                return null;
+                }
+            Mileage m=new Mileage();
+                m.setX(acm[0]);
+                m.setY(acm[1]);
+                m.setAngle(acm[2]);
+                m.setValue(lc);
+
+            res=  azimuthLC(x,y,jj,m,mileages,mileagexys,ty);
+
+//
+
+        }
+
+        return res;
+    }
+
+    public static void main(String[] srt){
+        Mileage mm=new Mileage();
+        mm.setAngle(30.331496472222224);
+        mm.setX(2864425.47798996);
+        mm.setY(37385681.63883557);
+        mm.setValue(5531.690890000001);
+
+        List<Mileagexy> mileagexys =new ArrayList<>();
+        Mileagexy m=new Mileagexy();
+        m.setAngle(30.331496472222224);
+        m.setX(2864425.47798996);
+        m.setY(37385681.63883557);
+        m.setValue(5531.690890000001);
+        m.setValueEnd(5581.690890000001);
+        m.setType(2);
+        m.setR(148.7839);
+        m.setL(50.0);
+        m.setSwing("左转");
+        mileagexys.add(m);
+        Mileagexy m1=new Mileagexy();
+        m1.setAngle(31.698597055555556);
+        m1.setX(2864282.57129165);
+        m1.setY(37385595.72074135);
+        m1.setValue(5364.940890000001);
+        m1.setValueEnd(5531.690890000001);
+        m1.setType(1);
+        m1.setR(6988.565);
+        m1.setL(166.75);
+        m1.setSwing("左转");
+        mileagexys.add(m1);
+        Mileagexy m2=new Mileagexy();
+        m2.setAngle(20.70414775);
+        m2.setX(2864469.92360773);
+        m2.setY(37385704.4054703);
+        m2.setValue(5581.690890000001);
+        m2.setValueEnd(5634.416790000001);
+        m2.setType(1);
+        m2.setR(148.7839);
+        m2.setL(52.7259);
+        m2.setSwing("左转");
+        mileagexys.add(m2);
+        String[] res = azimuthLC(2864441.350,37385690.766,90,mm,null,mileagexys,0);
+//        mileagexy.setAngle(a - b03);
+        System.out.println(res[0]);
+        System.out.println(res[1]);
+//        System.out.println(Math.sin(90* Math.PI/180));
+//        System.out.println(Math.sin(0* Math.PI/180));
+//       System.out.println(NumberUtil.sub(1.99951*100000, 1.99956*100000)/100000);
+//        System.out.println(1.999519877503401*100000-1.999519877503401*100000);
+//        System.out.println(NumberUtil.round(1.9995670643507062*100000, 5)-NumberUtil.round(1.999519877503401*100000, 4));
+//        BigDecimal b1 = new BigDecimal(Double.toString(1.99971*100000));
+//        BigDecimal b2 = new BigDecimal(Double.toString(1.99956*100000));
+//        System.out.println( b1.subtract(b2).floatValue());
+
+    }
+
+}
+

+ 459 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/utils/NumberUtil.java

@@ -0,0 +1,459 @@
+package org.springblade.business.utils;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.math.BigDecimal;
+import java.text.DecimalFormat;
+import java.util.regex.Pattern;
+
+/**
+ *
+ * 数字类型操作相关的公共方法
+ *
+ * @author huangjy
+ *
+ */
+
+public class NumberUtil {	
+    private static Log log = LogFactory.getLog(NumberUtil.class);
+	private static final String zhnum_0 = "零壹贰叁肆伍陆柒捌玖";
+	private static final String zhnum = "零一二三四五六七八九";
+	private static final String[] zhnum1 = {"","十","百","千"};
+	private static final String[] zhnum1_0 = {"","拾","佰","仟"};
+	private static final String[] zhnum2 = {"","万","亿","万亿","亿亿"};
+    private static final int DEFAULT_PRICESION = 3;
+
+	/**
+	 * 判断字符串是否为数字
+	 * @param str
+	 * @return
+	 */
+	public static boolean isNumeric(String str){ 
+	    Pattern pattern = Pattern.compile("[0-9.]*");
+	    return pattern.matcher(str).matches();    
+	 } 
+	
+    public static short parseShort(String pValue) {
+        if(pValue == null) return 0;
+        try {
+            return Short.parseShort(pValue);
+        } catch (Exception ex) {
+            log.error(ex);
+            return 0;
+        }
+    }
+
+    public static Short parseShortObj(String pValue) {
+        if(pValue == null) return null;
+        try {
+            return new Short(Short.parseShort(pValue));
+        } catch (Exception ex) {
+            log.error(ex);
+            return null;
+        }
+    }
+
+
+    public static int parseInt(String pValue) {
+        if(pValue == null) return 0;
+        try {
+            return Integer.parseInt(pValue);
+        } catch (Exception ex) {
+            log.error(ex);
+            return 0;
+        }
+    }
+
+    public static Integer parseInteger(String pValue) {
+        if(pValue == null) return null;
+        try {
+            return new Integer(Integer.parseInt(pValue));
+        } catch (Exception ex) {
+            log.error(ex);
+            return null;
+        }
+    }
+
+
+    public static long parseLong(String pValue) {
+        if(pValue == null) return 0;
+        try {
+            return Long.parseLong(pValue);
+        } catch (Exception ex) {
+            log.error(ex);
+            return 0;
+        }
+    }
+
+    public static Long parseLongObj(String pValue) {
+        if(pValue == null) return null;
+        try {
+            return new Long(Long.parseLong(pValue));
+        } catch (Exception ex) {
+            log.error(ex);
+            return null;
+        }
+    }
+
+
+    public static double parseDouble(String pValue) {
+        if(pValue == null) return 0;
+        try {
+            return Double.parseDouble(pValue);
+        } catch (Exception ex) {
+            log.error(ex);
+            return 0;
+        }
+    }
+
+    public static Double parseDoubleObj(String pValue) {
+        if(pValue == null) return null;
+        try {
+            return Double.parseDouble(pValue);
+        } catch (Exception ex) {
+            log.error(ex);
+            return null;
+        }
+    }
+
+
+    // 按给定的格式格式化。
+    public static String format(double d, String pattern) {
+        DecimalFormat df = new DecimalFormat(pattern);
+        return df.format(d);
+    }
+    
+    public static String format(double d, String pattern, boolean showZero) {
+    	if(!showZero&&d==0){
+    		return "";
+    	}
+    	return format(d, pattern);
+    }
+    
+    // 按给定的格式格式化。
+    public static String format(Double d, String pattern) {
+        if(d != null) {
+            return format(d.doubleValue(), pattern);
+        }else {
+            return null;
+        }
+    }
+
+    public static String format(Double d, String pattern, boolean showZero) {
+    	if(!showZero&&d==0){
+    		return "";
+    	}
+    	return format(d, pattern);
+    }
+    
+    // 指定精度格式化字符串, 不显示末尾多余的0。
+    public static String format(double d, int precision) {
+        if (precision < 0) {
+            return String.valueOf(d);
+        }
+        StringBuffer sb = new StringBuffer("#");
+        if (precision > 0) {
+            sb.append(".");
+        }
+        for (int i = 0; i < precision; i++) {
+            sb.append("#");
+        }
+        return format(d, sb.toString());
+    }
+    
+    public static String format(double d, int precision, boolean showZero) {
+    	if(!showZero&&d==0){
+    		return "";
+    	}
+    	return format(d, precision);
+    }
+    
+    // 指定精度格式化字符串, 不显示末尾多余的0。
+    public static String format(Double d, int precision) {
+        if(d != null) {
+            return format(d.doubleValue(), precision);
+        }else {
+            return null;
+        }
+    }
+
+    public static String format(Double d, int precision, boolean showZero) {
+    	if(!showZero&&d==0){
+    		return "";
+    	}
+    	return format(d, precision);
+    }
+    
+    // 指定精度格式化字符串, 不删除后面的0。 如果不够用0补齐。
+    public static String forcibleFormat(double d, int precision) {
+        if (precision < 0) {
+            return String.valueOf(d);
+        }
+        StringBuffer sb = new StringBuffer("#");
+        if (precision > 0) {
+            sb.append(".");
+        }
+        for (int i = 0; i < precision; i++) {
+            sb.append("0");
+        }
+        return format(d, sb.toString());
+    }
+    
+    public static String forcibleFormat(double d, int precision, boolean showZero) {
+    	if(!showZero&&d==0){
+    		return "";
+    	}
+    	return forcibleFormat(d, precision);
+    }
+    
+    // 指定精度格式化字符串, 不删除后面的0。 如果不够用0补齐。
+    public static String forcibleFormat(Double d, int precision) {
+        if(d != null) {
+            return forcibleFormat(d.doubleValue(), precision);
+        }else {
+            return null;
+        }
+    }
+
+    public static String forcibleFormat(Double d, int precision, boolean showZero) {
+    	if(!showZero&&d==0){
+    		return "";
+    	}
+    	return forcibleFormat(d, precision);
+    }
+    
+    // 四舍五入.
+    public static double round(double d, int precision) {
+        //return parseDouble(format(d, precision));
+    	//return Math.round(d * Math.pow(10, precision))/Math.pow(10, precision);
+    	
+    	//由于BigDecimal(double val) 方法不精确,把double转成String再传进去    	
+    	BigDecimal bd = new BigDecimal(Double.toString(d));
+		bd = bd.setScale(precision, BigDecimal.ROUND_HALF_UP);
+		return bd.doubleValue();
+    }
+    
+    // 四舍五入.
+    public static Double round(Double d, int precision) {
+        if(d != null) {
+            return new Double(round(d.doubleValue(), precision));
+        }else {
+            return null;
+        }
+    }
+
+    public static int intValue(Integer integer) {
+        if (integer != null) {
+            return integer.intValue();
+        } else {
+            return 0;
+        }
+    }
+
+    public static double doubleValue(Double d) {
+        if (d != null) {
+            return d.doubleValue();
+        } else {
+            return 0;
+        }
+    }
+    
+    /**
+	 * double 与 double 相加
+	 * 
+	 * @param v1
+	 * @param v2
+	 * @return
+	 */
+	public static double add(double v1, double v2) {
+		BigDecimal b1 = new BigDecimal(Double.toString(v1));
+		BigDecimal b2 = new BigDecimal(Double.toString(v2));
+		return b1.add(b2).doubleValue();
+	}
+
+	/**
+	 * double 与 double 相减
+	 * 
+	 * @param v1
+	 * @param v2
+	 * @return
+	 */
+	public static double sub(double v1, double v2) {
+		BigDecimal b1 = new BigDecimal(Double.toString(v1));
+		BigDecimal b2 = new BigDecimal(Double.toString(v2));
+		return b1.subtract(b2).doubleValue();
+	}
+
+	/**
+	 * double 与 double 相乘
+	 * 
+	 * @param v1
+	 * @param v2
+	 * @return
+	 */
+	public static double mul(double v1, double v2) {
+		BigDecimal b1 = new BigDecimal(Double.toString(v1));
+		BigDecimal b2 = new BigDecimal(Double.toString(v2));
+		return b1.multiply(b2).doubleValue();
+	}
+
+	/**
+	 * double 与 double 相除
+	 * 
+	 * @param v1
+	 * @param v2
+	 * @return
+	 */
+	public static double div(double v1, double v2) {
+		BigDecimal b1 = new BigDecimal(Double.toString(v1));
+		BigDecimal b2 = new BigDecimal(Double.toString(v2));
+		return b1.divide(b2, DEFAULT_PRICESION, BigDecimal.ROUND_HALF_UP).doubleValue();
+	}
+	
+	/**
+	 * 返回double
+	 * 
+	 * @param v
+	 * @return
+	 */
+	public static double round(double d) {
+		return round(d, DEFAULT_PRICESION);
+	}
+
+	 /**
+     * 将 1 组 4 位的数字转换成中文
+     * 返回格式为“几千几百几十几”的格式
+     */
+    private static String numberToZH4(String s,boolean fan){
+        StringBuffer sb = new StringBuffer(256);
+        if (s.length()!=4) return null;
+        for (int i=0;i<4;i++){
+            char c1 = s.charAt(i);
+            // 去掉重复的“零”
+            if (c1=='0' && i>1 && s.charAt(i-1)=='0')  continue;
+            if (c1!='0' && i>1 && s.charAt(i-1)=='0') sb.append('零');
+            if (c1!='0') {
+                if (fan) {
+                    //大写
+                    sb.append(zhnum_0.charAt(c1-48)); //数字
+                    sb.append(zhnum1_0[4-i-1]); // 数量级:千、百、十
+                } else {
+                    //小写
+                    sb.append(zhnum.charAt(c1-48));//数字
+                    sb.append(zhnum1[4-i-1]);// 数量级:千、百、十
+                }
+            }
+        }
+        return new String(sb);
+    }
+    
+    /**
+     * 将一个 long 数字转换为汉字
+     *
+     * @param n 要转换的 long 类型的数字
+     * @param fan 如果此参数true,数字将被转换为中文大写,否则转换为中文小写
+     * @return 参数 n 的汉字格式
+     */
+    public static String numberToZH(long n,boolean fan){
+        StringBuffer sb = new StringBuffer(16);
+        // 把 long 转换为字符串,且使它的长度是 4 的倍数 
+        
+        String strN = "000"+(n<0?-n:n);
+        int strN_L = strN.length()/4;
+        strN = strN.substring(strN.length()-strN_L*4);
+        // 中文数字是每 4 位为 1 组,所以,要一组一组地转换。
+        for (int i=0;i<strN_L;i++){
+            String s1 = strN.substring(i*4,i*4+4);
+            String s2 = numberToZH4(s1,fan);
+            //转换一组
+            sb.append(s2); 
+            // 该组的数量级:“亿亿、万亿、亿、万”,由循环变量 i 控制,从 zhnum2 串数组里取得
+            if(s2.length()!=0) sb.append(zhnum2[strN_L-i-1]);
+        }
+        String s = new String(sb);
+        // 去掉中文数字的前导“零”
+        if (s.length()!=0 && s.startsWith("零"))
+            s = s.substring(1);
+        if(s.length()==3 && s.charAt(1)=='十' && s.charAt(0)=='一')
+        	s = s.substring(s.length()-2);
+        if(n<0)
+        	s = "负" + s;
+        return s;
+    }
+    /**
+     * 将一个 double 数字转换为汉字
+     *
+     * @param d 要转换的 double 类型的数字
+     * @param fan 如果此参数true,数字将被转换为中文大写,否则转换为中文小写
+     *@return 参数 d 的汉字格式
+     */
+    public static String numberToZH(double d,boolean fan){
+        return numberToZH("" + d,fan);
+    }
+    
+    /**
+     * 将一个字符串数字转换为汉字
+     *
+     * @param str 要转换的 String 类型的数字字符串
+     * @param fan 如果此参数true,数字将被转换为中文大写,否则转换为中文小写
+     * @return 参数 str 的汉字格式
+     */
+    public static String numberToZH(String str,boolean fan){
+        StringBuffer sb = new StringBuffer(16);
+        int dot = str.indexOf(".");
+        if (dot<0) dot=str.length();
+        
+        // 取出整数部分,由 String numberToZH(long n,boolean fan) 处理
+        String zhengshu = str.substring(0,dot);
+        sb.append(numberToZH(Long.parseLong(zhengshu),fan));
+        
+        // 小数部分
+        if (dot!=str.length()){
+            sb.append("点");
+            String xiaoshu = str.substring(dot+1);
+            for (int i=0;i<xiaoshu.length();i++){
+                if(fan){
+                    sb.append(zhnum_0.charAt(Integer.parseInt(xiaoshu.substring(i,i+1))));
+                } else {
+                    sb.append(zhnum.charAt(Integer.parseInt(xiaoshu.substring(i,i+1))));
+                }
+            }
+        }
+        String s = new String(sb);
+        if (s.startsWith("零")) s = s.substring(1);
+        // 中文小写 以“一十”开头的,去掉前面的“一”,
+        // 中文大写 以“壹拾”开头的,不作处理。
+        if (s.startsWith("一十")) s = s.substring(1);
+        // 去掉末尾的“零”
+        while (s.endsWith("零")){s = s.substring(0,s.length()-1);}
+        if (s.endsWith("点")) s = s.substring(0,s.length()-1);
+        return s;
+    }
+    
+    /**
+     * 将一个 double 数字转换为人民币大写的汉字格式
+     *
+     * @param rmb 要转换的 double 类型的数字
+     * @return 参数 rmb 的人民币大写汉字格式
+     */
+    public static String numberToRMB(double rmb){
+        // 这段 不用解释了吧
+        String strRMB = "" + rmb;
+        DecimalFormat nf = new DecimalFormat("#.#");
+        nf.setMaximumFractionDigits(2);
+        strRMB=nf.format(rmb).toString();
+        strRMB=numberToZH(strRMB,true);
+        if (strRMB.indexOf("点")>=0){
+            strRMB = strRMB + "零";
+            strRMB = strRMB.replaceAll("点","圆");
+            String s1 = strRMB.substring(0,strRMB.indexOf("圆")+1);
+            String s2 = strRMB.substring(strRMB.indexOf("圆")+1);
+            strRMB=s1 + s2.charAt(0) + "角" + s2.charAt(1) + "分整";
+        }else {
+            strRMB=strRMB+"圆整";
+        }
+        return "人民币(大写):" + strRMB;
+    }
+
+}

+ 28 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/MileageVo.java

@@ -0,0 +1,28 @@
+package org.springblade.business.vo;
+
+import lombok.Data;
+import org.springblade.business.utils.MileageUtill;
+import org.springblade.business.utils.NumberUtil;
+
+/**
+ * @author yangyj
+ * @Date 2022/6/2 14:04
+ * @description TODO
+ */
+@Data
+public class MileageVo {
+    private Double value=0.0;
+    private Double x=0.0;
+    private Double y=0.0;
+    private Double b=0.0;//偏移
+    private Double jj=90.0;//夹角
+    public String getValueStr() {
+        return MileageUtill.convertToMileage(value);
+    }
+    public String getXxStr() {
+        return NumberUtil.forcibleFormat(x,3);
+    }
+    public String getYyStr() {
+        return NumberUtil.forcibleFormat(y,3);
+    }
+}

+ 4 - 0
blade-service/blade-business/pom.xml

@@ -46,6 +46,10 @@
             <groupId>org.springblade</groupId>
             <artifactId>blade-core-cloud</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+        </dependency>
     </dependencies>
 
 </project>

+ 297 - 0
blade-service/blade-business/src/main/java/org/springblade/business/controller/MileageController.java

@@ -0,0 +1,297 @@
+package org.springblade.business.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import io.swagger.annotations.Api;
+import lombok.AllArgsConstructor;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.springblade.business.entity.Mileage;
+import org.springblade.business.entity.MileagePart;
+import org.springblade.business.entity.Mileagexy;
+import org.springblade.business.service.impl.MileagePartService;
+import org.springblade.business.service.impl.MileagexyService;
+import org.springblade.business.utils.MileageUtill;
+import org.springblade.business.vo.MileageVo;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.secure.utils.AuthUtil;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.CollectionUtil;
+import org.springblade.core.tool.utils.Func;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.math.BigDecimal;
+import java.net.URLEncoder;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.regex.Pattern;
+
+/**
+ * @author yangyj
+ * @Date 2022/5/31 11:02
+ * @description TODO
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/mileage")
+@Api(tags = "平曲线接口")
+public class MileageController {
+    private final MileagePartService partService;
+    private final MileagexyService service;
+
+
+
+    @GetMapping("/part/list")
+    public R<List<MileagePart>> plist(@RequestParam Map<String, Object> part) {
+        List<MileagePart> list = partService.list(Condition.getQueryWrapper(part, MileagePart.class).lambda().orderByDesc(MileagePart::getCreateTime));
+        return R.data(list);
+    }
+
+
+
+//    @GetMapping("/part/list")
+//    public R<List<MileagePart>> list( String contractId) {
+//        List<MileagePart> data=partService.getBaseMapper().selectList(Wrappers.<MileagePart>query().lambda().eq(MileagePart::getContractId,contractId));
+//        return R.data(data);
+//    }
+
+
+
+    @PostMapping("/part/add")
+    public R<MileagePart> add (@RequestBody MileagePart part){
+        part.setCreateUser(AuthUtil.getUserId());
+        this.partService.save(part);
+        return R.data(part);
+    }
+
+
+    @PostMapping("/part/update")
+    public R<String> upDate ( MileagePart part){
+         MileagePart old = partService.getById(part.getId());
+        //同步更新片段信息
+        if(!old.getPrefix().equals(part.getPrefix())){
+            this.partService.updatePart(old.getProjectId(),old.getPrefix(),part.getPrefix());
+        }
+        old.setName(part.getName());
+        old.setPrefix(part.getPrefix());
+        old.setRemark(part.getRemark());
+        this.partService.updateById(old);
+        return R.success("更新成功");
+    }
+
+    @PostMapping("/part/del")
+    public R<String> partDel(String ids){
+        return R.status(partService.removeByIds(Func.toLongList(ids)));
+    }
+
+
+
+    @GetMapping("pschange")
+    public R<MileageVo> coordinate(String b , String value, String jj, String projId, String partId) {
+        double[] aa= MileageUtill.azimuthZbXy(Double.parseDouble(value),Double.parseDouble(b),Double.parseDouble(jj),this.service.list(Wrappers.<Mileagexy>query().lambda().eq(Mileagexy::getPartId,partId).eq(Mileagexy::getProjectId,projId)));
+        if(aa==null){
+            return null;
+        }
+        MileageVo vo = new MileageVo();
+        vo.setX(Double.parseDouble(String.format("%.3f",aa[0])));
+        vo.setValue(Double.parseDouble(value));
+        vo.setB(Double.parseDouble(b));
+        vo.setJj(Double.parseDouble(jj));
+        vo.setY(Double.parseDouble(String.format("%.3f",aa[1])));
+        return R.data(vo);
+    }
+
+    @PostMapping("/import")
+    public R importXy(@RequestParam("file") MultipartFile file, String projectId,String partId ) throws Exception {
+        if(file != null&&Func.isNotEmpty(partId)) {
+            if(Pattern.matches(".+(\\.xls)x?$", Objects.requireNonNull(file.getOriginalFilename()).toLowerCase(Locale.ROOT))) {
+             return   R.success(this.service.importMileagexy(file,AuthUtil.getUserId(),projectId,partId));
+            } else {
+               return   R.fail("文件格式不正确,请上传Excel文件");
+            }
+        }
+        return R.fail("文件或片段不存在");
+    }
+
+
+
+//    @ResponseBody
+//    @RequestMapping(value="/list",method= RequestMethod.POST)
+//    public R<Object> list(HttpServletRequest request, String projectId, String partNo, String partId, RequestPage page){
+//        Long  userid = AuthUtil.getUserId();
+//        Map<String, Object> param = new HashMap<String, Object>();
+//        param.put("partId",partId);
+//        param.put("deleted",0);
+//        param.put("projId", projectId);
+//        this.service
+//        result =mileagexyService.List(param,page.getStartNum(), page.getPageSize());
+//        return result;
+//    }
+    @GetMapping("/list")
+    public R<IPage<Mileagexy>> page(@RequestParam Map<String, Object> param, Query query) {
+        IPage<Mileagexy> pages = service.page(Condition.getPage(query), Condition.getQueryWrapper(param, Mileagexy.class));
+        return R.data(pages);
+    }
+
+
+    @PostMapping("/add")
+    public R<Mileagexy> add (@RequestBody Mileagexy mileagexy){
+        mileagexy.setUpdateUser(AuthUtil.getUserId());
+        mileagexy.setProjectId("");
+        mileagexy.setCreateTime(new Date());
+        mileagexy.setPartNo(mileagexy.getPartNo());
+        mileagexy.setValueEnd(mileagexy.getValue()+mileagexy.getL());
+        //必须要设置angle
+        mileagexy.setAngle(mileagexy.getDu()+Double.valueOf(mileagexy.getFen())/60+mileagexy.getMiao()/3600);
+        this.service.save(mileagexy);
+        return R.data(mileagexy);
+    }
+
+
+
+    @PostMapping("/del")
+    public R<String> del(String id){
+        if(service.removeById(id)){
+            return R.data("删除成功");
+        }else{
+            return R.fail("删除失败");
+        }
+    }
+
+
+
+    @PostMapping("/find")
+    public R<Mileagexy> find(String id){
+        return  R.data(service.getById(id));
+    }
+
+
+
+
+    @PostMapping("/update")
+    public R<Boolean> upDate (@RequestBody Mileagexy mileagexy){
+        Mileagexy old = service.getById(mileagexy.getId());
+        old.setPartNo(mileagexy.getPartNo());
+        old.setCreateTime(mileagexy.getCreateTime());
+        old.setPartId(mileagexy.getProjectId());
+        old.setValueEnd(mileagexy.getValue()+mileagexy.getL());
+        //必须要设置angle
+        old.setAngle(mileagexy.getDu()+ Double.valueOf(mileagexy.getFen())/60+mileagexy.getMiao()/3600);
+        return R.status(this.service.updateById(old));
+    }
+
+
+    @PostMapping("/getNextMileagexy")
+    public Mileagexy  getNextMileagexy(@RequestBody Mileagexy mileagexy) {
+        Mileagexy nextmileagexy =new Mileagexy();
+        Mileagexy max=service.getMaxMileagexy(mileagexy.getPartId(),0,mileagexy.getProjectId(),mileagexy.getOrderNum());
+        if(max!=null){
+            MileageUtill.initMileagexy(max,nextmileagexy);
+            nextmileagexy.setR(max.getR());
+            nextmileagexy.setSwing(max.getSwing());
+        }
+        return nextmileagexy;
+    }
+
+
+    @GetMapping("getZzList")
+    public R<List<Mileage>> getZzList(Mileage mileage) {
+        List<Mileage> mileages = new ArrayList<>(MileageUtill.azimuthZzZbXy(mileage.getX(), mileage.getY(), mileage.getValue(), mileage.getB(), this.service.list(Wrappers.<Mileagexy>query().lambda().eq(Mileagexy::getPartId,mileage.getPartId()).eq(Mileagexy::getProjectId,mileage.getProjId()).orderByAsc(Mileagexy::getOrderNum))));
+         if(CollectionUtil.isNotEmpty(mileages)){
+            return R.data(mileages);
+         }
+        return R.fail("暂无数据");
+    }
+
+
+    @GetMapping("exportExcel")
+    public boolean  exportExcel(HttpServletResponse response, String projectId , String partId, String partNo) throws IOException {
+        LambdaQueryWrapper<Mileagexy> queryWrapper = Wrappers.<Mileagexy>query().lambda();
+        queryWrapper.eq(Mileagexy::getPartId,partId).eq(Mileagexy::getProjectId,projectId);
+        List<Mileagexy> mileagexyData = this.service.list(queryWrapper);
+        //创建HSSFWorkbook对象(excel的文档对象)
+        HSSFWorkbook wb = new HSSFWorkbook();
+        //创建sheet对象(excel的表单)
+        HSSFSheet sheet=wb.createSheet("操作日志列表");
+
+        //创建第一行,这里即是表头。行的最小值是0,代表每一行,上限没研究过,可参考官方的文档
+        HSSFRow row1=sheet.createRow(0);
+        //在这一行创建单元格,并且将这个单元格的内容设为“账号”,下面同理。
+        //列的最小值标识也是0
+        row1.createCell(0).setCellValue("序号");
+        row1.createCell(1).setCellValue("里程");
+        row1.createCell(2).setCellValue("排序");
+        row1.createCell(3).setCellValue("长度");
+        row1.createCell(4).setCellValue("方位角");
+        row1.createCell(5).setCellValue("类型");
+        row1.createCell(6).setCellValue("转向");
+        row1.createCell(7).setCellValue("x");
+        row1.createCell(8).setCellValue("y");
+        row1.createCell(9).setCellValue("半径");
+        for (int i = 0; i < mileagexyData.size(); i++) {
+            HSSFRow row=sheet.createRow(i+1);
+            row.createCell(0).setCellValue(i+1);
+            row.createCell(1).setCellValue(valuetoStr(mileagexyData.get(i).getValue(),partNo) +'~'+valuetoStr(mileagexyData.get(i).getValueEnd(),partNo));
+            row.createCell(2).setCellValue(mileagexyData.get(i).getOrderNum());
+            row.createCell(3).setCellValue(mileagexyData.get(i).getL());
+            row.createCell(4).setCellValue(mileagexyData.get(i).getAngle());
+            row.createCell(5).setCellValue(mileagexyData.get(i).getType());
+            row.createCell(6).setCellValue(mileagexyData.get(i).getSwing());
+            row.createCell(7).setCellValue(mileagexyData.get(i).getX());
+            row.createCell(8).setCellValue(mileagexyData.get(i).getY());
+            row.createCell(9).setCellValue(mileagexyData.get(i).getR());
+
+        }
+        //输出Excel文件
+        OutputStream output=response.getOutputStream();
+        response.reset();
+        Date dt = new Date();
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss");
+        // 文件名
+        String fileName = sdf.format(dt)+"平曲线.xls";
+        response.setContentType("application/x-msdownload");
+        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
+        wb.write(output);
+        output.close();
+        return true;
+    }
+    public String valuetoStr(Double num,String partNo) {
+        String preffix = "000";
+        String xstr="";
+        String ystr="";
+        double x = Math.floor(num/1000);
+        if(x<0){
+            x=0;
+        }
+        xstr = x+"";
+        if (Math.round(x) - x == 0) {
+            xstr=(long) x+"";
+        }
+        BigDecimal bg = new BigDecimal(num%1000).setScale(3, BigDecimal.ROUND_HALF_UP);
+        double y = bg.doubleValue();
+        String sign=y<0?"-":"+";
+        ystr = y+"";
+        if (Math.round(y) - y == 0) {
+            ystr = ""+(long) y;
+        }
+        if(ystr.length() <= 3|| ystr.indexOf('.')<=3){
+            int len =0;
+            if(ystr.indexOf('.')>-1){
+                len=ystr.indexOf('.');
+            }else{
+                len=ystr.length();
+            }
+            ystr=""+preffix.substring(0,preffix.length()-len)+ystr;
+
+        }
+        return partNo+'K'+xstr+sign+ystr;
+    }
+
+
+}

+ 11 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/MileagePartMapper.java

@@ -0,0 +1,11 @@
+package org.springblade.business.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springblade.business.entity.MileagePart;
+
+/**
+ * @author yangyj
+ */
+public interface MileagePartMapper extends BaseMapper<MileagePart> {
+    void updateByProjectIdAndPrefix(String projectId ,String partNo ,String newpartno);
+}

+ 32 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/MileagePartMapper.xml

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.springblade.business.mapper.MileagePartMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="mileagePartResultMap" type="org.springblade.business.entity.MileagePart">
+        <result column="id" property="id"/>
+        <result column="createUser" property="create_user"/>
+        <result column="createDept" property="create_dept"/>
+        <result column="createTime" property="create_time"/>
+        <result column="updateUser" property="update_user"/>
+        <result column="updateTime" property="update_time"/>
+        <result column="status" property="status"/>
+        <result column="isDeleted" property="is_deleted"/>
+        <result column="tenantId" property="tenant_id"/>
+        <result column="name" property="name"/>
+        <result column="prefix" property="prefix"/>
+        <result column="remark" property="remark"/>
+        <result column="contractId" property="contract_id"/>
+        <result column="projectId" property="project_id"/>
+        <result column="sort" property="sort"/>
+    </resultMap>
+
+    <update id="updateByProjectIdAndPrefix">
+         update t_om_mileagexy set partno =#{newpartno}
+          where
+          AND project_id = #{projectId}
+          AND prefix = #{partNo}
+    </update>
+
+
+</mapper>

+ 17 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/MileagexyMapper.java

@@ -0,0 +1,17 @@
+package org.springblade.business.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
+import org.springblade.business.entity.Mileagexy;
+
+import java.util.List;
+
+
+/**
+ * @author yangyj
+ */
+public interface MileagexyMapper extends BaseMapper<Mileagexy> {
+
+   List<Mileagexy> getLast(@Param("partId") String partId,@Param("projectId") String projectId,@Param("orderNum") Integer orderNum);
+
+}

+ 49 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/MileagexyMapper.xml

@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.springblade.business.mapper.MileagexyMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="mileagexyResultMap" type="org.springblade.business.entity.Mileagexy">
+        <result column="id" property="id"/>
+        <result column="createUser" property="create_user"/>
+        <result column="createDept" property="create_dept"/>
+        <result column="createTime" property="create_time"/>
+        <result column="updateUser" property="update_user"/>
+        <result column="updateTime" property="update_time"/>
+        <result column="status" property="status"/>
+        <result column="isDeleted" property="is_deleted"/>
+        <result column="tenantId" property="tenant_id"/>
+        <result column="projectId" property="project_id"/>
+        <result column="notes" property="notes"/>
+        <result column="code" property="code"/>
+        <result column="value" property="value"/>
+        <result column="x" property="x"/>
+        <result column="y" property="y"/>
+        <result column="r" property="r"/>
+        <result column="r2" property="r2"/>
+        <result column="swing" property="swing"/>
+        <result column="l" property="l"/>
+        <result column="valueEnd" property="value_end"/>
+        <result column="orderNum" property="order_num"/>
+        <result column="type" property="type"/>
+        <result column="angle" property="angle"/>
+        <result column="du" property="du"/>
+        <result column="fen" property="fen"/>
+        <result column="miao" property="miao"/>
+        <result column="dlq" property="dlq"/>
+        <result column="dlh" property="dlh"/>
+        <result column="ids" property="ids"/>
+        <result column="partNo" property="part_no"/>
+        <result column="partId" property="part_id"/>
+        <result column="contractId" property="contract_id"/>
+    </resultMap>
+
+    <select id="getLast" resultMap="mileagexyResultMap">
+        select * from t_om_mileagexy  where partId = #{partId}   and project_id =#{projectId}
+        <if test="orderNum!=null and orderNum != ''">
+            and order_num = #{orderNum}
+        </if>
+        order by orderNum DESC
+    </select>
+
+</mapper>

+ 58 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/MileagePartService.java

@@ -0,0 +1,58 @@
+package org.springblade.business.service.impl;
+
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import org.springblade.business.entity.MileagePart;
+import org.springblade.business.mapper.MileagePartMapper;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.CollectionUtil;
+import org.springblade.core.tool.utils.StringUtil;
+import org.springframework.stereotype.Service;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author yangyj
+ */
+@Service
+public class MileagePartService extends BaseServiceImpl<MileagePartMapper, MileagePart>{
+
+
+
+    public void updatePart(String projectId ,String partNo ,String newPartNo){
+        baseMapper.updateByProjectIdAndPrefix(projectId,partNo,newPartNo);
+    }
+
+
+    public MileagePart getMileagePart(String projectId, String partNo){
+          MileagePart part = new MileagePart();
+          part.setPrefix(partNo);
+          part.setProjectId(projectId);
+          List<MileagePart> data= this.list(Wrappers.query(part));
+          if(CollectionUtil.isNotEmpty(data)){
+              return data.get(0);
+          }
+          return null;
+    }
+
+    public MileagePart getMileagePart(String projectId, String partNo ,String contractId){
+        MileagePart query = new MileagePart();
+        if(StringUtil.isNotBlank(partNo)){
+            query.setContractId(contractId);
+            query.setPrefix(partNo);
+        }else {
+            query.setProjectId(projectId);
+        }
+        List<MileagePart> parts =  this.list(Wrappers.query(query));
+        if(CollectionUtil.isNotEmpty(parts)){
+            return  parts.get(0);
+        }
+        return null;
+    }
+
+
+
+
+}

+ 173 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/MileagexyService.java

@@ -0,0 +1,173 @@
+package org.springblade.business.service.impl;
+
+
+import lombok.AllArgsConstructor;
+import org.apache.poi.hssf.usermodel.HSSFDataFormatter;
+import org.apache.poi.ss.usermodel.*;
+import org.springblade.business.entity.MileagePart;
+import org.springblade.business.entity.Mileagexy;
+import org.springblade.business.mapper.MileagexyMapper;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.core.tool.utils.StringUtil;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+@AllArgsConstructor
+public class MileagexyService  extends BaseServiceImpl<MileagexyMapper, Mileagexy> {
+
+    private  final MileagePartService partService;
+
+
+//    public R<IPage<Mileagexy>> list(Map<String, Object> MapParam, Integer start, Integer rows) {
+//        SmartResponse<Object> smartResp = new SmartResponse<Object>();
+//        smartResp.setResult(OP_NOT_DATA_SUCCESS);
+//        smartResp.setMsg(OP_NOT_DATA_SUCCESS_MSG);
+//        String sql =SQL_MLIST;
+//        try {
+//            if(StringUtils.isNotEmpty(sql)) {
+//                long totalNum = getOPDao().count(sql,MapParam);
+//                if(start<=totalNum) {
+//                    List<Object> objs = getOPDao().queryMapDatas(sql,MapParam, start, rows);
+//                    if(null != objs && objs.size()>0) {
+//                        smartResp.setResult(OP_SUCCESS);
+//                        smartResp.setMsg(OP_SUCCESS_MSG);
+//                        smartResp.setDatas(objs);
+//                        smartResp.setPerPageSize(rows);
+//                        smartResp.setTotalNum(totalNum);
+//                        smartResp.setTotalPage(PageHelper.getTotalPage(totalNum, rows));
+//                        smartResp.setSize(objs.size());
+//                    }
+//                }
+//            }
+//        } catch (DaoException e){
+//            e.printStackTrace();
+//        } catch (Exception e){
+//            e.printStackTrace();
+//        }
+//        return smartResp;
+//    }
+//
+
+
+//    public List<Mileagexy> getlist(String partId,Integer deleted,String projId) {
+////        String sql = "select * from t_om_mileagexy  where partId = :partId  and  deleted=:deleted and projId=:projId order by orderNum ASC";
+//        HashMap<String, Object> map = new HashMap<>();
+//        map.put("partId",partId);
+//        map.put("deleted",deleted);
+//        map.put("projId",projId);
+//        List<Mileagexy> result = this.mileagexyDao.queryByField(map,"orderNum ASC");
+////        List<Mileagexy> result = getDao().querySqlToEntity(sql, map,Mileagexy.class);
+//        return result;
+//    }
+
+
+    public Integer toType(String value){
+        String[] keys={"直线段","圆曲线","入缓和曲线","出缓和曲线","不完整缓和曲线"};
+        for(int i=0;i<keys.length;i++){
+            if(value.equals(keys[i])){
+                return i;
+            }
+        }
+        return 0;
+    }
+    public static Object getValue(Cell cell) {
+        if(cell != null) {
+            switch(cell.getCellTypeEnum()){
+                case STRING:
+                    return cell.getStringCellValue()==null ? null : cell.getStringCellValue().trim();
+                case NUMERIC:
+                    HSSFDataFormatter dataFormatter = new HSSFDataFormatter();
+                    return dataFormatter.formatCellValue(cell);
+                case BOOLEAN:
+                    return cell.getBooleanCellValue();
+                case ERROR:
+                    return cell.getErrorCellValue();
+                case FORMULA:
+                    try {
+                        return cell.getStringCellValue();
+                    } catch (IllegalStateException e) {
+                        return cell.getNumericCellValue();
+                    }
+                default:
+                    cell.setCellType(CellType.STRING);
+                    return cell.getStringCellValue()==null ? null : cell.getStringCellValue().trim();
+            }
+        }
+        return null;
+    }
+
+
+    public String importMileagexy(MultipartFile file,Long userId,String projectId, String partId) throws Exception {
+        try {
+            Workbook wb = WorkbookFactory.create(file.getInputStream());
+            Sheet sheet = wb.getSheetAt(0);
+            List<Mileagexy> importList = new ArrayList<>();
+            MileagePart part = this.partService.getById(partId);
+            if(part==null){
+                return "所属片段不存在,请重新再试";
+            }
+            for (int i = 1; ; i++) {
+                Row row = sheet.getRow(i);
+                if(row == null) {
+                    break;
+                }
+                Mileagexy obj = new Mileagexy();
+                for(int j=0;j<14;j++){
+                    Object v=getValue(row.getCell(j));
+                    String value="0";
+                    if(v!=null){
+                         value = v.toString();
+                    }
+                    switch (j){
+                        case 0:obj.setType(toType(value));break;
+                        case 1:obj.setValue(Double.valueOf(value));break;
+                        case 2:obj.setX(Double.valueOf(value));break;
+                        case 3:obj.setY(Double.valueOf(value));break;
+                        case 4:obj.setR(Double.valueOf(value));break;
+                        case 5:if("无".equals(value)||"0".equals(value)){obj.setSwing("");}else{obj.setSwing((String) value);};break;
+                        case 6:obj.setL(Double.valueOf(value));break;
+                        case 7:obj.setDu(Integer.valueOf(value));break;
+                        case 8:obj.setFen(Integer.valueOf(value));break;
+                        case 9:obj.setMiao(Double.valueOf(value));break;
+                        case 10:obj.setDlq(Double.valueOf(value));break;
+                        case 11:obj.setDlh(Double.valueOf(value));break;
+                        case 12:obj.setR2(Double.valueOf(value));break;
+                        case 13:obj.setOrderNum(Integer.valueOf(value));break;
+                        default:break;
+                    }
+
+                }
+                obj.setUpdateUser(userId);
+                obj.setProjectId(projectId);
+                obj.setValueEnd(obj.getValue()+obj.getL());
+                obj.setPartId(partId);
+                obj.setPartNo(part.getPrefix());
+                //必须要设置angle
+                obj.setAngle(obj.getDu()+Double.valueOf(obj.getFen())/60+obj.getMiao()/3600);
+                importList.add(obj);
+            }
+            this.saveBatch(importList);
+              return  "导入成功";
+        } catch (Exception e){
+            e.printStackTrace();
+        }
+        return "导入失败";
+    }
+
+
+    public Mileagexy getMaxMileagexy(String partId,Integer deleted,String projId,Integer orderNum){
+        if(null!=orderNum&&orderNum>0){
+            orderNum--;
+        }
+        List<Mileagexy> result = this.baseMapper.getLast(partId,projId,orderNum);
+        if(result.size()>0){
+            return result.get(0);
+        }else{
+            return new Mileagexy();
+        }
+    }
+
+}

+ 179 - 0
blade-service/blade-business/src/main/java/org/springblade/business/utils/FunctionMain.java

@@ -0,0 +1,179 @@
+package org.springblade.business.utils;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import com.alibaba.fastjson.JSON;
+import net.bytebuddy.description.annotation.AnnotationDescription;
+import org.apache.http.Consts;
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.message.BasicNameValuePair;
+import org.springblade.business.entity.MileagePart;
+import org.springblade.business.entity.Mileagexy;
+import com.baomidou.mybatisplus.annotation.TableName;
+import javax.validation.constraints.Size;
+
+
+/**
+ * @author yangyj
+ * @Date 2022/5/30 15:20
+ * @description TODO
+ */
+public class FunctionMain {
+
+    public static Matcher matcher(String regex, String value) {
+        Pattern pattern = Pattern.compile(regex);
+        return pattern.matcher(value);
+    }
+    public static String toMapper(Class<?> clazz) {
+        StringBuilder sb = new StringBuilder();
+        Field[] fields = clazz.getDeclaredFields();
+        for (Field field:fields) {
+            field.setAccessible(true);
+            if(field.getModifiers()== (Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL)){
+                continue;
+            }
+            String property =field.getName();
+            String column=property;
+            String template="<result column=\"$1\" property=\"$2\"/>\n";
+            Matcher m = matcher("[A-Z]",column);
+            while (m.find()){
+                String re=m.group();
+                column=column.replace(re,"_"+re.toLowerCase(Locale.ROOT));
+            }
+            template= template.replace("$1",property).replace("$2",column);
+            sb.append(template);
+        }
+       return sb.toString();
+    }
+
+    public static List<Field> collect(Class<?> clazz){
+        Field[] fields = clazz.getDeclaredFields();
+        return Arrays.stream(fields).filter(e->e.getModifiers()!= (Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL)).collect(Collectors.toList());
+    }
+
+    public static List<Field>  collectChain(Class<?> clazz,boolean fi ) {
+        Class<?> su = clazz.getSuperclass();
+        if(su!=null&&!Object.class.toString().equals(su.getName())&&fi){
+            List<Field> total=new ArrayList<>();
+            total.addAll(collectChain(su, true));
+            total.addAll(collect(clazz));
+            return total;
+        }else{
+            return  collect(clazz);
+        }
+    }
+
+    public static String  builder(Class<?> clazz) {
+        Class<?> su = clazz.getSuperclass();
+        if(su!=null&&!Object.class.toString().equals(su.getName())){
+             return builder(su)+toMapper(clazz);
+        }else{
+             return  toMapper(clazz);
+        }
+    }
+    public static void getToken()  {
+        HttpClient httpClient = HttpClientBuilder.create().build();
+        HttpPost httpPost = new HttpPost("http://localhost/blade-auth/oauth/token");
+        httpPost.setHeader("Authorization","Basic c2FiZXI6c2FiZXJfc2VjcmV0");
+        httpPost.setHeader("Content-Type","application/x-www-form-urlencoded");
+        httpPost.setHeader("Tenant-Id","000000");
+        List<NameValuePair> params=new ArrayList<NameValuePair>();
+        params.add(new BasicNameValuePair("grant_type" , "password"));
+        params.add(new BasicNameValuePair("username" , "admin"));
+        params.add(new BasicNameValuePair("password" , "21232f297a57a5a743894a0e4a801fc3"));
+        params.add(new BasicNameValuePair("scope" , "all"));
+        params.add(new BasicNameValuePair("tenantId" , "000000"));
+        httpPost.setEntity(new UrlEncodedFormEntity(params, Consts.UTF_8));
+        try {
+            HttpResponse httpResponse= httpClient.execute(httpPost);
+            InputStream inputStream = httpResponse.getEntity().getContent();
+            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+            byte[] buffer = new byte[1024];
+            int index = 0;
+            while ((index=inputStream.read(buffer))!=-1){
+                outputStream.write(buffer,0,index);
+            }
+            System.out.println("\n");
+            System.out.println("bearer "+ JSON.parseObject(outputStream.toString()).getString("access_token"));
+            System.out.print("bearer "+ JSON.parseObject(outputStream.toString()).getString("refresh_token"));
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+    public static void createTable(Class<?> clazz,String remark) {
+               String tableName=clazz.getAnnotation(TableName.class).value();
+               StringBuilder sql = new StringBuilder("CREATE TABLE `"+tableName+"` ( \n" +
+                                                      "`id` bigint(20) NOT NULL COMMENT '主键',\n");
+               List<Field> fields=collectChain(clazz,false);
+               for(Field f:fields){
+                   Size s=f.getAnnotation(Size.class);
+                   String column=f.getName();
+                   String template=" `$1` $2 DEFAULT NULL,\n";
+                   Matcher m = matcher("[A-Z]",column);
+                   while (m.find()){
+                       String re=m.group();
+                       column=column.replace(re,"_"+re.toLowerCase(Locale.ROOT));
+                   }
+                   template=template.replace("$1",column);
+                   String fieldName=f.getType().getCanonicalName();
+                   if(fieldName.contains("String")){
+                       int len=255;
+                       if(s!=null){
+                           len=s.max();
+                       }else if(column.contains("_id")){
+                           len=20;
+                       }
+                       template=template.replace("$2","varchar("+len+")");
+                   }else  if(fieldName.contains("Integer")){
+                       int len=2;
+                       if(s!=null){
+                           len=s.max();
+                       }
+                       template=template.replace("$2","int("+len+")");
+                   }else  if(fieldName.contains("Double")){
+                       template=template.replace("$2","double");
+                   }else  if(fieldName.contains("Long")){
+                       int len=20;
+                       if(s!=null){
+                           len=s.max();
+                       }
+                       template=template.replace("$2","bigint("+len+")");
+                   }else  if(fieldName.contains("Date")){
+                       template=template.replace("$2","datetime");
+                   }
+                   sql.append(template);
+               }
+               sql.append(
+                       "  `tenant_id` varchar(12) DEFAULT '000000' COMMENT '租户ID',\n" +
+                       " `create_user` bigint(20) DEFAULT NULL COMMENT '创建人',\n" +
+                       "  `create_dept` bigint(20) DEFAULT NULL COMMENT '创建部门',\n" +
+                       "  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n" +
+                       "  `update_user` bigint(20) DEFAULT NULL COMMENT '修改人',\n" +
+                       "  `update_time` datetime DEFAULT NULL COMMENT '修改时间',\n" +
+                       "  `status` int(2) DEFAULT NULL COMMENT '状态',\n" +
+                       "  `is_deleted` int(2) DEFAULT '0' COMMENT '是否已删除',");
+               sql.append("  PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='").append(remark).append("'");
+          System.out.println(sql);
+    }
+
+    public static void main(String[] args)  {
+//        createTable(Mileagexy.class,"");
+          getToken();
+    }
+
+}

+ 5 - 0
blade-service/blade-manager/pom.xml

@@ -51,6 +51,11 @@
             <artifactId>blade-business-api</artifactId>
             <version>${bladex.project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>com.jfirer</groupId>
+            <artifactId>baseutil</artifactId>
+            <version>1.0</version>
+        </dependency>
 
         <dependency>
             <groupId>junit</groupId>

+ 15 - 0
blade-service/blade-manager/src/main/java/com/jfireel/exception/IllegalFormatException.java

@@ -0,0 +1,15 @@
+package com.jfireel.exception;
+
+public class IllegalFormatException extends RuntimeException
+{
+    
+    /**
+     * 
+     */
+    private static final long serialVersionUID = -1549862548075188968L;
+    
+    public IllegalFormatException(String msg, String area)
+    {
+        super(msg + ",问题区间:" + area);
+    }
+}

+ 15 - 0
blade-service/blade-manager/src/main/java/com/jfireel/exception/UnParsedException.java

@@ -0,0 +1,15 @@
+package com.jfireel.exception;
+
+public class UnParsedException extends RuntimeException
+{
+    
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 6748928105241855848L;
+    
+    public UnParsedException(String el, Throwable e)
+    {
+        super("无法解析表达式:" + el, e);
+    }
+}

+ 124 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/Expression.java

@@ -0,0 +1,124 @@
+package com.jfireel.expression;
+
+import com.jfireel.exception.UnParsedException;
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.parse.Invoker;
+import com.jfireel.expression.parse.impl.*;
+import com.jfireel.expression.util.Functional;
+import com.jfireel.expression.util.OperatorResultUtil;
+
+import java.util.*;
+
+public class Expression {
+	private CalculateNode parseNode;
+	private Deque<CalculateNode> nodes = new LinkedList<CalculateNode>();
+	private String el;
+	private int function;
+	private Invoker head;
+	private static final Invoker DEFAULT_HEAD;
+
+	static {
+		NodeParser[] parsers = new NodeParser[] { //
+				new SkipIgnoredToken(), //
+				new LeftParenParser(), //
+				new RightParenParser(), //
+				new LeftBracketParser(), //
+				new TypeParser(), //
+				new RightBracketParser(), //
+				new PropertyParser(), //
+				new EnumParser(), //
+				new MethodParser(), //
+				new CommaParser(), //
+				new ConstantStringParser(), //
+				new NumberParser(), //
+				new IdentifierParser(), //
+				new OperatorParser()//
+		};
+		Invoker pred = new Invoker() {
+
+			@Override
+			public int parse(String el, int offset, Deque<CalculateNode> nodes, int function) {
+				return offset;
+			}
+		};
+		for (int i = parsers.length - 1; i > -1; i--) {
+			final NodeParser parser = parsers[i];
+			final Invoker next = pred;
+			Invoker invoker = new Invoker() {
+
+				@Override
+				public int parse(String el, int offset, Deque<CalculateNode> nodes, int function) {
+					return parser.parse(el, offset, nodes, function, next);
+				}
+			};
+			pred = invoker;
+		}
+		DEFAULT_HEAD = pred;
+	}
+
+	public static Expression parse(String el) {
+		return new Expression(el, Functional.build().setMethodInvokeByCompile(true).toFunction(), DEFAULT_HEAD);
+	}
+
+	public static Expression parse(String el, int function) {
+		return new Expression(el, function, DEFAULT_HEAD);
+	}
+
+	public static Expression parse(String el, int function, Invoker head) {
+		return new Expression(el, function, head);
+	}
+
+	private Expression(String el, int function, Invoker head) {
+		this.head = head;
+		this.el = el;
+		this.function = function;
+		try {
+			scan();
+		} catch (Exception e) {
+			throw new UnParsedException(el, e);
+		}
+	}
+
+	private void scan() {
+		int offset = 0;
+		int length = el.length();
+		while (offset < length) {
+			int result = head.parse(el, offset, nodes, function);
+			if (result == offset) {
+				throw new IllegalArgumentException("无法识别的表达式,解析过程预见无法识别的字符:" + el.substring(0, offset));
+			}
+			offset = result;
+		}
+		List<CalculateNode> list = new ArrayList<CalculateNode>();
+		CalculateNode tmp;
+		while ((tmp = nodes.pollFirst()) != null) {
+			list.add(0, tmp);
+		}
+		parseNode = OperatorResultUtil.aggregate(list, function, el, offset);
+		nodes = null;
+		el = null;
+	}
+
+	@SuppressWarnings("unchecked")
+	public <T> T calculate(Map<String, Object> variables) {
+		return (T) parseNode.calculate(variables);
+	}
+
+	@SuppressWarnings("unchecked")
+	public <T> T calculate() {
+		return (T) parseNode.calculate(null);
+	}
+
+	public CalculateNode parseResult() {
+		return parseNode;
+	}
+
+	/**
+	 * 返回解析的表达式
+	 *
+	 * @return
+	 */
+	public String getEl() {
+		return el;
+	}
+}

+ 14 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/CalculateNode.java

@@ -0,0 +1,14 @@
+package com.jfireel.expression.node;
+
+import com.jfireel.expression.token.TokenType;
+
+import java.util.Map;
+
+public interface CalculateNode {
+
+	Object calculate(Map<String, Object> variables);
+
+	TokenType type();
+
+	String literals();
+}

+ 102 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/MethodNode.java

@@ -0,0 +1,102 @@
+package com.jfireel.expression.node;
+
+public interface MethodNode extends CalculateNode {
+	enum ConvertType {
+		INT, LONG, SHORT, FLOAT, DOUBLE, BYTE, BOOLEAN, CHARACTER, OTHER
+	}
+
+	void setArgsNodes(CalculateNode[] argsNodes);
+
+	public static class MethodNodeUtil {
+		public static final void convertArgs(Object[] args, ConvertType[] convertTypes) {
+			for (int i = 0; i < args.length; i++) {
+				Object argeValue = args[i];
+				switch (convertTypes[i]) {
+				case INT:
+					if (argeValue instanceof Integer == false) {
+						args[i] = ((Number) argeValue).intValue();
+					}
+					break;
+				case LONG:
+					if (argeValue instanceof Long == false) {
+						args[i] = ((Number) argeValue).longValue();
+					}
+					break;
+				case SHORT:
+					if (argeValue instanceof Short == false) {
+						args[i] = ((Number) argeValue).shortValue();
+					}
+					break;
+				case FLOAT:
+					if (argeValue instanceof Float == false) {
+						args[i] = ((Number) argeValue).floatValue();
+					}
+					break;
+				case DOUBLE:
+					if (argeValue instanceof Double == false) {
+						args[i] = ((Number) argeValue).doubleValue();
+					}
+					break;
+				case BYTE:
+					if (argeValue instanceof Byte == false) {
+						args[i] = ((Number) argeValue).byteValue();
+					}
+					break;
+				case CHARACTER:
+				case BOOLEAN:
+				case OTHER:
+					// 以上三种不用转化
+					break;
+				default:
+					break;
+				}
+			}
+		}
+
+		public static final ConvertType[] buildConvertTypes(Class<?>[] parameterTypes) {
+			ConvertType[] convertTypes = new ConvertType[parameterTypes.length];
+			for (int i = 0; i < parameterTypes.length; i++) {
+				if (parameterTypes[i] == int.class || parameterTypes[i] == Integer.class) {
+					convertTypes[i] = ConvertType.INT;
+				} else if (parameterTypes[i] == short.class || parameterTypes[i] == short.class) {
+					convertTypes[i] = ConvertType.SHORT;
+				} else if (parameterTypes[i] == long.class || parameterTypes[i] == Long.class) {
+					convertTypes[i] = ConvertType.LONG;
+				} else if (parameterTypes[i] == float.class || parameterTypes[i] == Float.class) {
+					convertTypes[i] = ConvertType.FLOAT;
+				} else if (parameterTypes[i] == double.class || parameterTypes[i] == Double.class) {
+					convertTypes[i] = ConvertType.DOUBLE;
+				} else if (parameterTypes[i] == byte.class || parameterTypes[i] == Byte.class) {
+					convertTypes[i] = ConvertType.BYTE;
+				} else if (parameterTypes[i] == boolean.class || parameterTypes[i] == Boolean.class) {
+					convertTypes[i] = ConvertType.BOOLEAN;
+				} else {
+					convertTypes[i] = ConvertType.OTHER;
+				}
+			}
+			return convertTypes;
+		}
+
+		public static final boolean isWrapType(Class<?> primitiveType, Class<?> arge) {
+			if (primitiveType == int.class) {
+				return arge == Integer.class || arge == Long.class;
+			} else if (primitiveType == short.class) {
+				return arge == Integer.class || arge == Long.class;
+			} else if (primitiveType == long.class) {
+				return arge == Integer.class || arge == Long.class;
+			} else if (primitiveType == boolean.class) {
+				return arge == Boolean.class;
+			} else if (primitiveType == float.class) {
+				return arge == Float.class || arge == Double.class;
+			} else if (primitiveType == double.class) {
+				return arge == Float.class || arge == Double.class;
+			} else if (primitiveType == char.class) {
+				return arge == Character.class;
+			} else if (primitiveType == byte.class) {
+				return arge == Integer.class || arge == Long.class;
+			} else {
+				return false;
+			}
+		}
+	}
+}

+ 9 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/QuestionNode.java

@@ -0,0 +1,9 @@
+package com.jfireel.expression.node;
+
+public interface QuestionNode extends CalculateNode {
+	void setConditionNode(CalculateNode node);
+
+	void setLeftNode(CalculateNode node);
+
+	void setRightNode(CalculateNode node);
+}

+ 123 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/BracketNode.java

@@ -0,0 +1,123 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.token.Token;
+import com.jfireel.expression.token.TokenType;
+
+import java.util.List;
+import java.util.Map;
+
+public class BracketNode implements CalculateNode {
+	private CalculateNode beanNode;
+	private CalculateNode valueNode;
+	private ValueType type;
+
+	enum ValueType {
+		STRING, NUMBER, RUNTIME
+	}
+
+	/**
+	 * 代表[]的节点
+	 * 
+	 * @param beanNode
+	 *            元素节点
+	 * @param valueNode
+	 *            [] 内置的节点
+	 */
+	public BracketNode(CalculateNode beanNode, CalculateNode valueNode) {
+		this.beanNode = beanNode;
+		this.valueNode = valueNode;
+		if (valueNode.type() == Token.STRING) {
+			type = ValueType.STRING;
+		} else if (valueNode.type() == Token.NUMBER) {
+			type = ValueType.NUMBER;
+		} else {
+			type = ValueType.RUNTIME;
+		}
+	}
+
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		Object value = valueNode.calculate(variables);
+		if (value == null) {
+			return null;
+		}
+		switch (type) {
+		case STRING:
+			return returnMapValue(variables,(String) value);
+		case NUMBER:
+			return returnArrayOrListValue(variables, (Number) value);
+		case RUNTIME:
+			if (value instanceof String) {
+				return returnMapValue(variables, (String) value);
+			} else if (value instanceof Number) {
+				return returnArrayOrListValue(variables, (Number) value);
+			} else {
+				throw new IllegalArgumentException(value.getClass().getName());
+			}
+		default:
+			throw new UnsupportedOperationException();
+		}
+	}
+
+	private Object returnArrayOrListValue(Map<String, Object> variables, Number value) {
+		Object beanValue = beanNode.calculate(variables);
+		if (beanValue == null) {
+			return null;
+		}
+		if (beanValue instanceof List) {
+			return ((List<?>) beanValue).get((value).intValue());
+		} else if (beanValue instanceof Object[]) {
+			return ((Object[]) beanValue)[(value).intValue()];
+		} else if (beanValue instanceof int[]) {
+			return ((int[]) beanValue)[(value).intValue()];
+		} else if (beanValue instanceof long[]) {
+			return ((long[]) beanValue)[(value).intValue()];
+		} else if (beanValue instanceof short[]) {
+			return ((short[]) beanValue)[(value).intValue()];
+		} else if (beanValue instanceof float[]) {
+			return ((float[]) beanValue)[(value).intValue()];
+		} else if (beanValue instanceof double[]) {
+			return ((double[]) beanValue)[(value).intValue()];
+		} else if (beanValue instanceof boolean[]) {
+			return ((boolean[]) beanValue)[(value).intValue()];
+		} else if (beanValue instanceof char[]) {
+			return ((char[]) beanValue)[(value).intValue()];
+		} else if (beanValue instanceof byte[]) {
+			return ((byte[]) beanValue)[(value).intValue()];
+		} else {
+			throw new IllegalArgumentException(beanValue.getClass().getName());
+		}
+	}
+
+	@SuppressWarnings("unchecked")
+	private Object returnMapValue(Map<String, Object> variables, String value) {
+		Object result = null;
+		Object obj = beanNode.calculate(variables);
+		if(obj instanceof Map) {
+			result = ((Map) obj).get(value);
+		} else if(obj instanceof List) {
+			Object o = ((List) obj).get(0);
+			if(o instanceof Map) {
+				result = ((Map) o).get(value);
+			}
+		}
+		return result;
+	}
+
+	@Override
+	public TokenType type() {
+		return Token.BRACKET;
+	}
+
+	@Override
+	public String literals() {
+		return beanNode.literals() + "[" + valueNode.literals() + "]";
+	}
+
+	@Override
+	public String toString() {
+		return literals();
+	}
+
+}

+ 52 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/ClassPropertyNode.java

@@ -0,0 +1,52 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.token.Token;
+import com.jfireel.expression.token.TokenType;
+
+import java.lang.reflect.Field;
+import java.util.Map;
+
+public class ClassPropertyNode implements CalculateNode {
+	protected final Class<?> beanType;
+	protected final Field field;
+
+	/**
+	 * 使用通过变量名和属性名访问该变量的属性
+	 * 
+	 * @param literals
+	 */
+	public ClassPropertyNode(String literals, CalculateNode beanNode) {
+		try {
+			beanType = (Class<?>) beanNode.calculate(null);
+			field = beanType.getField(literals);
+		} catch (Exception e) {
+			throw new IllegalArgumentException("类型的静态属性无法获取到,检查" + literals, e);
+		}
+	}
+
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		try {
+			return field.get(null);
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	@Override
+	public TokenType type() {
+		return Token.PROPERTY;
+	}
+
+	@Override
+	public String toString() {
+		return literals();
+	}
+
+	@Override
+	public String literals() {
+		return beanType.getName() + "." + field.getName();
+	}
+
+}

+ 217 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/CompileObjectMethodNode.java

@@ -0,0 +1,217 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.node.MethodNode;
+import com.jfireel.expression.token.Token;
+import com.jfireel.expression.token.TokenType;
+import com.jfirer.baseutil.reflect.ReflectUtil;
+import com.jfirer.baseutil.smc.SmcHelper;
+import com.jfirer.baseutil.smc.compiler.CompileHelper;
+import com.jfirer.baseutil.smc.model.ClassModel;
+import com.jfirer.baseutil.smc.model.MethodModel;
+
+import java.lang.reflect.Method;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class CompileObjectMethodNode implements MethodNode {
+	public static interface Invoker {
+		Object invoke(Object host, Object[] params);
+	}
+
+	private static final CompileHelper COMPILER = new CompileHelper();
+	private static final AtomicInteger counter = new AtomicInteger(0);
+	private final CalculateNode beanNode;
+	private final String methodName;
+	private volatile Invoker invoker;
+	private volatile Class<?> beanType;
+	protected final boolean recognizeEveryTime;
+	private CalculateNode[] argsNodes;
+	private Token type;
+
+	public CompileObjectMethodNode(String literals, CalculateNode beanNode, boolean recognizeEveryTime) {
+		methodName = literals;
+		type = Token.METHOD;
+		this.beanNode = beanNode;
+		this.recognizeEveryTime = recognizeEveryTime;
+	}
+
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		Object value = beanNode.calculate(variables);
+		if (value == null) {
+			return value;
+		}
+		Object[] args = new Object[argsNodes.length];
+		try {
+			for (int i = 0; i < args.length; i++) {
+				args[i] = argsNodes[i].calculate(variables);
+			}
+			Invoker invoke = getMethod(value, args);
+			return invoke.invoke(value, args);
+		} catch (Exception e) {
+			ReflectUtil.throwException(e);
+			return null;
+		}
+	}
+
+	@Override
+	public TokenType type() {
+		return type;
+	}
+
+	private Invoker getMethod(Object value, Object[] args) {
+		if (recognizeEveryTime) {
+			Invoker invoker = this.invoker;
+			if (invoker == null || beanType.isAssignableFrom(value.getClass()) == false) {
+				synchronized (this) {
+					if ((invoker = this.invoker) == null || beanType.isAssignableFrom(value.getClass()) == false) {
+						invoker = this.invoker = buildInvoker(value, args);
+						return invoker;
+					}
+				}
+			}
+			return invoker;
+		} else {
+			if (invoker == null) {
+				synchronized (this) {
+					if (invoker == null) {
+						invoker = buildInvoker(value, args);
+						return invoker;
+					}
+				}
+			}
+			return invoker;
+		}
+	}
+
+	private Invoker buildInvoker(Object value, Object[] args) {
+		nextmethod: for (Method each : value.getClass().getMethods()) {
+			if (each.getName().equals(methodName) && each.getParameterTypes().length == args.length) {
+				Class<?>[] parameterTypes = each.getParameterTypes();
+				for (int i = 0; i < args.length; i++) {
+					if (parameterTypes[i].isPrimitive()) {
+						if (args[i] == null
+								|| MethodNodeUtil.isWrapType(parameterTypes[i], args[i].getClass()) == false) {
+							continue nextmethod;
+						}
+					} else {
+						if (args[i] != null && parameterTypes[i].isAssignableFrom(args[i].getClass()) == false) {
+							continue nextmethod;
+						}
+					}
+				}
+				beanType = value.getClass();
+				return buildInvoker(args, each);
+			}
+		}
+		ReflectUtil.throwException(new NullPointerException());
+		return null;
+	}
+
+	private Invoker buildInvoker(Object[] args, Method method) {
+		try {
+			ClassModel classModel = new ClassModel("Invoke_" + method.getName() + "_" + counter.incrementAndGet(),
+					Object.class, Invoker.class);
+			MethodModel methodModel = new MethodModel(classModel);
+			methodModel.setAccessLevel(MethodModel.AccessLevel.PUBLIC);
+			methodModel.setMethodName("invoke");
+			methodModel.setParamterTypes(Object.class, Object[].class);
+			methodModel.setReturnType(Object.class);
+			StringBuilder body = new StringBuilder(
+					" return ((" + SmcHelper.getReferenceName(method.getDeclaringClass(), classModel) + ")$0)."
+							+ method.getName() + "(");
+			int length = body.length();
+			Class<?>[] parameterTypes = method.getParameterTypes();
+			for (int i = 0; i < parameterTypes.length; i++) {
+				Class<?> parameterType = parameterTypes[i];
+				if (parameterType == int.class) {
+					body.append("((java.lang.Number)$1[").append(i).append("]).intValue(),");
+				} else if (parameterType == Integer.class) {
+					if (args[i].getClass() == Integer.class) {
+						body.append("((java.lang.Integer)$").append(i).append("),");
+					} else {
+						body.append("((java.lang.Number)$1[").append(i).append("]).intValue(),");
+					}
+				} else if (parameterTypes[i] == short.class || parameterTypes[i] == short.class) {
+					body.append("((java.lang.Number)$1[").append(i).append("]).shortValue(),");
+				} else if (parameterTypes[i] == long.class) {
+					body.append("((java.lang.Number)$1[").append(i).append("]).longValue(),");
+				} else if (parameterType == Long.class) {
+					if (args[i].getClass() == Long.class) {
+						body.append("((java.lang.Long)$").append(i).append("),");
+					} else {
+						body.append("((java.lang.Number)$1[").append(i).append("]).longValue(),");
+					}
+				} else if (parameterTypes[i] == float.class) {
+					body.append("((java.lang.Number)$1[").append(i).append("]).floatValue(),");
+				} else if (parameterType == Float.class) {
+					if (args[i].getClass() == Float.class) {
+						body.append("((java.lang.Float)$").append(i).append("),");
+					} else {
+						body.append("((java.lang.Number)$1[").append(i).append("]).floatValue(),");
+					}
+				} else if (parameterTypes[i] == double.class) {
+					body.append("((java.lang.Number)$1[").append(i).append("]).doubleValue(),");
+				} else if (parameterType == Double.class) {
+					body.append("((java.lang.Double)$").append(i).append("),");
+				} else if (parameterTypes[i] == byte.class || parameterTypes[i] == Byte.class) {
+					body.append("((java.lang.Number)$1[").append(i).append("]).byteValue(),");
+				} else if (parameterTypes[i] == boolean.class) {
+					body.append("((java.lang.Boolean)$1[").append(i).append("]).booleanValue(),");
+				} else if (parameterType == Boolean.class) {
+					body.append("((java.lang.Boolean)$").append(i).append("),");
+				} else {
+					body.append("((" + SmcHelper.getReferenceName(parameterTypes[i], classModel) + ")$1[").append(i)
+							.append("]),");
+				}
+			}
+			if (body.length() != length) {
+				body.setLength(body.length() - 1);
+			}
+			body.append(");");
+			methodModel.setBody(body.toString());
+			classModel.putMethodModel(methodModel);
+			Class<?> compile = COMPILER.compile(classModel);
+			return (Invoker) compile.newInstance();
+		} catch (Exception e) {
+			ReflectUtil.throwException(e);
+			return null;
+		}
+	}
+
+	@Override
+	public void setArgsNodes(CalculateNode[] argsNodes) {
+		this.argsNodes = argsNodes;
+		type = Token.METHOD_RESULT;
+	}
+
+	public CalculateNode[] getArgsNodes(){
+		return this.argsNodes;
+	}
+
+	public String getMethodName(){
+		return this.methodName;
+	}
+
+	@Override
+	public String literals() {
+		StringBuilder cache = new StringBuilder();
+		cache.append(beanNode.literals()).append('.').append(methodName).append('(');
+		if (argsNodes != null) {
+			for (CalculateNode each : argsNodes) {
+				cache.append(each.literals()).append(',');
+			}
+			if (cache.charAt(cache.length() - 1) == ',') {
+				cache.setLength(cache.length() - 1);
+			}
+		}
+		cache.append(')');
+		return cache.toString();
+	}
+
+	@Override
+	public String toString() {
+		return literals();
+	}
+}

+ 44 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/DivisionNode.java

@@ -0,0 +1,44 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.token.Operator;
+import com.jfireel.expression.util.number.DivisionUtil;
+import com.mixsmart.utils.StringUtils;
+
+import java.math.BigDecimal;
+import java.util.Map;
+
+public class DivisionNode extends OperatorResultNode {
+
+	public DivisionNode() {
+		super(Operator.DIVISION);
+	}
+
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		Object leftValue = leftOperand.calculate(variables);
+		if(leftValue instanceof String && StringUtils.isNumber(leftValue)) {
+			leftValue = new BigDecimal(leftValue.toString());
+		}
+		if (leftValue instanceof Number==false) {
+			return null;
+		}
+		Object rightValue = rightOperand.calculate(variables);
+		if(rightValue instanceof String && StringUtils.isNumber(rightValue)) {
+			rightValue = new BigDecimal(rightValue.toString());
+		}
+		if (rightValue instanceof Number==false) {
+			return null;
+		}
+		return DivisionUtil.calculate((Number) leftValue, (Number) rightValue);
+	}
+
+	@Override
+	public String literals() {
+		return "/";
+	}
+
+	@Override
+	public String toString() {
+		return literals();
+	}
+}

+ 32 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/DoubleAmpNode.java

@@ -0,0 +1,32 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.token.Operator;
+
+import java.util.Map;
+
+public class DoubleAmpNode extends OperatorResultNode {
+	public DoubleAmpNode() {
+		super(Operator.DOUBLE_AMP);
+	}
+
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		Object leftValue = leftOperand.calculate(variables);
+		if (leftValue == null) {
+			return null;
+		}
+		if (((Boolean) leftValue) == false) {
+			return false;
+		}
+		Object rightValue = rightOperand.calculate(variables);
+		if (rightValue == null) {
+			return null;
+		}
+		return (rightValue);
+	}
+
+	@Override
+	public String toString() {
+		return literals();
+	}
+}

+ 33 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/DoubleBarNode.java

@@ -0,0 +1,33 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.token.Operator;
+
+import java.util.Map;
+
+public class DoubleBarNode extends OperatorResultNode {
+
+	public DoubleBarNode() {
+		super(Operator.DOUBLE_BAR);
+	}
+
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		Object leftValue = leftOperand.calculate(variables);
+		if (leftValue == null) {
+			return null;
+		}
+		if (((Boolean) leftValue)) {
+			return true;
+		}
+		Object rightValue = rightOperand.calculate(variables);
+		if (rightValue == null) {
+			return null;
+		}
+		return (rightValue);
+	}
+
+	@Override
+	public String toString() {
+		return literals();
+	}
+}

+ 37 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/EnumNode.java

@@ -0,0 +1,37 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.token.Token;
+import com.jfireel.expression.token.TokenType;
+
+import java.util.Map;
+
+public class EnumNode implements CalculateNode {
+	private final Enum<?> value;
+
+	@SuppressWarnings({ "rawtypes", "unchecked" })
+	public EnumNode(CalculateNode enumTypeNode, String literals) {
+		Class<Enum> enumType = (Class<Enum>) enumTypeNode.calculate(null);
+		value = Enum.valueOf(enumType, literals);
+	}
+
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		return value;
+	}
+
+	@Override
+	public TokenType type() {
+		return Token.ENUM;
+	}
+
+	@Override
+	public String literals() {
+		return value.name();
+	}
+
+	@Override
+	public String toString() {
+		return literals();
+	}
+}

+ 33 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/EqualNode.java

@@ -0,0 +1,33 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.token.Operator;
+import com.jfireel.expression.util.number.EqUtil;
+
+import java.util.Map;
+
+public class EqualNode extends OperatorResultNode {
+
+	public EqualNode() {
+		super(Operator.EQ);
+	}
+
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		Object leftValue = leftOperand.calculate(variables);
+		Object rightValue = rightOperand.calculate(variables);
+		if (leftValue == null && rightValue == null) {
+			return true;
+		} else if (leftValue == null && rightValue != null) {
+			return false;
+		} else if (leftValue != null && rightValue == null) {
+			return false;
+		} else {
+			if (leftValue instanceof Number && rightValue instanceof Number) {
+				return EqUtil.calculate((Number) leftValue, (Number) rightValue);
+			} else {
+				return leftValue.equals(rightValue);
+			}
+		}
+	}
+
+}

+ 25 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/GtEqNode.java

@@ -0,0 +1,25 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.token.Operator;
+import com.jfireel.expression.util.number.LtUtil;
+
+import java.util.Map;
+
+public class GtEqNode extends OperatorResultNode {
+	public GtEqNode() {
+		super(Operator.GT_EQ);
+	}
+
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		Object leftValue = leftOperand.calculate(variables);
+		if (leftValue == null) {
+			return null;
+		}
+		Object rightValue = rightOperand.calculate(variables);
+		if (rightValue == null) {
+			return null;
+		}
+		return (Boolean) LtUtil.calculate((Number) leftValue, (Number) rightValue) == false;
+	}
+}

+ 26 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/GtNode.java

@@ -0,0 +1,26 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.token.Operator;
+import com.jfireel.expression.util.number.GtUtil;
+
+import java.util.Map;
+
+public class GtNode extends OperatorResultNode {
+	public GtNode() {
+		super(Operator.GT);
+	}
+
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		Object leftValue = leftOperand.calculate(variables);
+		if (leftValue == null) {
+			return null;
+		}
+		Object rightValue = rightOperand.calculate(variables);
+		if (rightValue == null) {
+			return null;
+		}
+		return GtUtil.calculate((Number) leftValue, (Number) rightValue);
+	}
+
+}

+ 48 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/KeywordNode.java

@@ -0,0 +1,48 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.token.Token;
+import com.jfireel.expression.token.TokenType;
+
+import java.util.Map;
+
+public class KeywordNode implements CalculateNode {
+	private Object keywordValue;
+
+	public KeywordNode(String literals) {
+		if (literals.equalsIgnoreCase("true")) {
+			keywordValue = Boolean.TRUE;
+		} else if (literals.equalsIgnoreCase("false")) {
+			keywordValue = Boolean.FALSE;
+		} else if (literals.equalsIgnoreCase("null")) {
+			keywordValue = null;
+		} else {
+			throw new IllegalArgumentException();
+		}
+	}
+
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		return keywordValue;
+	}
+
+	@Override
+	public TokenType type() {
+		return Token.CONSTANT;
+	}
+
+	@Override
+	public String toString() {
+		return "KeywordNode [keywordValue=" + keywordValue + "]";
+	}
+
+	@Override
+	public String literals() {
+		if (keywordValue != null) {
+			return keywordValue.toString();
+		} else {
+			return "NULL";
+		}
+	}
+
+}

+ 26 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/LtEqNode.java

@@ -0,0 +1,26 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.token.Operator;
+import com.jfireel.expression.util.number.GtUtil;
+
+import java.util.Map;
+
+public class LtEqNode extends OperatorResultNode {
+	public LtEqNode() {
+		super(Operator.LT_EQ);
+	}
+
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		Object leftValue = leftOperand.calculate(variables);
+		if (leftValue == null) {
+			return null;
+		}
+		Object rightValue = rightOperand.calculate(variables);
+		if (rightValue == null) {
+			return null;
+		}
+		return (Boolean) GtUtil.calculate((Number) leftValue, (Number) rightValue) == false;
+	}
+
+}

+ 27 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/LtNode.java

@@ -0,0 +1,27 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.token.Operator;
+import com.jfireel.expression.util.number.LtUtil;
+
+import java.util.Map;
+
+public class LtNode extends OperatorResultNode {
+
+	public LtNode() {
+		super(Operator.LT);
+	}
+
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		Object leftValue = leftOperand.calculate(variables);
+		if (leftValue == null) {
+			return null;
+		}
+		Object rightValue = rightOperand.calculate(variables);
+		if (rightValue == null) {
+			return null;
+		}
+		return LtUtil.calculate((Number) leftValue, (Number) rightValue);
+	}
+
+}

+ 34 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/MinusNode.java

@@ -0,0 +1,34 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.token.Operator;
+import com.jfireel.expression.util.number.SubtractUtil;
+import com.mixsmart.utils.StringUtils;
+
+import java.math.BigDecimal;
+import java.util.Map;
+
+public class MinusNode extends OperatorResultNode {
+	public MinusNode() {
+		super(Operator.MINUS);
+	}
+
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		Object leftValue = leftOperand.calculate(variables);
+		if(leftValue instanceof String && StringUtils.isNumber(leftValue)) {
+			leftValue = new BigDecimal(leftValue.toString());
+		}
+		if (leftValue instanceof Number == false) {
+			return null;
+		}
+		Object rightValue = rightOperand.calculate(variables);
+		if(rightValue instanceof String && StringUtils.isNumber(rightValue)) {
+			rightValue = new BigDecimal(rightValue.toString());
+		}
+		if (rightValue instanceof Number == false) {
+			return null;
+		}
+		return SubtractUtil.calculate((Number) leftValue, (Number) rightValue);
+	}
+
+}

+ 35 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/MutliNode.java

@@ -0,0 +1,35 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.token.Operator;
+import com.jfireel.expression.util.number.MultiplyUtil;
+import com.mixsmart.utils.StringUtils;
+
+import java.math.BigDecimal;
+import java.util.Map;
+
+public class MutliNode extends OperatorResultNode {
+
+	public MutliNode() {
+		super(Operator.MULTI);
+	}
+
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		Object leftValue = leftOperand.calculate(variables);
+		if(leftValue instanceof String && StringUtils.isNumber(leftValue)) {
+			leftValue = new BigDecimal(leftValue.toString());
+		}
+		if (leftValue instanceof Number == false) {
+			return null;
+		}
+		Object rightValue = rightOperand.calculate(variables);
+		if(rightValue instanceof String && StringUtils.isNumber(rightValue)) {
+			rightValue = new BigDecimal(rightValue.toString());
+		}
+		if (rightValue instanceof Number == false) {
+			return null;
+		}
+		return MultiplyUtil.calculate((Number) leftValue, (Number) rightValue);
+	}
+
+}

+ 33 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/NotEqualNode.java

@@ -0,0 +1,33 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.token.Operator;
+import com.jfireel.expression.util.number.EqUtil;
+
+import java.util.Map;
+
+public class NotEqualNode extends OperatorResultNode {
+
+	public NotEqualNode() {
+		super(Operator.NOT_EQ);
+	}
+
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		Object leftValue = leftOperand.calculate(variables);
+		Object rightValue = rightOperand.calculate(variables);
+		if (leftValue == null && rightValue == null) {
+			return false;
+		} else if (leftValue == null && rightValue != null) {
+			return true;
+		} else if (leftValue != null && rightValue == null) {
+			return true;
+		} else {
+			if (leftValue instanceof Number && rightValue instanceof Number) {
+				return EqUtil.calculate((Number) leftValue, (Number) rightValue) == false;
+			} else {
+				return leftValue.equals(rightValue) == false;
+			}
+		}
+	}
+
+}

+ 46 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/NumberNode.java

@@ -0,0 +1,46 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.token.Token;
+import com.jfireel.expression.token.TokenType;
+
+import java.util.Map;
+
+public class NumberNode implements CalculateNode {
+	private Number value;
+
+	public NumberNode(String literals) {
+		if (literals.indexOf('.') > -1) {
+			value = Float.valueOf(literals);
+			if (Float.isInfinite((Float) value)) {
+				value = Double.valueOf(literals);
+			}
+		} else {
+			try {
+				value = Integer.valueOf(literals);
+			} catch (NumberFormatException e) {
+				value = Long.valueOf(literals);
+			}
+		}
+	}
+
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		return value;
+	}
+
+	@Override
+	public TokenType type() {
+		return Token.NUMBER;
+	}
+
+	@Override
+	public String literals() {
+		return value.toString();
+	}
+
+	@Override
+	public String toString() {
+		return literals();
+	}
+}

+ 101 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/ObjectPropertyNode.java

@@ -0,0 +1,101 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.token.Token;
+import com.jfireel.expression.token.TokenType;
+import com.jfirer.baseutil.StringUtil;
+import com.jfirer.baseutil.reflect.ReflectUtil;
+import com.jfirer.baseutil.reflect.ValueAccessor;
+
+import java.lang.reflect.Field;
+import java.util.Map;
+
+public class ObjectPropertyNode implements CalculateNode {
+	protected Class<?> beanType;
+	protected String propertyName;
+	protected boolean recognizeEveryTime = true;
+	private CalculateNode beanNode;
+	private volatile ValueAccessor valueAccessor;
+
+	/**
+	 * 使用通过变量名和属性名访问该变量的属性
+	 *
+	 * @param literals
+	 */
+	public ObjectPropertyNode(String literals, CalculateNode beanNode, boolean recognizeEveryTime) {
+		propertyName = literals;
+		this.beanNode = beanNode;
+		this.recognizeEveryTime = recognizeEveryTime;
+	}
+
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		Object value = beanNode.calculate(variables);
+		if (value == null) {
+			return null;
+		}
+		try {
+			return getValueAccessor(value).get(value);
+		} catch (Exception e) {
+			ReflectUtil.throwException(e);
+			return null;
+		}
+	}
+
+	@Override
+	public TokenType type() {
+		return Token.PROPERTY;
+	}
+
+	protected final ValueAccessor getValueAccessor(Object value) {
+		ValueAccessor valueAccessor = this.valueAccessor;
+		if (recognizeEveryTime) {
+			if (valueAccessor == null || beanType.isAssignableFrom(value.getClass())) {
+				synchronized (this) {
+					if ((valueAccessor = this.valueAccessor) == null || beanType.isAssignableFrom(value.getClass())) {
+						return buildValueAccessor(value);
+					}
+				}
+			}
+			return valueAccessor;
+		} else {
+			if (valueAccessor == null) {
+				synchronized (this) {
+					if ((valueAccessor = this.valueAccessor) == null) {
+						return buildValueAccessor(value);
+					}
+				}
+			}
+			return valueAccessor;
+		}
+	}
+
+	private ValueAccessor buildValueAccessor(Object value) {
+		ValueAccessor valueAccessor;
+		Field propertyField;
+		Class<?> ckass = value.getClass();
+		while (ckass != Object.class) {
+			try {
+				propertyField = ckass.getDeclaredField(propertyName);
+				beanType = value.getClass();
+				valueAccessor = this.valueAccessor = new ValueAccessor(propertyField);
+				return valueAccessor;
+			} catch (NoSuchFieldException e) {
+				ckass = ckass.getSuperclass();
+			} catch (SecurityException e) {
+				ReflectUtil.throwException(e);
+			}
+		}
+		throw new NullPointerException(StringUtil.format("无法在类{}中找到属性:{}", value.getClass(), propertyName));
+	}
+
+	@Override
+	public String literals() {
+		return beanNode.literals() + "." + propertyName;
+	}
+
+	@Override
+	public String toString() {
+		return literals();
+	}
+}

+ 36 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/OperatorNode.java

@@ -0,0 +1,36 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.token.Operator;
+import com.jfireel.expression.token.TokenType;
+
+import java.util.Map;
+
+public class OperatorNode implements CalculateNode {
+	private Operator operatorType;
+
+	public OperatorNode(Operator operatorType) {
+		this.operatorType = operatorType;
+	}
+
+	// 操作符节点不会有计算动作
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public TokenType type() {
+		return operatorType;
+	}
+
+	@Override
+	public String literals() {
+		return operatorType.getLiterals();
+	}
+
+	@Override
+	public String toString() {
+		return literals();
+	}
+}

+ 38 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/OperatorResultNode.java

@@ -0,0 +1,38 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.token.Operator;
+import com.jfireel.expression.token.Token;
+import com.jfireel.expression.token.TokenType;
+
+public abstract class OperatorResultNode implements CalculateNode {
+	protected CalculateNode leftOperand;
+	protected CalculateNode rightOperand;
+	protected Operator type;
+
+	protected OperatorResultNode(Operator type) {
+		this.type = type;
+	}
+
+	public void setLeftOperand(CalculateNode node) {
+		leftOperand = node;
+	}
+
+	public void setRightOperand(CalculateNode node) {
+		rightOperand = node;
+	}
+
+	@Override
+	public TokenType type() {
+		return Token.OPERATOR_RESULT;
+	}
+
+	public String literals() {
+		return leftOperand.literals() + type.getLiterals() + rightOperand.literals();
+	}
+
+	@Override
+	public String toString() {
+		return literals();
+	}
+}

+ 26 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/PercentNode.java

@@ -0,0 +1,26 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.token.Operator;
+import com.jfireel.expression.util.number.RemainderUtil;
+
+import java.util.Map;
+
+public class PercentNode extends OperatorResultNode {
+	public PercentNode() {
+		super(Operator.PERCENT);
+	}
+
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		Object leftValue = leftOperand.calculate(variables);
+		if (leftValue == null) {
+			return null;
+		}
+		Object rightValue = rightOperand.calculate(variables);
+		if (rightValue == null) {
+			return null;
+		}
+		return RemainderUtil.calculate((Number) leftValue, (Number) rightValue);
+	}
+
+}

+ 47 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/PlusNode.java

@@ -0,0 +1,47 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.token.Operator;
+import com.jfireel.expression.util.number.PlusUtil;
+
+import java.util.Map;
+
+public class PlusNode extends OperatorResultNode {
+	private static final ThreadLocal<StringBuilder> LOCAL = new ThreadLocal<StringBuilder>() {
+		protected StringBuilder initialValue() {
+			return new StringBuilder();
+		}
+
+		;
+	};
+
+	public PlusNode() {
+		super(Operator.PLUS);
+	}
+
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		Object leftValue = leftOperand.calculate(variables);
+		Object rightValue = rightOperand.calculate(variables);
+		if (leftValue instanceof String || rightValue instanceof String) {
+			StringBuilder cache = LOCAL.get();
+			if(leftValue != null) {
+				cache.append(leftValue);
+			}
+			if(rightValue != null) {
+				cache.append(rightValue);
+			}
+			String result = cache.toString();
+			cache.setLength(0);
+			return result;
+		} else {
+			if (leftValue != null && rightValue != null) {
+				return PlusUtil.calculate((Number) leftValue, (Number) rightValue);
+			}else if (leftValue == null && rightValue != null) {
+				return  rightValue;
+			}else if  (leftValue != null && rightValue == null) {
+				return  leftValue;
+			}
+		}
+		return null;
+	}
+}

+ 57 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/QuestionNodeImpl.java

@@ -0,0 +1,57 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.node.QuestionNode;
+import com.jfireel.expression.token.Token;
+import com.jfireel.expression.token.TokenType;
+
+import java.util.Map;
+
+public class QuestionNodeImpl implements QuestionNode {
+	private CalculateNode conditionNode;
+	private CalculateNode expressionNode1;
+	private CalculateNode expressionNode2;
+
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		Object condition = conditionNode.calculate(variables);
+		if (condition == null) {
+			return null;
+		}
+		if ((Boolean) condition) {
+			return expressionNode1.calculate(variables);
+		} else {
+			return expressionNode2.calculate(variables);
+		}
+	}
+
+	@Override
+	public TokenType type() {
+		return Token.QUESTION;
+	}
+
+	@Override
+	public void setConditionNode(CalculateNode node) {
+		conditionNode = node;
+	}
+
+	@Override
+	public void setLeftNode(CalculateNode node) {
+		expressionNode1 = node;
+	}
+
+	@Override
+	public void setRightNode(CalculateNode node) {
+		expressionNode2 = node;
+	}
+
+	@Override
+	public String literals() {
+		return conditionNode.literals() + "?" + expressionNode1.literals() + ":" + expressionNode2.literals();
+	}
+
+	@Override
+	public String toString() {
+		return literals();
+	}
+}

+ 146 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/ReflectMethodNode.java

@@ -0,0 +1,146 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.node.MethodNode;
+import com.jfireel.expression.token.Token;
+import com.jfireel.expression.token.TokenType;
+
+import java.lang.reflect.Method;
+import java.util.Map;
+
+public class ReflectMethodNode implements MethodNode {
+	private final CalculateNode beanNode;
+	private final String methodName;
+	private volatile Method method;
+	private volatile Class<?> beanType;
+	protected final boolean recognizeEveryTime;
+	private CalculateNode[] argsNodes;
+	private ConvertType[] convertTypes;
+	private Token type;
+
+	public ReflectMethodNode(String literals, CalculateNode beanNode, boolean recognizeEveryTime) {
+		methodName = literals;
+		type = Token.METHOD;
+		this.beanNode = beanNode;
+		this.recognizeEveryTime = recognizeEveryTime;
+	}
+
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		Object value = beanNode.calculate(variables);
+		if (value == null) {
+			return value;
+		}
+		Object[] args = new Object[argsNodes.length];
+		try {
+			for (int i = 0; i < args.length; i++) {
+				args[i] = argsNodes[i].calculate(variables);
+			}
+			Method invoke = getMethod(value, args);
+			MethodNodeUtil.convertArgs(args, convertTypes);
+			return invoke.invoke(value, args);
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new RuntimeException(e);
+		}
+	}
+
+	@Override
+	public TokenType type() {
+		return type;
+	}
+
+	private Method getMethod(Object value, Object[] args) {
+		if (recognizeEveryTime) {
+			Method accessMethod = method;
+			if (accessMethod == null || beanType.isAssignableFrom(value.getClass()) == false) {
+				synchronized (this) {
+					if ((accessMethod = method) == null || beanType.isAssignableFrom(value.getClass()) == false) {
+						nextmethod: for (Method each : value.getClass().getMethods()) {
+							if (each.getName().equals(methodName) && each.getParameterTypes().length == args.length) {
+								Class<?>[] parameterTypes = each.getParameterTypes();
+								for (int i = 0; i < args.length; i++) {
+									if (parameterTypes[i].isPrimitive()) {
+										if (args[i] == null || MethodNodeUtil.isWrapType(parameterTypes[i],
+												args[i].getClass()) == false) {
+											continue nextmethod;
+										}
+									} else {
+										if (args[i] != null
+												&& parameterTypes[i].isAssignableFrom(args[i].getClass()) == false) {
+											continue nextmethod;
+										}
+									}
+								}
+								convertTypes = MethodNodeUtil.buildConvertTypes(parameterTypes);
+								accessMethod = each;
+								accessMethod.setAccessible(true);
+								beanType = value.getClass();
+								method = accessMethod;
+								return accessMethod;
+							}
+						}
+						throw new NullPointerException();
+					}
+				}
+			}
+			return method;
+		} else {
+			if (method == null) {
+				synchronized (this) {
+					if (method == null) {
+						Class<?> ckass = value.getClass();
+						nextmethod: for (Method each : ckass.getMethods()) {
+							if (each.getName().equals(methodName) && each.getParameterTypes().length == args.length) {
+								Class<?>[] parameterTypes = each.getParameterTypes();
+								for (int i = 0; i < args.length; i++) {
+									if (parameterTypes[i].isPrimitive()) {
+										if (args[i] == null || MethodNodeUtil.isWrapType(parameterTypes[i],
+												args[i].getClass()) == false) {
+											continue nextmethod;
+										}
+									} else if (args[i] != null
+											&& parameterTypes[i].isAssignableFrom(args[i].getClass()) == false) {
+										continue nextmethod;
+									}
+								}
+								convertTypes = MethodNodeUtil.buildConvertTypes(parameterTypes);
+								each.setAccessible(true);
+								method = each;
+								return method;
+							}
+						}
+					}
+					throw new NullPointerException();
+				}
+			}
+			return method;
+		}
+	}
+
+	public void setArgsNodes(CalculateNode[] argsNodes) {
+		this.argsNodes = argsNodes;
+		type = Token.METHOD_RESULT;
+	}
+
+	@Override
+	public String literals() {
+		StringBuilder cache = new StringBuilder();
+		cache.append(beanNode.literals()).append('.').append(methodName).append('(');
+		if (argsNodes != null) {
+			for (CalculateNode each : argsNodes) {
+				cache.append(each.literals()).append(',');
+			}
+			if (cache.charAt(cache.length() - 1) == ',') {
+				cache.setLength(cache.length() - 1);
+			}
+		}
+		cache.append(')');
+		return cache.toString();
+	}
+
+	@Override
+	public String toString() {
+		return literals();
+	}
+}

+ 108 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/StaticObjectMethodNode.java

@@ -0,0 +1,108 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.node.MethodNode;
+import com.jfireel.expression.token.Token;
+import com.jfireel.expression.token.TokenType;
+import com.jfirer.baseutil.reflect.ReflectUtil;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Map;
+
+public class StaticObjectMethodNode implements MethodNode {
+	private final Class<?> beanType;
+	private volatile Method method;
+	private String methodName;
+	private CalculateNode[] argsNodes;
+	private ConvertType[] convertTypes;
+	private Token type;
+
+	public StaticObjectMethodNode(String literals, CalculateNode beanNode) {
+		if (beanNode.type() != Token.TYPE) {
+			throw new IllegalArgumentException("静态方法的前面一个节点必须是类型节点");
+		}
+		beanType = (Class<?>) beanNode.calculate(null);
+		methodName = literals;
+		type = Token.METHOD;
+	}
+
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		Object[] args = new Object[argsNodes.length];
+		try {
+			for (int i = 0; i < args.length; i++) {
+				args[i] = argsNodes[i].calculate(variables);
+			}
+			Method invoke = getMethod(args);
+			MethodNodeUtil.convertArgs(args, convertTypes);
+			return invoke.invoke(null, args);
+		} catch (Exception e) {
+			ReflectUtil.throwException(e);
+			return null;
+		}
+	}
+
+	@Override
+	public TokenType type() {
+		return type;
+	}
+
+	private Method getMethod(Object[] args) {
+		if (method == null) {
+			synchronized (this) {
+				if (method == null) {
+					nextmethod: for (Method each : beanType.getMethods()) {
+						if (Modifier.isStatic(each.getModifiers()) && each.getName().equals(methodName)
+								&& each.getParameterTypes().length == args.length) {
+							Class<?>[] parameterTypes = each.getParameterTypes();
+							for (int i = 0; i < args.length; i++) {
+								if (parameterTypes[i].isPrimitive()) {
+									if (args[i] == null || MethodNodeUtil.isWrapType(parameterTypes[i],
+											args[i].getClass()) == false) {
+										continue nextmethod;
+									}
+								} else if (args[i] != null
+										&& parameterTypes[i].isAssignableFrom(args[i].getClass()) == false) {
+									continue nextmethod;
+								}
+							}
+							convertTypes = MethodNodeUtil.buildConvertTypes(parameterTypes);
+							each.setAccessible(true);
+							method = each;
+							return method;
+						}
+					}
+				}
+				throw new NullPointerException("没有在类" + beanType.getName() + "找到静态方法" + methodName);
+			}
+		}
+		return method;
+	}
+
+	public void setArgsNodes(CalculateNode[] argsNodes) {
+		this.argsNodes = argsNodes;
+		type = Token.METHOD_RESULT;
+	}
+
+	@Override
+	public String literals() {
+		StringBuilder cache = new StringBuilder();
+		cache.append(beanType.getName()).append('.').append(methodName).append('(');
+		if (argsNodes != null) {
+			for (CalculateNode each : argsNodes) {
+				cache.append(each.literals()).append(',');
+			}
+			if (cache.charAt(cache.length() - 1) == ',') {
+				cache.setLength(cache.length() - 1);
+			}
+		}
+		cache.append(')');
+		return cache.toString();
+	}
+
+	@Override
+	public String toString() {
+		return literals();
+	}
+}

+ 36 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/StringNode.java

@@ -0,0 +1,36 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.token.Token;
+import com.jfireel.expression.token.TokenType;
+
+import java.util.Map;
+
+public class StringNode implements CalculateNode {
+	private String literals;
+
+	public StringNode(String literals) {
+		this.literals = literals;
+	}
+
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		return literals;
+	}
+
+	@Override
+	public TokenType type() {
+		return Token.STRING;
+	}
+
+	@Override
+	public String literals() {
+		return '\'' + literals + "'";
+	}
+
+	@Override
+	public String toString() {
+		return literals();
+	}
+
+}

+ 38 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/SymBolNode.java

@@ -0,0 +1,38 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.token.Symbol;
+import com.jfireel.expression.token.TokenType;
+
+import java.util.Map;
+
+public class SymBolNode implements CalculateNode {
+
+	private Symbol symbol;
+
+	public SymBolNode(Symbol symbol) {
+		this.symbol = symbol;
+	}
+
+	// 符号节点没有参数计算
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public TokenType type() {
+		return symbol;
+	}
+
+	@Override
+	public String toString() {
+		return literals();
+	}
+
+	@Override
+	public String literals() {
+		return symbol.getLiterals();
+	}
+
+}

+ 37 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/TypeNode.java

@@ -0,0 +1,37 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.token.Token;
+import com.jfireel.expression.token.TokenType;
+
+import java.util.Map;
+
+public class TypeNode implements CalculateNode {
+	private Class<?> ckass;
+	private Token type;
+
+	public TypeNode(Class<?> ckass, Token type) {
+		this.ckass = ckass;
+		this.type = type;
+	}
+
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		return ckass;
+	}
+
+	@Override
+	public TokenType type() {
+		return type;
+	}
+
+	@Override
+	public String literals() {
+		return ckass.getName();
+	}
+
+	public String toString() {
+		return literals();
+	}
+
+}

+ 36 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/VariableNode.java

@@ -0,0 +1,36 @@
+package com.jfireel.expression.node.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.token.Token;
+import com.jfireel.expression.token.TokenType;
+
+import java.util.Map;
+
+public class VariableNode implements CalculateNode {
+	private String literals;
+
+	public VariableNode(String literals) {
+		this.literals = literals;
+	}
+
+	@Override
+	public Object calculate(Map<String, Object> variables) {
+		return variables.get(literals);
+	}
+
+	@Override
+	public TokenType type() {
+		return Token.VARIABLE;
+	}
+
+	@Override
+	public String toString() {
+		return "VariableNode [literals=" + literals + "]";
+	}
+
+	@Override
+	public String literals() {
+		return literals;
+	}
+
+}

+ 10 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/Invoker.java

@@ -0,0 +1,10 @@
+package com.jfireel.expression.parse;
+
+import com.jfireel.expression.node.CalculateNode;
+
+import java.util.Deque;
+
+public interface Invoker {
+	int parse(String el, int offset, Deque<CalculateNode> nodes, int function);
+
+}

+ 22 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/CommaParser.java

@@ -0,0 +1,22 @@
+package com.jfireel.expression.parse.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.node.impl.SymBolNode;
+import com.jfireel.expression.parse.Invoker;
+import com.jfireel.expression.token.Symbol;
+
+import java.util.Deque;
+
+public class CommaParser extends NodeParser {
+
+	@Override
+	public int parse(String el, int offset, Deque<CalculateNode> nodes, int function, Invoker next) {
+		if (',' != getChar(offset, el)) {
+			return next.parse(el, offset, nodes, function);
+		}
+		nodes.push(new SymBolNode(Symbol.COMMA));
+		offset += 1;
+		return offset;
+	}
+
+}

+ 32 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/ConstantStringParser.java

@@ -0,0 +1,32 @@
+package com.jfireel.expression.parse.impl;
+
+import com.jfireel.exception.IllegalFormatException;
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.node.impl.StringNode;
+import com.jfireel.expression.parse.Invoker;
+
+import java.util.Deque;
+
+public class ConstantStringParser extends NodeParser {
+
+	@Override
+	public int parse(String el, int offset, Deque<CalculateNode> nodes, int function, Invoker next) {
+		if ('\'' != getChar(offset, el)) {
+			return next.parse(el, offset, nodes, function);
+		}
+		offset += 1;
+		int origin = offset;
+		int length = el.length();
+		while (offset < length && getChar(offset, el) != '\'') {
+			offset++;
+		}
+		if (getChar(offset, el) != '\'') {
+			throw new IllegalFormatException("字符串表达式没有被'包围", el.substring(origin - 1));
+		}
+		String literals = el.substring(origin, offset);
+		nodes.push(new StringNode(literals));
+		offset += 1;
+		return offset;
+	}
+
+}

+ 35 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/EnumParser.java

@@ -0,0 +1,35 @@
+package com.jfireel.expression.parse.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.node.impl.EnumNode;
+import com.jfireel.expression.parse.Invoker;
+import com.jfireel.expression.token.Token;
+import com.jfireel.expression.util.CharType;
+
+import java.util.Deque;
+
+public class EnumParser extends NodeParser {
+
+	@Override
+	public int parse(String el, int offset, Deque<CalculateNode> nodes, int function, Invoker next) {
+		// 如果是后一种情况,意味着此时应该是一个枚举值而不是属性
+		if ('.' != getChar(offset, el) || (nodes.peek() != null && nodes.peek().type() != Token.TYPE_ENUM)) {
+			return next.parse(el, offset, nodes, function);
+		}
+		int origin = offset;
+		offset += 1;
+		char c;
+		while (CharType.isAlphabet(c = getChar(offset, el)) || CharType.isDigital(c)) {
+			offset++;
+		}
+		if (c == '(') {
+			throw new IllegalArgumentException("非法的el表达式,检查:" + el.substring(origin, offset));
+		}
+		String literals = el.substring(origin + 1, offset);
+		CalculateNode beanNode = nodes.pop();
+		CalculateNode current = new EnumNode(beanNode, literals);
+		nodes.push(current);
+		return offset;
+	}
+
+}

+ 38 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/IdentifierParser.java

@@ -0,0 +1,38 @@
+package com.jfireel.expression.parse.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.node.impl.KeywordNode;
+import com.jfireel.expression.node.impl.VariableNode;
+import com.jfireel.expression.parse.Invoker;
+import com.jfireel.expression.token.DefaultKeyWord;
+import com.jfireel.expression.util.CharType;
+
+import java.util.Deque;
+
+public class IdentifierParser extends NodeParser {
+
+	@Override
+	public int parse(String el, int offset, Deque<CalculateNode> nodes, int function, Invoker next) {
+		if (CharType.isAlphabet(getChar(offset, el)) == false) {
+			return next.parse(el, offset, nodes, function);
+		}
+		return parseIdentifier(el, offset, nodes);
+	}
+
+	private int parseIdentifier(String el, int offset, Deque<CalculateNode> nodes) {
+		int length = 0;
+		char c;
+		while (CharType.isAlphabet(c = getChar(length + offset, el)) || CharType.isDigital(c)) {
+			length++;
+		}
+		String literals = el.substring(offset, offset + length);
+		offset += length;
+		if (DefaultKeyWord.getDefaultKeyWord(literals) != null) {
+			nodes.push(new KeywordNode(literals));
+		} else {
+			nodes.push(new VariableNode(literals));
+		}
+		return offset;
+	}
+
+}

+ 22 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/LeftBracketParser.java

@@ -0,0 +1,22 @@
+package com.jfireel.expression.parse.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.node.impl.SymBolNode;
+import com.jfireel.expression.parse.Invoker;
+import com.jfireel.expression.token.Symbol;
+
+import java.util.Deque;
+
+public class LeftBracketParser extends NodeParser {
+
+	@Override
+	public int parse(String el, int offset, Deque<CalculateNode> nodes, int function, Invoker next) {
+		if ('[' != getChar(offset, el)) {
+			return next.parse(el, offset, nodes, function);
+		}
+		nodes.push(new SymBolNode(Symbol.LEFT_BRACKET));
+		offset += 1;
+		return offset;
+	}
+
+}

+ 22 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/LeftParenParser.java

@@ -0,0 +1,22 @@
+package com.jfireel.expression.parse.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.node.impl.SymBolNode;
+import com.jfireel.expression.parse.Invoker;
+import com.jfireel.expression.token.Symbol;
+
+import java.util.Deque;
+
+public class LeftParenParser extends NodeParser {
+
+	@Override
+	public int parse(String el, int offset, Deque<CalculateNode> nodes, int function, Invoker next) {
+		if ('(' != getChar(offset, el)) {
+			return next.parse(el, offset, nodes, function);
+		}
+		offset += 1;
+		nodes.push(new SymBolNode(Symbol.LEFT_PAREN));
+		return offset;
+	}
+
+}

+ 49 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/MethodParser.java

@@ -0,0 +1,49 @@
+package com.jfireel.expression.parse.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.node.MethodNode;
+import com.jfireel.expression.node.impl.CompileObjectMethodNode;
+import com.jfireel.expression.node.impl.ReflectMethodNode;
+import com.jfireel.expression.node.impl.StaticObjectMethodNode;
+import com.jfireel.expression.parse.Invoker;
+import com.jfireel.expression.token.Token;
+import com.jfireel.expression.util.CharType;
+import com.jfireel.expression.util.Functions;
+
+import java.util.Deque;
+
+public class MethodParser extends NodeParser {
+
+	@Override
+	public int parse(String el, int offset, Deque<CalculateNode> nodes, int function, Invoker next) {
+		if ('.' != getChar(offset, el)) {
+			return next.parse(el, offset, nodes, function);
+		}
+		int origin = offset;
+		offset += 1;
+		char c;
+		while (CharType.isAlphabet(c = getChar(offset, el)) || CharType.isDigital(c)) {
+			offset++;
+		}
+		// 该情况意味着是属性
+		if (c != '(') {
+			return next.parse(el, offset, nodes, function);
+		}
+		String literals = el.substring(origin + 1, offset);
+		CalculateNode beanNode = nodes.pop();
+		MethodNode methodNode;
+		if (beanNode.type() == Token.TYPE) {
+			methodNode = new StaticObjectMethodNode(literals, beanNode);
+		} else {
+			if (Functions.isMethodInvokeByCompile(function)) {
+				methodNode = new CompileObjectMethodNode(literals, beanNode, Functions.isRecognizeEveryTime(function));
+			} else {
+				methodNode = new ReflectMethodNode(literals, beanNode, Functions.isRecognizeEveryTime(function));
+			}
+		}
+		nodes.push(methodNode);
+		// 当前位置是(,所以位置+1
+		offset += 1;
+		return offset;
+	}
+}

+ 40 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/NodeParser.java

@@ -0,0 +1,40 @@
+package com.jfireel.expression.parse.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.parse.Invoker;
+import com.jfireel.expression.util.CharType;
+
+import java.util.Deque;
+
+public abstract class NodeParser {
+
+	/**
+	 * 在解析节点后返回新的偏移量
+	 * 
+	 * @param el
+	 * @param offset
+	 * @param nodes
+	 * @return
+	 */
+	public abstract int parse(String el, int offset, Deque<CalculateNode> nodes, int function, Invoker next);
+
+	protected char getChar(int offset, String sentence) {
+		return offset >= sentence.length() ? (char) CharType.EOI : sentence.charAt(offset);
+	}
+
+	protected int skipWhiteSpace(int offset, String el) {
+		while (CharType.isWhitespace(getChar(offset, el))) {
+			offset++;
+		}
+		return offset;
+	}
+
+	protected int getIdentifier(int offset, String el) {
+		int length = 0;
+		char c;
+		while (CharType.isAlphabet(c = getChar(length + offset, el)) || CharType.isDigital(c)) {
+			length++;
+		}
+		return length + offset;
+	}
+}

+ 68 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/NumberParser.java

@@ -0,0 +1,68 @@
+package com.jfireel.expression.parse.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.node.impl.NumberNode;
+import com.jfireel.expression.parse.Invoker;
+import com.jfireel.expression.token.Operator;
+import com.jfireel.expression.token.Symbol;
+import com.jfireel.expression.util.CharType;
+
+import java.util.Deque;
+
+public class NumberParser extends NodeParser {
+
+	private boolean match(String el, int offset, Deque<CalculateNode> nodes, int function) {
+ 		if ('-' == getChar(offset, el)) {
+			/*// 这种情况下,-是一个操作符
+			if (nodes.peek() != null && nodes.peek().type() instanceof Operator) {
+				return false;
+			}
+			// 这种情况下,-代表是一个负数
+			if (CharType.isDigital(getChar(offset + 1, el))) {
+				return true;
+			} else {
+				throw new IllegalArgumentException("无法识别的-符号,不是负数也不是操作符,问题区间:" + el.substring(0, offset));
+			}*/
+			
+			if (nodes.peek() != null && nodes.peek().type() == Symbol.LEFT_PAREN) {
+				// 这种情况下,-代表是一个负数
+				return true;
+			} else if(nodes.peek() != null && nodes.peek().type() instanceof Operator==false) {
+				// 这种情况下,-是一个操作符
+				return false;
+			} else {
+				throw new IllegalArgumentException("无法识别的-符号,不是负数也不是操作符,问题区间:" + el.substring(0, offset));
+			}
+		} else if (CharType.isDigital(getChar(offset, el))) {
+			return true;
+		} else {
+			return false;
+		}
+	}
+
+	@Override
+	public int parse(String el, int offset, Deque<CalculateNode> nodes, int function, Invoker next) {
+		if (match(el, offset, nodes, function) == false) {
+			return next.parse(el, offset, nodes, function);
+		}
+		int index = offset;
+		char c = getChar(offset, el);
+		if (c == '-') {
+			offset += 1;
+		}
+		boolean hasDot = false;
+		while (CharType.isDigital(c = getChar(offset, el)) || (hasDot == false && c == '.')) {
+			offset++;
+			if (c == '.') {
+				hasDot = true;
+			}
+		}
+		if (c == '.') {
+			throw new IllegalArgumentException("非法的负数格式,问题区间:" + el.substring(index, offset));
+		}
+		String literals = el.substring(index, offset);
+		nodes.push(new NumberNode(literals));
+		return offset;
+	}
+
+}

+ 33 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/OperatorParser.java

@@ -0,0 +1,33 @@
+package com.jfireel.expression.parse.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.node.impl.OperatorNode;
+import com.jfireel.expression.parse.Invoker;
+import com.jfireel.expression.token.Operator;
+import com.jfireel.expression.util.CharType;
+
+import java.util.Deque;
+
+public class OperatorParser extends NodeParser {
+
+	@Override
+	public int parse(String el, int offset, Deque<CalculateNode> nodes, int function, Invoker next) {
+		if (CharType.isOperator(getChar(offset, el)) == false) {
+			return next.parse(el, offset, nodes, function);
+		}
+		String literals = new String(new char[] { getChar(offset, el), getChar(offset + 1, el) });
+		if (Operator.literalsOf(literals) != null) {
+			nodes.push(new OperatorNode(Operator.literalsOf(literals)));
+			offset += 2;
+			return offset;
+		}
+		literals = String.valueOf(getChar(offset, el));
+		if (Operator.literalsOf(literals) != null) {
+			nodes.push(new OperatorNode(Operator.literalsOf(literals)));
+			offset += 1;
+			return offset;
+		}
+		throw new IllegalArgumentException("无法识别:" + literals + "检查:" + el.substring(0, offset));
+	}
+
+}

+ 43 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/PropertyParser.java

@@ -0,0 +1,43 @@
+package com.jfireel.expression.parse.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.node.impl.ClassPropertyNode;
+import com.jfireel.expression.node.impl.ObjectPropertyNode;
+import com.jfireel.expression.parse.Invoker;
+import com.jfireel.expression.token.Token;
+import com.jfireel.expression.util.CharType;
+import com.jfireel.expression.util.Functions;
+
+import java.util.Deque;
+
+public class PropertyParser extends NodeParser {
+
+	@Override
+	public int parse(String el, int offset, Deque<CalculateNode> nodes, int function, Invoker next) {
+		// 如果是后一种情况,意味着此时应该是一个枚举值而不是属性
+		if ('.' != getChar(offset, el)//
+				|| (nodes.peek() != null && nodes.peek().type() == Token.TYPE_ENUM)) {
+			return next.parse(el, offset, nodes, function);
+		}
+		int origin = offset;
+		offset += 1;
+		char c;
+		while (CharType.isAlphabet(c = getChar(offset, el)) || CharType.isDigital(c)) {
+			offset++;
+		}
+		// 该情况意味着是方法
+		if (c == '(') {
+			return next.parse(el, origin, nodes, function);
+		}
+		String literals = el.substring(origin + 1, offset);
+		CalculateNode beanNode = nodes.pop();
+		CalculateNode current;
+		if (beanNode.type() == Token.TYPE) {
+			current = new ClassPropertyNode(literals, beanNode);
+		} else {
+			current = new ObjectPropertyNode(literals, beanNode, Functions.isRecognizeEveryTime(function));
+		}
+		nodes.push(current);
+		return offset;
+	}
+}

+ 42 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/RightBracketParser.java

@@ -0,0 +1,42 @@
+package com.jfireel.expression.parse.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.node.impl.BracketNode;
+import com.jfireel.expression.parse.Invoker;
+import com.jfireel.expression.token.Symbol;
+import com.jfireel.expression.util.OperatorResultUtil;
+
+import java.util.Deque;
+import java.util.LinkedList;
+import java.util.List;
+
+public class RightBracketParser extends NodeParser {
+
+	@Override
+	public int parse(String el, int offset, Deque<CalculateNode> nodes, int function, Invoker next) {
+		if (']' != getChar(offset, el)) {
+			return next.parse(el, offset, nodes, function);
+		}
+		List<CalculateNode> list = new LinkedList<CalculateNode>();
+		CalculateNode pred;
+		while ((pred = nodes.pollFirst()) != null) {
+			if (pred.type() != Symbol.LEFT_BRACKET) {
+				list.add(0, pred);
+			} else {
+				break;
+			}
+		}
+		if (pred == null) {
+			throw new IllegalArgumentException(el.substring(0, offset));
+		}
+		CalculateNode valueNode = OperatorResultUtil.aggregate(list, function, el, offset);
+		CalculateNode beanNode = nodes.pollFirst();
+		if (beanNode == null) {
+			throw new UnsupportedOperationException();
+		}
+		nodes.push(new BracketNode(beanNode, valueNode));
+		offset += 1;
+		return offset;
+	}
+
+}

+ 59 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/RightParenParser.java

@@ -0,0 +1,59 @@
+package com.jfireel.expression.parse.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.node.MethodNode;
+import com.jfireel.expression.parse.Invoker;
+import com.jfireel.expression.token.Symbol;
+import com.jfireel.expression.token.Token;
+import com.jfireel.expression.util.OperatorResultUtil;
+
+import java.util.Deque;
+import java.util.LinkedList;
+import java.util.List;
+
+public class RightParenParser extends NodeParser {
+
+	@Override
+	public int parse(String el, int offset, Deque<CalculateNode> nodes, int function, Invoker next) {
+		if (')' != getChar(offset, el)) {
+			return next.parse(el, offset, nodes, function);
+		}
+		List<CalculateNode> list = new LinkedList<CalculateNode>();
+		CalculateNode pred;
+		while ((pred = nodes.pollFirst()) != null) {
+			if (pred.type() != Symbol.LEFT_PAREN && pred.type() != Token.METHOD) {
+				list.add(0, pred);
+			} else {
+				break;
+			}
+		}
+		if (pred == null) {
+			throw new IllegalArgumentException(el.substring(0, offset));
+		}
+		if (pred.type() == Token.METHOD) {
+			MethodNode methodNode = (MethodNode) pred;
+			List<CalculateNode> argsNodes = new LinkedList<CalculateNode>();
+			for (int i = 0; i < list.size();) {
+				if (list.get(i).type() == Symbol.COMMA) {
+					list.remove(i);
+					argsNodes.add(OperatorResultUtil.aggregate(list.subList(0, i), function, el, offset));
+					list.remove(0);
+					i = 0;
+				} else {
+					i++;
+				}
+			}
+			if (list.isEmpty() == false) {
+				argsNodes.add(OperatorResultUtil.aggregate(list, function, el, offset));
+			}
+			methodNode.setArgsNodes(argsNodes.toArray(new CalculateNode[argsNodes.size()]));
+			offset += 1;
+			nodes.push(methodNode);
+			return offset;
+		} else {
+			nodes.push(OperatorResultUtil.aggregate(list, function, el, offset));
+			offset += 1;
+			return offset;
+		}
+	}
+}

+ 16 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/SkipIgnoredToken.java

@@ -0,0 +1,16 @@
+package com.jfireel.expression.parse.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.parse.Invoker;
+
+import java.util.Deque;
+
+public class SkipIgnoredToken extends NodeParser {
+
+	@Override
+	public int parse(String el, int offset, Deque<CalculateNode> nodes, int function, Invoker next) {
+		offset = skipWhiteSpace(offset, el);
+		return next.parse(el, offset, nodes, function);
+	}
+
+}

+ 45 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/TypeParser.java

@@ -0,0 +1,45 @@
+package com.jfireel.expression.parse.impl;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.node.impl.TypeNode;
+import com.jfireel.expression.parse.Invoker;
+import com.jfireel.expression.token.Token;
+import com.jfireel.expression.util.CharType;
+
+import java.util.Deque;
+
+public class TypeParser extends NodeParser {
+
+	@Override
+	public int parse(String el, int offset, Deque<CalculateNode> nodes, int function, Invoker next) {
+		if ('T' != getChar(offset, el) || '(' != getChar(offset + 1, el)) {
+			return next.parse(el, offset, nodes, function);
+		}
+		offset += 2;
+		offset = skipWhiteSpace(offset, el);
+		int origin = offset;
+		char c;
+		while (CharType.isAlphabet(c = getChar(offset, el)) || '.' == c || '_' == c || '$' == c) {
+			offset++;
+		}
+		int end = offset;
+		offset = skipWhiteSpace(offset, el);
+		if (')' != getChar(offset, el)) {
+			throw new IllegalArgumentException("类型操作没有被)包围,检查:" + el.substring(origin, offset));
+		}
+		String literals = el.substring(origin, end);
+		try {
+			Class<?> type = Class.forName(literals);
+			if (Enum.class.isAssignableFrom(type)) {
+				nodes.push(new TypeNode(type, Token.TYPE_ENUM));
+			} else {
+				nodes.push(new TypeNode(type, Token.TYPE));
+			}
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		offset += 1;
+		return offset;
+	}
+
+}

+ 20 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/token/DefaultKeyWord.java

@@ -0,0 +1,20 @@
+package com.jfireel.expression.token;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public enum DefaultKeyWord implements KeyWord {
+	TRUE, FALSE, NULL;
+
+	private static Map<String, DefaultKeyWord> defaultKeeyWords = new HashMap<String, DefaultKeyWord>(128);
+
+	static {
+		for (DefaultKeyWord each : DefaultKeyWord.values()) {
+			defaultKeeyWords.put(each.name().toLowerCase(), each);
+		}
+	}
+
+	public static DefaultKeyWord getDefaultKeyWord(String literals) {
+		return defaultKeeyWords.get(literals.toLowerCase());
+	}
+}

+ 5 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/token/KeyWord.java

@@ -0,0 +1,5 @@
+package com.jfireel.expression.token;
+
+public interface KeyWord extends TokenType {
+
+}

+ 58 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/token/Operator.java

@@ -0,0 +1,58 @@
+package com.jfireel.expression.token;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public enum Operator implements TokenType {
+	PLUS("+"), //
+	MINUS("-"), //
+	MULTI("*"), //
+	DIVISION("/"), //
+	QUESTION("?"), //
+	EQ("=="), //
+	GT(">"), //
+	LT("<"), //
+	PERCENT("%"), //
+	COLON(":"), //
+	LT_EQ("<="), //
+	GT_EQ(">="), //
+	NOT_EQ("!="), //
+	DOUBLE_AMP("&&"), //
+	DOUBLE_BAR("||"), //
+	;
+	private static Map<String, Operator> symbols = new HashMap<String, Operator>(128);
+	private static Set<Operator> store = new HashSet<Operator>();
+	static {
+		for (Operator each : Operator.values()) {
+			symbols.put(each.getLiterals(), each);
+			store.add(each);
+		}
+	}
+
+	private Operator(String literals) {
+		this.literals = literals;
+	}
+
+	private final String literals;
+
+	/**
+	 * 通过字面量查找词法符号.
+	 * 
+	 * @param literals
+	 *            字面量
+	 * @return 词法符号
+	 */
+	public static Operator literalsOf(final String literals) {
+		return symbols.get(literals);
+	}
+
+	public static boolean isOperator(TokenType type) {
+		return store.contains(type);
+	}
+
+	public String getLiterals() {
+		return literals;
+	}
+}

+ 42 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/token/Symbol.java

@@ -0,0 +1,42 @@
+package com.jfireel.expression.token;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public enum Symbol implements TokenType {
+	LEFT_PAREN("("), //
+	RIGHT_PAREN(")"), //
+	LEFT_BRACKET("["), //
+	RIGHT_BRACKET("]"), //
+	COMMA(",")//
+	;
+
+	private static Map<String, Symbol> symbols = new HashMap<String, Symbol>(128);
+
+	static {
+		for (Symbol each : symbols.values()) {
+			symbols.put(each.getLiterals(), each);
+		}
+	}
+
+	private Symbol(String literals) {
+		this.literals = literals;
+	}
+
+	private final String literals;
+
+	/**
+	 * 通过字面量查找词法符号.
+	 * 
+	 * @param literals
+	 *            字面量
+	 * @return 词法符号
+	 */
+	public static Symbol literalsOf(final String literals) {
+		return symbols.get(literals);
+	}
+
+	public String getLiterals() {
+		return literals;
+	}
+}

+ 34 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/token/Token.java

@@ -0,0 +1,34 @@
+package com.jfireel.expression.token;
+
+public enum Token implements TokenType {
+	// 参数变量
+	VARIABLE, //
+	// 属性访问
+	PROPERTY, //
+	// 方法访问,该节点尚未完全,需要填充参数。其本身不能作为参数值
+	METHOD, //
+	// 已经获取完毕参数的方法访问,该种节点可以作为参数值
+	METHOD_RESULT, //
+	// 字符串
+	STRING, //
+	// 数字
+	NUMBER, //
+	// 运算式结果
+	OPERATOR_RESULT, //
+	// 三元表达式
+	QUESTION, //
+	// []运算符
+	BRACKET, //
+	// Class类型
+	TYPE, //
+	// 是一个枚举类型的class
+	TYPE_ENUM, //
+	// 是一个枚举值
+	ENUM,
+	// 常量
+	CONSTANT, //
+	IF, //
+	ELSE, //
+	ELSE_IF, //
+	FOR,//
+}

+ 5 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/token/TokenType.java

@@ -0,0 +1,5 @@
+package com.jfireel.expression.token;
+
+public interface TokenType {
+
+}

+ 77 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/util/CharType.java

@@ -0,0 +1,77 @@
+package com.jfireel.expression.util;
+
+public class CharType {
+	/**
+	 * 输入结束符.
+	 */
+	public static final byte EOI = 0x1A;
+
+	/**
+	 * 判断是否为空格.
+	 * 
+	 * @param ch
+	 *            待判断的字符
+	 * @return 是否为空格
+	 */
+	public static boolean isWhitespace(final char ch) {
+		return ch == ' ';
+	}
+
+	/**
+	 * 判断是否输入结束.
+	 *
+	 * @param ch
+	 *            待判断的字符
+	 * @return 是否输入结束
+	 */
+	public static boolean isEndOfInput(final char ch) {
+		return ch == 0x1A;
+	}
+
+	/**
+	 * 判断是否为字母.
+	 *
+	 * @param ch
+	 *            待判断的字符
+	 * @return 是否为字母
+	 */
+	public static boolean isAlphabet(final char ch) {
+		return ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z';
+	}
+
+	/**
+	 * 判断是否为数字.
+	 *
+	 * @param ch
+	 *            待判断的字符
+	 * @return 是否为数字
+	 */
+	public static boolean isDigital(final char ch) {
+		return ch >= '0' && ch <= '9';
+	}
+
+	/**
+	 * 判断是否为符号.
+	 *
+	 * @param ch
+	 *            待判断的字符
+	 * @return 是否为符号
+	 */
+	public static boolean isOperator(final char ch) {
+		return '+' == ch //
+				|| '-' == ch //
+				|| '*' == ch //
+				|| '/' == ch //
+				|| '%' == ch //
+				|| '=' == ch //
+				|| '>' == ch //
+				|| '<' == ch //
+				|| '!' == ch//
+				|| '&' == ch //
+				|| '|' == ch //
+				|| '?' == ch//
+				|| ':' == ch //
+		;
+	}
+
+}

+ 31 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/util/Functional.java

@@ -0,0 +1,31 @@
+package com.jfireel.expression.util;
+
+public final class Functional {
+	private int function = 0;
+
+	public static Functional build() {
+		return new Functional();
+	}
+
+	public Functional setMethodInvokeByCompile(boolean flag) {
+		if (flag) {
+			function |= Functions.METHOD_INVOKE_BY_COMPILE;
+		} else {
+			function &= ~Functions.METHOD_INVOKE_BY_COMPILE;
+		}
+		return this;
+	}
+
+	public Functional setRecognizeEveryTime(boolean flag) {
+		if (flag) {
+			function |= Functions.RECOGNIZE_EVERY_TIME;
+		} else {
+			function &= ~Functions.RECOGNIZE_EVERY_TIME;
+		}
+		return this;
+	}
+
+	public int toFunction() {
+		return function;
+	}
+}

+ 15 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/util/Functions.java

@@ -0,0 +1,15 @@
+package com.jfireel.expression.util;
+
+public class Functions {
+	public static final int METHOD_INVOKE_BY_REFLECT = 1 << 0;
+	public static final int METHOD_INVOKE_BY_COMPILE = 1 << 1;
+	public static final int RECOGNIZE_EVERY_TIME = 1 << 2;
+
+	public static boolean isMethodInvokeByCompile(int function) {
+		return (function & METHOD_INVOKE_BY_COMPILE) != 0;
+	}
+
+	public static boolean isRecognizeEveryTime(int function) {
+		return (function & RECOGNIZE_EVERY_TIME) != 0;
+	}
+}

+ 177 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/util/OperatorResultUtil.java

@@ -0,0 +1,177 @@
+package com.jfireel.expression.util;
+
+import com.jfireel.expression.node.CalculateNode;
+import com.jfireel.expression.node.QuestionNode;
+import com.jfireel.expression.node.impl.*;
+import com.jfireel.expression.token.Operator;
+import com.jfireel.expression.token.Token;
+import com.jfireel.expression.token.TokenType;
+import com.jfirer.baseutil.StringUtil;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class OperatorResultUtil {
+	public static CalculateNode aggregate(List<CalculateNode> list, int function, String el, int offset) {
+		// 只有一个参数的情况
+		if (list.size() == 1) {
+			return list.get(0);
+		} else if (list.size() == 3) {
+			// 只有一个操作符
+			// 第二个node是操作符
+			if (Operator.class.isAssignableFrom(list.get(1).type().getClass())) {
+				return buildOperatorResultNode(list.get(0), list.get(1), list.get(2), function);
+			}
+			// 否则是非法情况
+			else {
+				throw new IllegalArgumentException(el.substring(0, offset));
+			}
+		} else if (list.size() >= 5) {
+			// 具备至少2个操作符
+			// 优先操作乘法,除法,取余
+			for (int i = 0; i < list.size();) {
+				TokenType type = list.get(i).type();
+				if (type == Operator.MULTI || type == Operator.DIVISION || type == Operator.PERCENT) {
+					if (i > 0 && list.size() > i + 1//
+							&& Operator.isOperator(list.get(i - 1).type()) == false//
+							&& Operator.isOperator(list.get(i + 1).type()) == false//
+					) {
+						CalculateNode resultNode = buildOperatorResultNode(list.get(i - 1), list.get(i),
+								list.get(i + 1), function);
+						list.remove(i - 1);
+						list.remove(i - 1);
+						list.remove(i - 1);
+						// 执行3次消除操作符和2个操作数
+						list.add(i - 1, resultNode);
+					} else {
+						throw new IllegalArgumentException(el.substring(0, offset));
+					}
+				} else {
+					i++;
+				}
+			}
+			for (int i = 0; i < list.size();) {
+				TokenType type = list.get(i).type();
+				if (type == Operator.QUESTION) {
+					if (i == 0) {
+						throw new IllegalArgumentException(
+								StringUtil.format("?操作符前面应该有操作数,问题区间:{}", el.substring(0, offset)));
+					}
+					CalculateNode pred = list.get(i - 1);
+					// 删除前置节点
+					list.remove(i - 1);
+					// 删除?节点
+					list.remove(i - 1);
+					list.add(i - 1, buildQuestionNode(pred));
+				} else if (type == Operator.COLON) {
+					list.remove(i);
+					boolean find = false;
+					List<CalculateNode> tmp = new LinkedList<CalculateNode>();
+					for (int index = i - 1; index >= 0; index--) {
+						if (list.get(index).type() != Token.QUESTION) {
+							tmp.add(0, list.get(index));
+							list.remove(index);
+						} else {
+							if (tmp.size() == 0) {
+								throw new IllegalArgumentException("?和:之间缺少有效表达式,问题区间:" + el.substring(0, offset));
+							}
+							find = true;
+							CalculateNode leftNode = aggregate(tmp, function, el, offset);
+							((QuestionNode) list.get(index)).setLeftNode(leftNode);
+							i = index + 1;
+							break;
+						}
+					}
+					if (find == false) {
+						throw new IllegalArgumentException("不是有效的三元表达式:" + el.substring(0, offset));
+					}
+					if (i >= list.size()) {
+						throw new IllegalArgumentException("不是有效的三元表达式:" + el.substring(0, offset));
+					}
+					((QuestionNode) list.get(i - 1)).setRightNode(list.get(i));
+					list.remove(i);
+				} else if (Operator.isOperator(type)) {
+					if (i > 0 && list.size() > i + 1//
+							&& Operator.isOperator(list.get(i - 1).type()) == false//
+							&& Operator.isOperator(list.get(i + 1).type()) == false//
+					) {
+						CalculateNode resultNode = buildOperatorResultNode(list.get(i - 1), list.get(i),
+								list.get(i + 1), function);
+						list.remove(i - 1);
+						list.remove(i - 1);
+						list.remove(i - 1);
+						// 执行3次消除操作符和2个操作数
+						list.add(i - 1, resultNode);
+					} else {
+						throw new IllegalArgumentException(el.substring(0, offset));
+					}
+				} else {
+					i++;
+				}
+			}
+			if (list.size() != 1) {
+				throw new IllegalArgumentException(el.substring(0, offset));
+			}
+			return list.get(0);
+		} else {
+			throw new IllegalArgumentException(el.substring(0, offset));
+		}
+	}
+
+	private static CalculateNode buildOperatorResultNode(CalculateNode leftNode, CalculateNode operatorNode,
+			CalculateNode rightNode, int function) {
+		OperatorResultNode resultNode = null;
+		switch ((Operator) operatorNode.type()) {
+		case PLUS:
+			resultNode = new PlusNode();
+			break;
+		case MULTI:
+			resultNode = new MutliNode();
+			break;
+		case EQ:
+			resultNode = new EqualNode();
+			break;
+		case NOT_EQ:
+			resultNode = new NotEqualNode();
+			break;
+		case MINUS:
+			resultNode = new MinusNode();
+			break;
+		case DIVISION:
+			resultNode = new DivisionNode();
+			break;
+		case GT:
+			resultNode = new GtNode();
+			break;
+		case LT:
+			resultNode = new LtNode();
+			break;
+		case PERCENT:
+			resultNode = new PercentNode();
+			break;
+		case GT_EQ:
+			resultNode = new GtEqNode();
+			break;
+		case LT_EQ:
+			resultNode = new LtEqNode();
+			break;
+		case DOUBLE_AMP:
+			resultNode = new DoubleAmpNode();
+			break;
+		case DOUBLE_BAR:
+			resultNode = new DoubleBarNode();
+			break;
+		default:
+			throw new UnsupportedOperationException(((Operator) operatorNode.type()).toString());
+		}
+		resultNode.setLeftOperand(leftNode);
+		resultNode.setRightOperand(rightNode);
+		return resultNode;
+	}
+
+	private static CalculateNode buildQuestionNode(CalculateNode conditionNode) {
+		QuestionNode questionNode = new QuestionNodeImpl();
+		questionNode.setConditionNode(conditionNode);
+		return questionNode;
+	}
+}

+ 91 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/util/number/DivisionUtil.java

@@ -0,0 +1,91 @@
+package com.jfireel.expression.util.number;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+public class DivisionUtil {
+	private static Object calculate(int arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 / b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 / b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 / b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 / b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+
+	private static Object calculate(long arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 / b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 / b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 / b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 / b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+
+	private static Object calculate(float arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 / b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 / b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 / b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 / b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+
+	private static Object calculate(double arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 / b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 / b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 / b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 / b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+
+	private static Object calculate(BigDecimal a, BigDecimal b) {
+		int aScale = new BigDecimal(a.toString()).scale();
+		int bScale = new BigDecimal(b.toString()).scale();
+		return a.divide(b, aScale > bScale ? aScale : bScale, BigDecimal.ROUND_HALF_UP);
+	}
+	
+	public static Object calculate(Number a, Number b) {
+		//先判断处理big类型的
+		if(a instanceof BigDecimal || b instanceof BigDecimal) {
+			return calculate(new BigDecimal(a.toString()), new BigDecimal(b.toString()));
+		} else if(a instanceof BigInteger || b instanceof BigInteger) {
+			return new BigInteger(a.toString()).divide(new BigInteger(a.toString()));
+		} else if (a instanceof Integer || a instanceof Short || a instanceof Byte) {
+			int arg0 = a.intValue();
+			return calculate(arg0, b);
+		} else if (a instanceof Long) {
+			long arg0 = a.longValue();
+			return calculate(arg0, b);
+		} else if (a instanceof Float) {
+			float arg0 = a.floatValue();
+			return calculate(arg0, b);
+		} else if (a instanceof Double) {
+			double arg0 = a.doubleValue();
+			return calculate(arg0, b);
+		} else {
+			throw new UnsupportedOperationException(a.getClass().getName() + "不支持该类型的除法操作");
+		}
+	}
+}

+ 89 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/util/number/EqUtil.java

@@ -0,0 +1,89 @@
+package com.jfireel.expression.util.number;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+public class EqUtil {
+	private static boolean calculate(int arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 == b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 == b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 == b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 == b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+
+	private static boolean calculate(long arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 == b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 == b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 == b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 == b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+
+	private static boolean calculate(float arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 == b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 == b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 == b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 == b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+
+	private static boolean calculate(double arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 == b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 == b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 == b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 == b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+	
+	private static boolean calculate(BigDecimal a, BigDecimal b) {
+		return a.compareTo(b) == 0;
+	}
+
+	public static boolean calculate(Number a, Number b) {
+		//先判断处理big类型的
+		if(a instanceof BigDecimal || b instanceof BigDecimal) {
+			return calculate(new BigDecimal(a.toString()), new BigDecimal(b.toString()));
+		} else if(a instanceof BigInteger || b instanceof BigInteger) {
+			return new BigInteger(a.toString()).compareTo(new BigInteger(a.toString())) == 0;
+		} else if (a instanceof Integer || a instanceof Short || a instanceof Byte) {
+			int arg0 = a.intValue();
+			return calculate(arg0, b);
+		} else if (a instanceof Long) {
+			long arg0 = a.longValue();
+			return calculate(arg0, b);
+		} else if (a instanceof Float) {
+			float arg0 = a.floatValue();
+			return calculate(arg0, b);
+		} else if (a instanceof Double) {
+			double arg0 = a.doubleValue();
+			return calculate(arg0, b);
+		} else {
+			throw new UnsupportedOperationException(a.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+}

+ 89 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/util/number/GtUtil.java

@@ -0,0 +1,89 @@
+package com.jfireel.expression.util.number;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+public class GtUtil {
+	private static Object calculate(int arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 > b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 > b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 > b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 > b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+
+	private static Object calculate(long arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 > b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 > b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 > b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 > b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+
+	private static Object calculate(float arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 > b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 > b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 > b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 > b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+
+	private static Object calculate(double arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 > b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 > b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 > b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 > b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+	
+	private static Object calculate(BigDecimal a, BigDecimal b) {
+		return a.compareTo(b) == 1;
+	}
+
+	public static Object calculate(Number a, Number b) {
+		//先判断处理big类型的
+		if(a instanceof BigDecimal || b instanceof BigDecimal) {
+			return calculate(new BigDecimal(a.toString()), new BigDecimal(b.toString()));
+		} else if(a instanceof BigInteger || b instanceof BigInteger) {
+			return new BigInteger(a.toString()).compareTo(new BigInteger(a.toString())) == 1;
+		} else if (a instanceof Integer || a instanceof Short || a instanceof Byte) {
+			int arg0 = a.intValue();
+			return calculate(arg0, b);
+		} else if (a instanceof Long) {
+			long arg0 = a.longValue();
+			return calculate(arg0, b);
+		} else if (a instanceof Float) {
+			float arg0 = a.floatValue();
+			return calculate(arg0, b);
+		} else if (a instanceof Double) {
+			double arg0 = a.doubleValue();
+			return calculate(arg0, b);
+		} else {
+			throw new UnsupportedOperationException(a.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+}

+ 89 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/util/number/LtUtil.java

@@ -0,0 +1,89 @@
+package com.jfireel.expression.util.number;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+public class LtUtil {
+	private static Object calculate(int arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 < b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 < b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 < b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 < b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+
+	private static Object calculate(long arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 < b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 < b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 < b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 < b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+
+	private static Object calculate(float arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 < b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 < b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 < b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 < b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+
+	private static Object calculate(double arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 < b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 < b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 < b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 < b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+	
+	private static Object calculate(BigDecimal a, BigDecimal b) {
+		return a.compareTo(b) == -1;
+	}
+
+	public static Object calculate(Number a, Number b) {
+		//先判断处理big类型的
+		if(a instanceof BigDecimal || b instanceof BigDecimal) {
+			return calculate(new BigDecimal(a.toString()), new BigDecimal(b.toString()));
+		} else if(a instanceof BigInteger || b instanceof BigInteger) {
+			return new BigInteger(a.toString()).compareTo(new BigInteger(a.toString())) == -1;
+		} else if (a instanceof Integer || a instanceof Short || a instanceof Byte) {
+			int arg0 = a.intValue();
+			return calculate(arg0, b);
+		} else if (a instanceof Long) {
+			long arg0 = a.longValue();
+			return calculate(arg0, b);
+		} else if (a instanceof Float) {
+			float arg0 = a.floatValue();
+			return calculate(arg0, b);
+		} else if (a instanceof Double) {
+			double arg0 = a.doubleValue();
+			return calculate(arg0, b);
+		} else {
+			throw new UnsupportedOperationException(a.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+}

+ 91 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/util/number/MultiplyUtil.java

@@ -0,0 +1,91 @@
+package com.jfireel.expression.util.number;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+public class MultiplyUtil {
+	private static Object calculate(int arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 * b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 * b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 * b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 * b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+
+	private static Object calculate(long arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 * b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 * b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 * b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 * b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+
+	private static Object calculate(float arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 * b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 * b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 * b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 * b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+
+	private static Object calculate(double arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 * b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 * b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 * b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 * b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+	
+	private static Object calculate(BigDecimal a, BigDecimal b) {
+		int aScale = new BigDecimal(a.toString()).scale();
+		int bScale = new BigDecimal(b.toString()).scale();
+		return a.multiply(b).setScale(aScale > bScale ? aScale : bScale, BigDecimal.ROUND_HALF_UP);
+	}
+	
+	public static Object calculate(Number a, Number b) {
+		//先判断处理big类型的
+		if(a instanceof BigDecimal || b instanceof BigDecimal) {
+			return calculate(new BigDecimal(a.toString()), new BigDecimal(b.toString()));
+		} else if(a instanceof BigInteger || b instanceof BigInteger) {
+			return new BigInteger(a.toString()).multiply(new BigInteger(a.toString()));
+		} else if (a instanceof Integer || a instanceof Short || a instanceof Byte) {
+			int arg0 = a.intValue();
+			return calculate(arg0, b);
+		} else if (a instanceof Long) {
+			long arg0 = a.longValue();
+			return calculate(arg0, b);
+		} else if (a instanceof Float) {
+			float arg0 = a.floatValue();
+			return calculate(arg0, b);
+		} else if (a instanceof Double) {
+			double arg0 = a.doubleValue();
+			return calculate(arg0, b);
+		} else {
+			throw new UnsupportedOperationException(a.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+}

+ 91 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/util/number/PlusUtil.java

@@ -0,0 +1,91 @@
+package com.jfireel.expression.util.number;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+public class PlusUtil {
+	private static Object calculate(int arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 + b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 + b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 + b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 + b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+
+	private static Object calculate(long arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 + b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 + b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 + b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 + b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+
+	private static Object calculate(float arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 + b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 + b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 + b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 + b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+
+	private static Object calculate(double arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 + b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 + b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 + b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 + b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+	
+	private static Object calculate(BigDecimal a, BigDecimal b) {
+		int aScale = new BigDecimal(a.toString()).scale();
+		int bScale = new BigDecimal(b.toString()).scale();
+		return a.add(b).setScale(aScale > bScale ? aScale : bScale, BigDecimal.ROUND_HALF_UP);
+	}
+
+	public static Object calculate(Number a, Number b) {
+		//先判断出来big类型的
+		if(a instanceof BigDecimal || b instanceof BigDecimal) {
+			return calculate(new BigDecimal(a.toString()), new BigDecimal(b.toString()));
+		} else if(a instanceof BigInteger || b instanceof BigInteger) {
+			return new BigInteger(a.toString()).add(new BigInteger(a.toString()));
+		} else if (a instanceof Integer || a instanceof Short || a instanceof Byte) {
+			int arg0 = a.intValue();
+			return calculate(arg0, b);
+		} else if (a instanceof Long) {
+			long arg0 = a.longValue();
+			return calculate(arg0, b);
+		} else if (a instanceof Float) {
+			float arg0 = a.floatValue();
+			return calculate(arg0, b);
+		} else if (a instanceof Double) {
+			double arg0 = a.doubleValue();
+			return calculate(arg0, b);
+		} else {
+			throw new UnsupportedOperationException(a.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+}

+ 91 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/util/number/RemainderUtil.java

@@ -0,0 +1,91 @@
+package com.jfireel.expression.util.number;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+public class RemainderUtil {
+	private static Object calculate(int arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 % b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 % b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 % b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 % b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+
+	private static Object calculate(long arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 % b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 % b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 % b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 % b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+
+	private static Object calculate(float arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 % b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 % b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 % b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 % b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+
+	private static Object calculate(double arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 % b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 % b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 % b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 % b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+	
+	private static Object calculate(BigDecimal a, BigDecimal b) {
+		int aScale = new BigDecimal(a.toString()).scale();
+		int bScale = new BigDecimal(b.toString()).scale();
+		return a.remainder(b).setScale( aScale > bScale ? aScale : bScale, BigDecimal.ROUND_HALF_UP);
+	}
+
+	public static Object calculate(Number a, Number b) {
+		//先判断处理big类型的
+		if(a instanceof BigDecimal || b instanceof BigDecimal) {
+			return calculate(new BigDecimal(a.toString()), new BigDecimal(b.toString()));
+		} else if(a instanceof BigInteger || b instanceof BigInteger) {
+			return new BigInteger(a.toString()).remainder(new BigInteger(a.toString()));
+		} else if (a instanceof Integer || a instanceof Short || a instanceof Byte) {
+			int arg0 = a.intValue();
+			return calculate(arg0, b);
+		} else if (a instanceof Long) {
+			long arg0 = a.longValue();
+			return calculate(arg0, b);
+		} else if (a instanceof Float) {
+			float arg0 = a.floatValue();
+			return calculate(arg0, b);
+		} else if (a instanceof Double) {
+			double arg0 = a.doubleValue();
+			return calculate(arg0, b);
+		} else {
+			throw new UnsupportedOperationException(a.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+}

+ 91 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/util/number/SubtractUtil.java

@@ -0,0 +1,91 @@
+package com.jfireel.expression.util.number;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+public class SubtractUtil {
+	private static Object calculate(int arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 - b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 - b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 - b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 - b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+
+	private static Object calculate(long arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 - b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 - b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 - b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 - b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+
+	private static Object calculate(float arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 - b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 - b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 - b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 - b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+
+	private static Object calculate(double arg0, Number b) {
+		if (b instanceof Integer || b instanceof Short || b instanceof Byte) {
+			return arg0 - b.intValue();
+		} else if (b instanceof Long) {
+			return arg0 - b.longValue();
+		} else if (b instanceof Float) {
+			return arg0 - b.floatValue();
+		} else if (b instanceof Double) {
+			return arg0 - b.doubleValue();
+		} else {
+			throw new UnsupportedOperationException(b.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+
+	private static Object calculate(BigDecimal a, BigDecimal b) {
+		int aScale = new BigDecimal(a.toString()).scale();
+		int bScale = new BigDecimal(b.toString()).scale();
+		return a.subtract(b).setScale(aScale > bScale ? aScale : bScale, BigDecimal.ROUND_HALF_UP);
+	}
+	
+	public static Object calculate(Number a, Number b) {
+		//先判断处理big类型的
+		if(a instanceof BigDecimal || b instanceof BigDecimal) {
+			return calculate(new BigDecimal(a.toString()), new BigDecimal(b.toString()));
+		} else if(a instanceof BigInteger || b instanceof BigInteger) {
+			return new BigInteger(a.toString()).subtract(new BigInteger(a.toString()));
+		} else if (a instanceof Integer || a instanceof Short || a instanceof Byte) {
+			int arg0 = a.intValue();
+			return calculate(arg0, b);
+		} else if (a instanceof Long) {
+			long arg0 = a.longValue();
+			return calculate(arg0, b);
+		} else if (a instanceof Float) {
+			float arg0 = a.floatValue();
+			return calculate(arg0, b);
+		} else if (a instanceof Double) {
+			double arg0 = a.doubleValue();
+			return calculate(arg0, b);
+		} else {
+			throw new UnsupportedOperationException(a.getClass().getName() + "不支持该类型的加操作");
+		}
+	}
+}

+ 9 - 0
blade-service/blade-manager/src/main/java/com/jfireel/template/ScanMode.java

@@ -0,0 +1,9 @@
+package com.jfireel.template;
+
+public enum ScanMode
+{
+    // 字符串
+    LITERALS, //
+    // 执行语句.说明当前处于<%%>包围之中
+    EXECUTION, //
+}

+ 108 - 0
blade-service/blade-manager/src/main/java/com/jfireel/template/Template.java

@@ -0,0 +1,108 @@
+package com.jfireel.template;
+
+import com.jfireel.exception.IllegalFormatException;
+import com.jfireel.template.execution.Execution;
+import com.jfireel.template.execution.impl.StringExecution;
+import com.jfireel.template.parser.Invoker;
+import com.jfireel.template.parser.Parser;
+import com.jfireel.template.parser.impl.*;
+
+import java.util.Deque;
+import java.util.LinkedList;
+import java.util.Map;
+
+public class Template {
+	private static final ThreadLocal<StringBuilder> LOCAL = new ThreadLocal<StringBuilder>() {
+		@Override
+		protected StringBuilder initialValue() {
+			return new StringBuilder();
+		};
+	};
+	private Deque<Execution> executions = new LinkedList<Execution>();
+	private Execution[] runtimeExecutions;
+	private ScanMode mode = ScanMode.LITERALS;
+	private Invoker head = DEFAULT_HEAD;
+	private static final Invoker DEFAULT_HEAD;
+	static {
+		Parser[] parsers = new Parser[] { //
+				new ExecutionBeginParser(), //
+				new ExecutionEndParser(), //
+				new IfParser(), //
+				new ElseParser(), //
+				new ForEachParser(), //
+				new EndBraceParser(), //
+				new ExpressionParser(), //
+				new LiteralsParser(), //
+
+		};
+		Invoker pred = new Invoker() {
+
+			@Override
+			public int scan(String sentence, int offset, Deque<Execution> executions, Template template,
+					StringBuilder cache) {
+				return offset;
+			}
+		};
+		for (int i = parsers.length - 1; i > -1; i--) {
+			final Parser parser = parsers[i];
+			final Invoker next = pred;
+			Invoker invoker = new Invoker() {
+
+				@Override
+				public int scan(String sentence, int offset, Deque<Execution> executions, Template template,
+						StringBuilder cache) {
+					return parser.parse(sentence, offset, executions, template, cache, next);
+				}
+			};
+			pred = invoker;
+		}
+		DEFAULT_HEAD = pred;
+	}
+
+	public ScanMode getMode() {
+		return mode;
+	}
+
+	public void setMode(ScanMode mode) {
+		this.mode = mode;
+	}
+
+	private Template(String sentence) {
+		StringBuilder cache = new StringBuilder();
+		int offset = 0;
+		int length = sentence.length();
+		mode = ScanMode.LITERALS;
+		while (offset < length) {
+			int result = head.scan(sentence, offset, executions, this, cache);
+			if (result == offset) {
+				throw new IllegalFormatException("没有解析器可以识别", sentence.substring(0, offset));
+			}
+			offset = result;
+		}
+		if (cache.length() != 0) {
+			Execution execution = new StringExecution(cache.toString());
+			executions.push(execution);
+		}
+		Deque<Execution> array = new LinkedList<Execution>();
+		while (executions.isEmpty() == false) {
+			array.push(executions.pollFirst());
+		}
+		runtimeExecutions = array.toArray(new Execution[0]);
+		executions = null;
+		mode = null;
+	}
+
+	public String render(Map<String, Object> variables) {
+		StringBuilder cache = LOCAL.get();
+		for (Execution execution : runtimeExecutions) {
+			execution.execute(variables, cache);
+		}
+		String result = cache.toString();
+		cache.setLength(0);
+		return result;
+	}
+
+	public static Template parse(String sentence) {
+		return new Template(sentence);
+	}
+}

+ 21 - 0
blade-service/blade-manager/src/main/java/com/jfireel/template/execution/Execution.java

@@ -0,0 +1,21 @@
+package com.jfireel.template.execution;
+
+import java.util.Map;
+
+public interface Execution
+{
+
+    /**
+     * 语句是否已经执行
+     *
+     * @param variables
+     * @param cache
+     * @return
+     */
+    boolean execute(Map<String, Object> variables, StringBuilder cache);
+
+    /**
+     * 在所有的执行语句都生成完毕后会执行一次校验
+     */
+    void check();
+}

+ 6 - 0
blade-service/blade-manager/src/main/java/com/jfireel/template/execution/InvokerOnExecute.java

@@ -0,0 +1,6 @@
+package com.jfireel.template.execution;
+
+public interface InvokerOnExecute
+{
+    void invoke(Object value);
+}

+ 8 - 0
blade-service/blade-manager/src/main/java/com/jfireel/template/execution/WithBodyExecution.java

@@ -0,0 +1,8 @@
+package com.jfireel.template.execution;
+
+public interface WithBodyExecution extends Execution
+{
+    void setBody(Execution... executions);
+    
+    boolean isBodyNotSet();
+}

+ 40 - 0
blade-service/blade-manager/src/main/java/com/jfireel/template/execution/impl/ElseExecution.java

@@ -0,0 +1,40 @@
+package com.jfireel.template.execution.impl;
+
+import com.jfireel.template.execution.Execution;
+import com.jfireel.template.execution.WithBodyExecution;
+
+import java.util.Map;
+
+public class ElseExecution implements WithBodyExecution
+{
+    private Execution[] body;
+    
+    @Override
+    public boolean execute(Map<String, Object> variables, StringBuilder cache)
+    {
+        for (Execution each : body)
+        {
+            each.execute(variables, cache);
+        }
+        return true;
+    }
+    
+    @Override
+    public void check()
+    {
+        // TODO Auto-generated method stub
+        
+    }
+    
+    @Override
+    public void setBody(Execution... executions)
+    {
+        body = executions;
+    }
+    
+    @Override
+    public boolean isBodyNotSet()
+    {
+        return body == null;
+    }
+}

+ 52 - 0
blade-service/blade-manager/src/main/java/com/jfireel/template/execution/impl/ElseIfExecution.java

@@ -0,0 +1,52 @@
+package com.jfireel.template.execution.impl;
+
+import com.jfireel.expression.Expression;
+import com.jfireel.template.execution.Execution;
+import com.jfireel.template.execution.WithBodyExecution;
+
+import java.util.Map;
+
+public class ElseIfExecution implements WithBodyExecution
+{
+    private Expression  expression;
+    private Execution[] body;
+    
+    public ElseIfExecution(Expression expression)
+    {
+        this.expression = expression;
+    }
+    
+    @Override
+    public boolean execute(Map<String, Object> variables, StringBuilder cache)
+    {
+        if ((boolean) expression.calculate(variables))
+        {
+            for (Execution each : body)
+            {
+                each.execute(variables, cache);
+            }
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+    
+    @Override
+    public void check()
+    {
+    }
+    
+    @Override
+    public void setBody(Execution... executions)
+    {
+        body = executions;
+    }
+    
+    @Override
+    public boolean isBodyNotSet()
+    {
+        return body == null;
+    }
+}

+ 35 - 0
blade-service/blade-manager/src/main/java/com/jfireel/template/execution/impl/ExpressionExecution.java

@@ -0,0 +1,35 @@
+package com.jfireel.template.execution.impl;
+
+import com.jfireel.expression.Expression;
+import com.jfireel.template.execution.Execution;
+
+import java.util.Map;
+
+public class ExpressionExecution implements Execution
+{
+    private Expression expression;
+    
+    public ExpressionExecution(Expression expression)
+    {
+        this.expression = expression;
+    }
+    
+    @Override
+    public boolean execute(Map<String, Object> variables, StringBuilder cache)
+    {
+        Object result = expression.calculate(variables);
+        if (result != null)
+        {
+            cache.append(result);
+        }
+        return true;
+    }
+    
+    @Override
+    public void check()
+    {
+        // TODO Auto-generated method stub
+        
+    }
+    
+}

+ 63 - 0
blade-service/blade-manager/src/main/java/com/jfireel/template/execution/impl/ForEachExecution.java

@@ -0,0 +1,63 @@
+package com.jfireel.template.execution.impl;
+
+import com.jfireel.expression.Expression;
+import com.jfireel.template.execution.Execution;
+import com.jfireel.template.execution.WithBodyExecution;
+
+import java.util.Collection;
+import java.util.Map;
+
+public class ForEachExecution implements WithBodyExecution
+{
+    private Execution[] body;
+    private String      itemName;
+    private Expression  collection;
+    
+    public ForEachExecution(String itemName, Expression collection)
+    {
+        this.itemName = itemName;
+        this.collection = collection;
+    }
+    
+    @Override
+    public boolean execute(Map<String, Object> variables, StringBuilder cache)
+    {
+        Object result = collection.calculate(variables);
+        if (result == null)
+        {
+            return true;
+        }
+        if (result instanceof Collection<?>)
+        {
+            for (Object each : ((Collection<?>) result))
+            {
+                variables.put(itemName, each);
+                for (Execution execution : body)
+                {
+                    execution.execute(variables, cache);
+                }
+            }
+            variables.remove(itemName);
+        }
+        return true;
+    }
+    
+    @Override
+    public void check()
+    {
+        // TODO Auto-generated method stub
+        
+    }
+    
+    @Override
+    public void setBody(Execution... executions)
+    {
+        body = executions;
+    }
+    
+    @Override
+    public boolean isBodyNotSet()
+    {
+        return body == null;
+    }
+}

+ 85 - 0
blade-service/blade-manager/src/main/java/com/jfireel/template/execution/impl/IfExecution.java

@@ -0,0 +1,85 @@
+package com.jfireel.template.execution.impl;
+
+import com.jfireel.expression.Expression;
+import com.jfireel.template.execution.Execution;
+import com.jfireel.template.execution.WithBodyExecution;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+public class IfExecution implements WithBodyExecution
+{
+    
+    private Expression  conditionLexer;
+    private Execution[] body;
+    private Execution       elseExecution;
+    private List<Execution> elseIfExecutions = new LinkedList<Execution>();
+    
+    public IfExecution(Expression conditionLexer)
+    {
+        this.conditionLexer = conditionLexer;
+    }
+    
+    @Override
+    public boolean execute(Map<String, Object> variables, StringBuilder cache)
+    {
+        Object result = conditionLexer.calculate(variables);
+        if (result == null)
+        {
+            throw new IllegalArgumentException("参数不存在,导致无法计算条件表达式");
+        }
+        if ((Boolean) result)
+        {
+            for (Execution each : body)
+            {
+                each.execute(variables, cache);
+            }
+        }
+        else
+        {
+            for (Execution execution : elseIfExecutions)
+            {
+                if (execution.execute(variables, cache))
+                {
+                    return true;
+                }
+            }
+            if (elseExecution != null)
+            {
+                elseExecution.execute(variables, cache);
+            }
+        }
+        return true;
+    }
+    
+    public void addElseIf(ElseIfExecution execution)
+    {
+        elseIfExecutions.add(execution);
+    }
+    
+    public void setElse(ElseExecution execution)
+    {
+        elseExecution = execution;
+    }
+    
+    @Override
+    public void check()
+    {
+        // TODO Auto-generated method stub
+        
+    }
+    
+    @Override
+    public void setBody(Execution... executions)
+    {
+        body = executions;
+    }
+    
+    @Override
+    public boolean isBodyNotSet()
+    {
+        return body == null;
+    }
+    
+}

+ 29 - 0
blade-service/blade-manager/src/main/java/com/jfireel/template/execution/impl/StringExecution.java

@@ -0,0 +1,29 @@
+package com.jfireel.template.execution.impl;
+
+import com.jfireel.template.execution.Execution;
+
+import java.util.Map;
+
+public class StringExecution implements Execution
+{
+    private String literals;
+    
+    public StringExecution(String literals)
+    {
+        this.literals = literals;
+    }
+    
+    @Override
+    public boolean execute(Map<String, Object> variables, StringBuilder cache)
+    {
+        cache.append(literals);
+        return true;
+    }
+    
+    @Override
+    public void check()
+    {
+        
+    }
+    
+}

+ 11 - 0
blade-service/blade-manager/src/main/java/com/jfireel/template/parser/Invoker.java

@@ -0,0 +1,11 @@
+package com.jfireel.template.parser;
+
+import com.jfireel.template.Template;
+import com.jfireel.template.execution.Execution;
+
+import java.util.Deque;
+
+public interface Invoker
+{
+    int scan(String sentence, int offset, Deque<Execution> executions, Template template, StringBuilder cache);
+}

+ 116 - 0
blade-service/blade-manager/src/main/java/com/jfireel/template/parser/Parser.java

@@ -0,0 +1,116 @@
+package com.jfireel.template.parser;
+
+import com.jfireel.exception.IllegalFormatException;
+import com.jfireel.expression.util.CharType;
+import com.jfireel.template.Template;
+import com.jfireel.template.execution.Execution;
+import com.jfireel.template.execution.impl.StringExecution;
+
+import java.util.Deque;
+
+public abstract class Parser {
+
+	protected static final Execution[] emptyBody = new Execution[0];
+
+	public abstract int parse(String sentence, int offset, Deque<Execution> executions, Template template,
+			StringBuilder cache, Invoker next);
+
+	/**
+	 * 查询{的位置,如果查询不到抛出异常。如果查询到,则返回{位置+1的结果
+	 *
+	 * @param sentence
+	 * @param offset
+	 * @return
+	 */
+	protected int findMethodBodyBegin(String sentence, int offset) {
+		offset = skipWhiteSpace(offset, sentence);
+		if ('{' != getChar(offset, sentence)) {
+			throw new IllegalFormatException("方法体没有以{开始", sentence.substring(0, offset));
+		}
+		offset++;
+		return offset;
+	}
+
+	protected void extractLiterals(StringBuilder cache, Deque<Execution> executions) {
+		if (cache.length() != 0) {
+			Execution execution = new StringExecution(cache.toString());
+			cache.setLength(0);
+			executions.push(execution);
+		}
+	}
+
+	protected char getChar(int offset, String sentence) {
+		return offset >= sentence.length() ? (char) CharType.EOI : sentence.charAt(offset);
+	}
+
+	protected int skipWhiteSpace(int offset, String el) {
+		while (CharType.isWhitespace(getChar(offset, el))) {
+			offset++;
+		}
+		return offset;
+	}
+
+	protected boolean isExecutionBegin(int offset, String sentence) {
+		char c1 = getChar(offset, sentence);
+		char c2 = getChar(offset + 1, sentence);
+		if (c1 != '<' || c2 != '%') {
+			return false;
+		}
+		return true;
+	}
+
+	/**
+	 * offset当前位置为'(',寻找与之配对的)结束符.返回寻找到)位置。如果找不到,则返回-1
+	 *
+	 * @param sentence
+	 * @param offset
+	 * @return
+	 */
+	protected int findEndRightBracket(String sentence, int offset) {
+		offset++;
+		int length = sentence.length();
+		int countForLeftBracket = 0;
+		do {
+			char c = getChar(offset, sentence);
+			if (c == '(') {
+				countForLeftBracket++;
+			} else if (c == ')') {
+				if (countForLeftBracket > 0) {
+					countForLeftBracket--;
+				} else {
+					// 此时找到if的括号的封闭括号
+					break;
+				}
+			}
+			offset++;
+		} while (offset < length);
+		if (offset >= length) {
+			return -1;
+		}
+		return offset;
+	}
+
+	/**
+	 * 搜索执行语句的结尾,也就是%>所在位置。返回>的坐标。如果没有找到,返回-1
+	 *
+	 * @param startIndex
+	 * @param sentence
+	 * @return
+	 */
+	protected int findExectionEnd(int startIndex, String sentence) {
+		int offset = startIndex;
+		int length = sentence.length();
+		while (offset < length) {
+			char c = getChar(offset, sentence);
+			if (c == '%') {
+				offset = skipWhiteSpace(offset + 1, sentence);
+				c = getChar(offset, sentence);
+				if (c == '>') {
+					return offset;
+				}
+			}
+			offset++;
+		}
+		return -1;
+	}
+}

+ 58 - 0
blade-service/blade-manager/src/main/java/com/jfireel/template/parser/impl/ElseParser.java

@@ -0,0 +1,58 @@
+package com.jfireel.template.parser.impl;
+
+import com.jfireel.exception.IllegalFormatException;
+import com.jfireel.expression.Expression;
+import com.jfireel.template.ScanMode;
+import com.jfireel.template.Template;
+import com.jfireel.template.execution.Execution;
+import com.jfireel.template.execution.impl.ElseExecution;
+import com.jfireel.template.execution.impl.ElseIfExecution;
+import com.jfireel.template.parser.Invoker;
+import com.jfireel.template.parser.Parser;
+
+import java.util.Deque;
+
+public class ElseParser extends Parser {
+
+	@Override
+	public int parse(String sentence, int offset, Deque<Execution> executions, Template template, StringBuilder cache,
+			Invoker next) {
+		if (template.getMode() != ScanMode.EXECUTION) {
+			return next.scan(sentence, offset, executions, template, cache);
+		}
+		if (getChar(offset, sentence) != 'e'//
+				|| getChar(offset + 1, sentence) != 'l' //
+				|| getChar(offset + 2, sentence) != 's'//
+				|| getChar(offset + 3, sentence) != 'e'//
+		) {
+			return next.scan(sentence, offset, executions, template, cache);
+		}
+		offset = skipWhiteSpace(offset + 4, sentence);
+		// 此种情况意味着是一个单纯的else
+		if (getChar(offset, sentence) == '{') {
+			ElseExecution execution = new ElseExecution();
+			executions.push(execution);
+			offset++;
+			return offset;
+		} else if (getChar(offset, sentence) == 'i' && getChar(offset + 1, sentence) == 'f') {
+			offset = skipWhiteSpace(offset + 2, sentence);
+			if (getChar(offset, sentence) != '(') {
+				throw new IllegalFormatException("else if的条件没有以(开始", sentence.substring(0, offset));
+			}
+			int leftBracketIndex = offset;
+			offset = findEndRightBracket(sentence, offset);
+			if (offset == -1) {
+				throw new IllegalFormatException("else if的条件没有以)结束", sentence.substring(0, leftBracketIndex));
+			}
+			ElseIfExecution execution = new ElseIfExecution(
+					Expression.parse(sentence.substring(leftBracketIndex + 1, offset)));
+			executions.push(execution);
+			offset++;
+			offset = findMethodBodyBegin(sentence, offset);
+			return offset;
+		} else {
+			throw new IllegalFormatException("无法识别的语法内容", sentence.substring(0, offset));
+		}
+	}
+
+}

+ 55 - 0
blade-service/blade-manager/src/main/java/com/jfireel/template/parser/impl/EndBraceParser.java

@@ -0,0 +1,55 @@
+package com.jfireel.template.parser.impl;
+
+import com.jfireel.exception.IllegalFormatException;
+import com.jfireel.template.ScanMode;
+import com.jfireel.template.Template;
+import com.jfireel.template.execution.Execution;
+import com.jfireel.template.execution.WithBodyExecution;
+import com.jfireel.template.execution.impl.ElseExecution;
+import com.jfireel.template.execution.impl.ElseIfExecution;
+import com.jfireel.template.execution.impl.IfExecution;
+import com.jfireel.template.parser.Invoker;
+import com.jfireel.template.parser.Parser;
+
+import java.util.Deque;
+import java.util.LinkedList;
+
+public class EndBraceParser extends Parser {
+
+	@Override
+	public int parse(String sentence, int offset, Deque<Execution> executions, Template template, StringBuilder cache,
+			Invoker next) {
+		if (template.getMode() != ScanMode.EXECUTION || getChar(offset, sentence) != '}') {
+			return next.scan(sentence, offset, executions, template, cache);
+		}
+		Deque<Execution> array = new LinkedList<Execution>();
+		Execution pop;
+		while ((pop = executions.pollFirst()) != null) {
+			if (pop instanceof WithBodyExecution == false || ((WithBodyExecution) pop).isBodyNotSet() == false) {
+				array.push(pop);
+			} else {
+				break;
+			}
+		}
+		if (pop == null) {
+			throw new IllegalFormatException("结束符}前面没有开始符号", sentence.substring(0, offset));
+		}
+		((WithBodyExecution) pop).setBody(array.toArray(emptyBody));
+		if (pop instanceof ElseExecution) {
+			if (executions.peek() == null || executions.peek() instanceof IfExecution == false) {
+				throw new IllegalFormatException("else 节点之前没有if节点", sentence.substring(0, offset));
+			}
+			((IfExecution) executions.peek()).setElse((ElseExecution) pop);
+		} else if (pop instanceof ElseIfExecution) {
+			if (executions.peek() == null || executions.peek() instanceof IfExecution == false) {
+				throw new IllegalFormatException("else if 节点之前没有if节点", sentence.substring(0, offset));
+			}
+			((IfExecution) executions.peek()).addElseIf((ElseIfExecution) pop);
+		} else {
+			executions.push(pop);
+		}
+		offset += 1;
+		return offset;
+	}
+
+}

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio