content: package com.alibaba.markovdemo.engine.util;
  
  import com.alibaba.fastjson.JSON;
  import com.alibaba.fastjson.JSONArray;
  import com.alibaba.fastjson.JSONObject;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  
  import java.io.*;
  import java.lang.reflect.Field;
  import java.lang.reflect.Method;
  import java.net.InetAddress;
  import java.text.ParseException;
  import java.text.SimpleDateFormat;
  import java.util.*;
  import java.util.regex.Matcher;
  import java.util.regex.Pattern;
  import java.util.zip.CRC32;
  
  public class Toolkit {
      private static final Logger logger = LoggerFactory.getLogger(Toolkit.class);
  
  
      private static String IGNORE_FIELDS = "ignoreFields";
      private static String PREGMATCH_FIELDS = "pregMatchFields";
      private static String NUMCHECKFIELDS = "numCheckFields";
      private static String CALL_FUNC_FIELDS = "callFuncFields";
      private static String NON_EXSIT_FIELDS = "nonExsitFields";
  
      private static String UNSORT_FIELDS = "unsortFields";
      private static String COUNT_FIELDS = "countFields";
  
      private static String ACTUAL = "actual";
      private static String EXPECT = "expect";
      private static String IS_SUCCESS = "isSuccess";
      private static String MESSAGE = "message";
  
      private static String SORT_TYPE = "sort";
      private static String REMOVE_TYPE = "remove";
      private static String COUNT_TYPE = "count";
      private static String NUM_CHECK_TYPE = "num_check";
  
      private static String PREG_MATCH_CHECK = "字段值正则匹配不相等!";
      private static String NON_EXSIT_CHECK = "字段不应该存在!";
      private static String FUNC_CHECK = "字段值函数化处理后不相等!";
      private static String VALUE_CHECK = "字段值不相等!";
      private static String KEY_NO_EXIST_CHECK = "字段在实际结果中不存在!!";
      private static String IGNORE_CAL = "实际返回已忽略字段，如下:";
      private static String SORT_CAL = "实际返回已将无序字段处理为有序，如下:";
      private static String PREG_MATCH_CAL = "实际返回已将字段转化为正则匹配校验，如下:";
      private static String NON_EXSIT_CAL = "实际返回已对字段进行存在与否校验，如下:";
      private static String COUNT_CAL = "实际返回已将字段值转为个数，如下:";
      private static String NUM_CHECK_CAL = "实际返回中对部分字段进行数量校验，如下:";
      private static String FUNC_CAL = "实际返回已将字段进行特殊化处理:";
  
      private static String RES = "res";
      private static String CAL = "cal";
      private static String PRE_SINGAL = "$$$$${{{{{";
  
  
      private static String MENU_GROUP_ID = "markov";
      private static String MENU_DATA_MENU_ID = "menu_reflection";
      private static String MENU_DATA_MENU_ID_4BU = "menu_reflection_4_bu";
  
      public static String strtotime(String str, String seprator) {
  
          if (str.indexOf("timeStamp" +
                  "" +
                  "(") > 0 || str.indexOf("date(") > 0) {
              List<String> strList = new ArrayList<String>();
              Calendar calendar = Calendar.getInstance();
              int date;
              String[] timeList = str.split(seprator + "\\(");
              for (String elem : timeList) {
                  String[] tmp = elem.split("\\)");
                  if (tmp.length == 2) {
                      String timeStamp = "";
                      if (tmp[0].contains(" days")) {
                          tmp[0] = tmp[0].replace(" days", "");
  
                          date = Integer.parseInt(tmp[0]);
                          calendar.add(Calendar.DAY_OF_YEAR, date);
                      }
                      if (tmp[0].contains(" hours")) {
                          tmp[0] = tmp[0].replace(" hours", "");
                          date = Integer.parseInt(tmp[0]);
                          calendar.add(Calendar.HOUR_OF_DAY, date);
                      }
                      if ("timeStamp".equals(seprator)) {
                          timeStamp = String.valueOf(calendar.getTimeInMillis() / 1000);
                      } else {
                          SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd", Locale.CHINA);
                          timeStamp = (format.format(calendar.getTime()));
                      }
  
                      strList.add(timeStamp);
                      strList.add(tmp[1]);
                  }
                  if (tmp.length == 1) {
                      strList.add(tmp[0]);
                  }
              }
              str = implode("", strList);
          }
          return str;
      }
  
      /**
       * @param elementSeprator List元素的连接符
       * @param list            待连接的List
       * @return
       */
      public static String implode(String elementSeprator, List<String> list) {
  
          String result = "";
  
          if (list.size() == 0) {
              return result;
          }
  
          int i;
          for (i = 0; i < list.size() - 1; i++) {
              result += list.get(i) + elementSeprator;
          }
          result += list.get(i);
          return result;
      }
  
      public static String implode(String elementSeprator, Set<Long> set) {
  
          List list = new ArrayList(set);
          String result = "";
          int i;
  
          if (list.size() == 0) {
              return result;
          }
  
          for (i = 0; i < list.size() - 1; i++) {
              result += list.get(i) + elementSeprator;
          }
          result += list.get(i);
          return result;
      }
  
  
      /**
       * 函数功能
       * 将String按照分隔符切分,写入map中
       *
       * @param str
       * @param elementSeprator
       * @param kvSeprator
       * @return
       */
      public static Map<String, String> explode2Map(String str, String elementSeprator, String kvSeprator) {
  
          Map<String, String> map = new HashMap<String, String>();
          String[] arr = str.split(elementSeprator);
          List<String> tmp;
          String key = null;
          String value = null;
          for (int i = 0; i < arr.length; i++) {
              tmp = new ArrayList<String>(Arrays.asList(arr[i].split(kvSeprator)));
              if (tmp.size() == 2) {
                  key = tmp.get(0);
                  value = tmp.get(1);
              } else if (tmp.size() > 2) {
                  key = tmp.get(0);
                  tmp.remove(0);
                  value = implode(kvSeprator, tmp);
              }
              map.put(key, value);
          }
          return map;
      }
  
  
  
      public static String explode2Json(String str, String elementSeprator, String kvSeprator) {
  
          JSONObject map = new JSONObject();
          String[] arr = str.split(elementSeprator);
          List<String> tmp;
          String key = null;
          String value = null;
          for (int i = 0; i < arr.length; i++) {
              tmp = new ArrayList<String>(Arrays.asList(arr[i].split(kvSeprator)));
              if (tmp.size() == 2) {
                  key = tmp.get(0);
                  value = tmp.get(1);
              } else if (tmp.size() > 2) {
                  key = tmp.get(0);
                  tmp.remove(0);
                  value = implode(kvSeprator, tmp);
                  //System.out.println(key + ":" + value);
              } else if (tmp.size() == 1) {
                  key = tmp.get(0);
                  value = "";
              } else {
                  continue;
              }
              key = key.trim();
              value = value.trim();
              map.put(key, value);
          }
          return map.toString();
      }
  
      public static String getType(Object o) {
          return o.getClass().toString();
      }
  
      /**
       * 函数功能,进行map的连接
       */
      public static String implodeMapObject(String kvSeprator, String elementSeprator, JSONObject mapObject) {
  
          //拼接成msg
          List<String> list = new ArrayList<String>();
          Object value;
          String element;
          String pre = "'";
  
          for (String key : mapObject.keySet()) {
              value = mapObject.get(key);
              if (getType(value).contains("com.alibaba.fastjson.JSONArray")) {
                  for (Object fieldValue : (JSONArray) value) {
                      element = key + kvSeprator + fieldValue;
                      list.add(element);
                  }
              } else if (getType(value).contains("java.lang.String") && !"ubs_action".equals(key)) {
                  element = key + kvSeprator + pre + value + pre;
                  list.add(element);
              } else {
                  element = key + kvSeprator + value;
                  list.add(element);
              }
  
          }
  
          return implode(elementSeprator, list);
      }
  
      /**
       * 函数功能,进行map的连接
       */
      public static String implodeMap(String kvSeprator, String elementSeprator, JSONObject mapObject) {
  
          //拼接成msg
          List<String> list = new ArrayList<String>();
          Object value;
          String element;
          String pre = "";
  
          for (String key : mapObject.keySet()) {
              value = mapObject.get(key);
              if (getType(value).contains("com.alibaba.fastjson.JSONArray")) {
                  System.out.println(value);
                  for (Object fieldValue : (JSONArray) value) {
                      element = key + kvSeprator + fieldValue;
                      list.add(element);
                  }
              } else if (getType(value).contains("java.lang.String") && !"ubs_action".equals(key)) {
                  element = key + kvSeprator + pre + value + pre;
                  list.add(element);
              } else {
                  element = key + kvSeprator + value;
                  list.add(element);
              }
  
          }
  
          return implode(elementSeprator, list);
      }
  
  
      public static String getPre(String content) {
  
          String pre = "";
          try {
              JSONObject obj = JSON.parseObject(content);
              Integer appId = (Integer) obj.get("appId");
              Integer scenarioId = (Integer) obj.get("scenarioId");
              Integer caseId = 0;
              if (obj.containsKey("id")) {
                  caseId = (Integer) obj.get("id");
              }
              pre = appId.toString() + scenarioId.toString() + caseId.toString();
              return pre;
          } catch (Exception e) {
              return pre;
          }
      }
  
      public static String placeholderReplace(String content, String pre) {
  
          String reg = "\\$\\{[a-zA-Z0-9,\\^ :\\-=_;]+\\}";
          Pattern pattern = Pattern.compile(reg);
          Matcher matcher = pattern.matcher(content);
          while (matcher.find()) {
              //获取匹配
              String matchWord = matcher.group(0);
              //如果为时间变量
              if (matchWord.contains("datetime")) {
                  content = content.replace(matchWord, dateTimeGet(matchWord));
              }
              //不可见separator
              else if (matchWord.contains("separator")) {
                  content = content.replace(matchWord, genSeparator(matchWord));
              }
              //xml的属性匹配
              else if (matchWord.contains("property")) {
                  content = content.replace(matchWord, genXmlProperty(matchWord));
              }
              //shardId变量
              else if (matchWord.contains("shardId")) {
                  content = content.replace(matchWord, genShardId(genStrId(pre + matchWord, 8)));
              }
              //如果为普通变量
              else {
                  content = content.replace(matchWord, genStrId(pre + matchWord, 8));
              }
          }
          return content;
      }
  
      public static String genShardId(String id) {
  
          String newId = null;
          for (int i = 1; i < 100; i++) {
              newId = i + id;
              if (getShardId(Long.valueOf(newId)) == 0) {
                  return newId;
              }
          }
          return id;
      }
  
      public static int getShardId(Long id) {
  
          id = id & 65535;
          int shardCount = 2;
          int base = 65536 / shardCount;
          int remain = 65536 % shardCount;
  
          for (int shardId = 0; shardId < shardCount; ++shardId) {
              int start = base * shardId + (shardId < remain ? shardId : remain);
              int stop = base * (shardId + 1) + (shardId < remain ? shardId + 1 : remain);
              if (id >= start && id < stop) {
                  return shardId;
              }
          }
          return -1;
      }
  
      /**
       * 占位符替换,目前支持id和时间变量
       *
       * @param content
       * @return
       */
      public static String placeholderReplace(String content) {
  
          String reg = "\\$\\{[a-zA-Z0-9,\\^ :\\-\\+=_;]+\\}";
          Pattern pattern = Pattern.compile(reg);
          Matcher matcher = pattern.matcher(content);
          String pre = getPre(content);
          while (matcher.find()) {
              //获取匹配
              String matchWord = matcher.group(0);
  
              //如果为时间变量
              if (matchWord.contains("datetime")) {
                  content = content.replace(matchWord, dateTimeGet(matchWord));
              }
              //不可见separator
              else if (matchWord.contains("separator")) {
                  content = content.replace(matchWord, genSeparator(matchWord));
              }
              //xml的属性匹配
              else if (matchWord.contains("property")) {
                  content = content.replace(matchWord, genXmlProperty(matchWord));
              }
              //shardId变量
              else if (matchWord.contains("shardId")) {
                  content = content.replace(matchWord, genShardId(genStrId(pre + matchWord, 8)));
              } else if (matchWord.contains("skip")) {
                  String matchWordNew = matchWord.replace("{skip,", PRE_SINGAL);
                  content = content.replace(matchWord, matchWordNew);
              }
              //如果为普通变量
              else {
                  content = content.replace(matchWord, genStrId(pre + matchWord, 8));
              }
          }
          content = content.replace(PRE_SINGAL, "{");
  
          return content;
      }
  
  
  
  
      public static String genXmlProperty(String content) {
          String[] arr = content.split(",");
  
          try {
              String propertyStr = arr[1].trim().replace("}", "");
              String[] propertyArr = propertyStr.split(";");
              String res = "";
              for (String property : propertyArr) {
  
                  String[] kv = property.split("=");
                  String k = kv[0].trim();
                  String v = kv[1].trim();
                  String p = " " + k + "='" + v + "'";
                  res += p;
              }
  
              return res;
  
          } catch (Exception e) {
              logger.error("xml属性转化失败:" + e.getMessage());
              return content;
          }
  
      }
  
      public static String genSeparator(String content) {
  
          String[] arr = content.split(",");
          try {
              String pattern = arr[1].trim().replace("}", "");
              String kv;
              switch (pattern) {
                  case "^A":
                      kv = "\u0001";
                      break;
                  case "^B":
                      kv = "\u0002";
                      break;
                  case "^C":
                      kv = "\u0003";
                      break;
                  case "^D":
                      kv = "\u0004";
                      break;
                  case "^E":
                      kv = "\u0005";
                      break;
                  case "^F":
                      kv = "\u0006";
                      break;
                  default:
                      kv = content;
              }
  
              return kv;
  
          } catch (Exception e) {
              System.out.println("不可见字符转化失败:" + e.getMessage());
              return content;
          }
      }
  
      /**
       * 将string转化为唯一id
       *
       * @param content
       * @return
       */
      public static String genStrId(String content, int num) {
          CRC32 crc32 = new CRC32();
          crc32.update(content.getBytes());
          Long crc32Value = crc32.getValue();
          String crc32ValueStr = crc32Value.toString();
          if (crc32ValueStr.length() < num) {
              return crc32ValueStr.substring(0, crc32ValueStr.length());
          }
          return crc32Value.toString().substring(0, num);
      }
  
  
      public static String genRepeatId(Integer start, Integer i, Integer repeatNum, Integer mutiple) {
  
          List<String> idList = new ArrayList<>();
  
          start = (start + i) * mutiple;
          for (int t = 0; t < repeatNum; t++) {
              idList.add(String.valueOf(start));
          }
          return implode(",", idList);
      }
  
  
      /**
       * //获取当前时间
       * //${datetime,now,yyyy-MM-dd HH:mm:ss}
       * //${datetime,-1 day,yyyy-MM-dd HH:mm:ss}
       * //${datetime,-1 hour,timestamp}
       * //${datetime,-1 minute,timestamp}
       *
       * @param datetimeStr
       * @return
       */
      public static String dateTimeGet(String datetimeStr) {
  
          String[] dateArr = datetimeStr.split(",");
          try {
  
              String curTime = dateArr[1].trim();
              String pattern = dateArr[2].trim().replace("}", "");
  
              Date date = new Date();//取时间
              Calendar calendar = new GregorianCalendar();
              calendar.setTime(date);
              SimpleDateFormat formatter;
              //校验格式
              if (!"now".equals(curTime)) {
                  String[] timeArr = curTime.split(" ");
                  Integer offset = Integer.valueOf(timeArr[0]);
                  String timeType = timeArr[1];
                  if ("day".equals(timeType)) {
                      calendar.add(Calendar.DATE, offset);//把日期往前减少一天，若想把日期向后推一天则将负数改为正数
                  }
                  if ("hour".equals(timeType)) {
                      calendar.add(Calendar.HOUR, offset);//把日期往前减少一小时，若想把日期向后推一天则将负数改为正数
                  }
                  if ("minute".equals(timeType)) {
                      calendar.add(Calendar.MINUTE, offset);//把日期往前减少一分钟，若想把日期向后推一天则将负数改为正数
                  }
              }
  
              date = calendar.getTime();
  
              //时间戳
              if ("timestamp".equals(pattern) || "timeStamp".equals(pattern)) {
                  formatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
                  Date dateUnix = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse(formatter.format(date));
                  long unixTimestamp = dateUnix.getTime() / 1000;
                  return String.valueOf(unixTimestamp);
              } else {
                  formatter = new SimpleDateFormat(pattern);
                  return formatter.format(date);
              }
  
          } catch (Exception e) {
              logger.error("时间转化失败:" + e.getMessage());
  
              return datetimeStr;
          }
      }
  
  
      public static String commonJsonCompare(String expect, String actual, String calFieldsConfig) {
  
          String result = "";
          //将两个json进行转换,进行比较
          try {
  
              if (expect == null || "".equals(expect)) {
                  expect = "{}";
              }
              if (actual == null || "".equals(actual)) {
                  actual = "{}";
              }
              if (calFieldsConfig == null || "".equals(calFieldsConfig)) {
                  calFieldsConfig = "{}";
              }
  
  
              String reExpect = expect;
              String reActual = actual;
              Field valueFieldOfString = String.class.getDeclaredField("value");
              valueFieldOfString.setAccessible(true);
  
              if (isJsonArray(actual)) {
                  JSONObject obj = new JSONObject();
                  obj.put("JSONArray", JSONArray.parse(actual));
                  actual = obj.toString();
              }
              if (isJsonArray(expect)) {
                  JSONObject obj = new JSONObject();
                  obj.put("JSONArray", JSONArray.parse(expect));
                  expect = obj.toString();
              }
  
              //系统预处理=> 系统提供公共的处理,比如设置 忽略字段 or 字段有序无序 or 正则匹配
              JSONObject allObj = systemPreCal(expect, actual, calFieldsConfig);
  
              JSONObject resObj = (JSONObject) allObj.get(RES);
              HashMap<String, List<String>> calMapPre = (HashMap<String, List<String>>) allObj.get(CAL);
  
              expect = (String) resObj.get(EXPECT);
              actual = (String) resObj.get(ACTUAL);
              //反射机制,将实际和期望修改后的值带出去
              valueFieldOfString.set(reExpect, expect.toCharArray());
              valueFieldOfString.set(reActual, actual.toCharArray());
  
              HashMap<String, List<String>> errorMap = new HashMap<>();
              HashMap<String, List<String>> calMap = new HashMap<>();
              calMap.putAll(calMapPre);
  
              JsonPathParser expectParser = new JsonPathParser(expect);
              JsonPathParser actualParser = new JsonPathParser(actual);
              JSONObject expectObj = JSONObject.parseObject(expectParser.getPathJsonStr());
              JSONObject actualObj = JSONObject.parseObject(actualParser.getPathJsonStr());
              String expectValue;
              String actualValue;
  
  
              List<String> pregMatchList = calPregMatchList(calFieldsConfig);
              Map<String, String> callFuncMap = getFuncList(calFieldsConfig);
              List<String> numCheckList = getNumCheckList(calFieldsConfig);
              List<String> nonExsitList = calNonExsitList(calFieldsConfig);
  
              if (("{}".equals(expect) || "{}".equals(actual)) && !expect.equals(actual)) {
                  if (!errorMap.containsKey(VALUE_CHECK)) {
                      errorMap.put(VALUE_CHECK, new ArrayList<>());
                  }
                  errorMap.get(VALUE_CHECK).add("1.实际和期望不相等!");
              }
  
              //校验应该不存在的key
              for (String actualKey : actualObj.keySet()) {
                  if (isNonExsitCheck(actualKey, nonExsitList)) {
                      //if exsit
                      actualValue = String.valueOf(actualObj.get(actualKey));
                      if (!errorMap.containsKey(NON_EXSIT_CHECK)) {
                          errorMap.put(NON_EXSIT_CHECK, new ArrayList<>());
                      }
                      if (!calMap.containsKey(NON_EXSIT_CAL)) {
                          calMap.put(NON_EXSIT_CAL, new ArrayList<>());
                      }
  
                      errorMap.get(NON_EXSIT_CHECK).add(".字段名:" + actualKey + ",期望: 不出现" + " VS 实际:" + actualValue);
                      calMap.get(NON_EXSIT_CAL).add(".字段名:" + actualKey);
                  }
              }
  
              for (String expectKey : expectObj.keySet()) {
  
                  //存在相同key,进行对比
                  if (actualObj.containsKey(expectKey)) {
                      expectValue = String.valueOf(expectObj.get(expectKey));
                      actualValue = String.valueOf(actualObj.get(expectKey));
                      //如果不相等
                      if (!expectValue.equals(actualValue)) {
                          //判断是否正则匹配
                          if (isPregMatch(expectKey, pregMatchList)) {
                              //执行正则
                              Pattern pattern = Pattern.compile(expectValue);
                              Matcher matcher = pattern.matcher(actualValue);
                              // 查找字符串中是否有匹配正则表达式的字符/字符串
                              if (!matcher.find()) {
                                  if (!errorMap.containsKey(PREG_MATCH_CHECK)) {
                                      errorMap.put(PREG_MATCH_CHECK, new ArrayList<>());
                                  }
                                  if (!calMap.containsKey(PREG_MATCH_CAL)) {
                                      calMap.put(PREG_MATCH_CAL, new ArrayList<>());
                                  }
  
                                  errorMap.get(PREG_MATCH_CHECK).add(".字段名:" + expectKey + ",期望:" + expectValue + " VS 实际:" + actualValue);
                                  calMap.get(PREG_MATCH_CAL).add(".字段名:" + expectKey);
                              }
  
                          }//判断是否动态调用处理函数
                          else if (isCallFunc(expectKey, callFuncMap)) {
                              String expectCalKey = removeIndexFieldName(expectKey);
                              String funcName = callFuncMap.get(expectCalKey);
  
                              String[] funcNameList = funcName.split("\\[");
                              String funcDesc = "";
                              String func = FUNC_CAL;
                              if (funcNameList.length == 2) {
                                  funcName = funcNameList[0];
                                  funcDesc = funcNameList[1];
                                  func += funcDesc;
                              }
  
                              Class<?> threadClazz = Class.forName("com.alimama.zhizi.engine.util.Toolkit");
                              Method method = threadClazz.getMethod(funcName, String.class, String.class);
                              boolean res = (boolean) method.invoke(null, expectValue, actualValue);
  
                              if (!calMap.containsKey(func)) {
                                  calMap.put(func, new ArrayList<>());
                              }
  
                              if (!res) {
                                  if (!errorMap.containsKey(FUNC_CHECK)) {
                                      errorMap.put(FUNC_CHECK, new ArrayList<>());
                                  }
                                  errorMap.get(FUNC_CHECK).add(".字段名:" + expectKey + ",特殊处理函数:" + funcName + ",期望:" + expectValue + " VS 实际:" + actualValue);
                                  calMap.get(func).add(".字段名:" + expectKey);
                              }
  
                          } else {
                              if (!errorMap.containsKey(VALUE_CHECK)) {
                                  errorMap.put(VALUE_CHECK, new ArrayList<>());
                              }
                              errorMap.get(VALUE_CHECK).add(".字段名:" + expectKey + ",期望:" + expectValue + " VS 实际:" + actualValue);
                          }
                      }
  
                  }
                  //key不存在
                  else {
                      if (!errorMap.containsKey(KEY_NO_EXIST_CHECK)) {
                          errorMap.put(KEY_NO_EXIST_CHECK, new ArrayList<>());
                      }
                      errorMap.get(KEY_NO_EXIST_CHECK).add("字段名:" + expectKey);
                  }
              }
  
              if (errorMap.size() == 0) {
                  result = "校验通过!";
  
                  if (calMap.size() > 0) {
                      result += "[存在特殊处理字段] 详情如下:\n";
                      for (String calType : calMap.keySet()) {
  
                          String calStr = "======" + calType + "======\n";
  
                          List<String> calList = calMap.get(calType);
  
                          for (int i = 1; i <= calList.size(); i++) {
                              calStr += i + "." + calList.get(i - 1) + "\n";
                          }
                          result += calStr;
                      }
                  }
              } else {
  //                resList.sort(Comparator.reverseOrder());
  //                result = "校验失败,失败详情如下:\n";
  //                result += Toolkit.implode("\n",resList);
                  result = "[校验失败] 失败详情如下:\n";
                  //失败原因
                  for (String errorType : errorMap.keySet()) {
  
                      String errorStr = "======" + errorType + "======\n";
  
                      List<String> errorList = errorMap.get(errorType);
  
                      for (int i = 1; i <= errorList.size(); i++) {
                          errorStr += i + errorList.get(i - 1) + "\n";
                      }
                      result += errorStr;
                  }
  
                  //处理
                  if (calMap.size() > 0) {
                      result += "[存在特殊处理字段] 详情如下:\n";
  
                      for (String calType : calMap.keySet()) {
  
                          String calStr = "======" + calType + "======\n";
  
                          List<String> calList = calMap.get(calType);
  
                          for (int i = 1; i <= calList.size(); i++) {
                              calStr += i + "." + calList.get(i - 1) + "\n";
                          }
                          result += calStr;
                      }
                  }
              }
  
          } catch (Exception e) {
              result = "校验失败,对比异常原因:" + e.getMessage();
          }
  
          return result;
      }
  
  
      public static Boolean isJsonObjcet(String in) {
          if (in == null || in.isEmpty()) {
              return false;
          }
          try {
              JSONObject.parseObject(in);
              return true;
  
          } catch (Exception e) {
              return false;
          }
      }
  
      public static Boolean isJsonArray(String in) {
          if (in == null || in.isEmpty()) {
              return false;
          }
          try {
              JSONArray.parseArray(in);
              return true;
  
          } catch (Exception e) {
              return false;
          }
      }
      /**
       * 判断是否是需要正则匹配字段
       *
       * @return
       */
      public static boolean isPregMatch(String expectKey, List<String> pregMatchList) {
  
  
          if (pregMatchList.size() > 0) {
  
              expectKey = removeIndexFieldName(expectKey);
              if (pregMatchList.contains(expectKey)) {
                  return true;
              }
          }
  
          return false;
  
      }
  
  
  
      /**
       * 去除序号相关
       *
       * @param fileName
       * @return
       */
      public static String removeIndexFieldName(String fileName) {
  
  
          String match = "\\[[0-9]+\\]";
          Pattern pattern = Pattern.compile(match);
          Matcher matcher = pattern.matcher(fileName);
          // 查找字符串中是否有匹配正则表达式的字符/字符串
          while (matcher.find()) {
              String matchWord = matcher.group(0);
              fileName = fileName.replace(matchWord, "");
          }
          return fileName;
      }
  
  
      /**
       * 判断是否是需要校验不存在的字段
       *
       * @return
       */
      public static boolean isNonExsitCheck(String actualKey, List<String> nonExsitList) {
  
  
          if (nonExsitList.size() > 0) {
  
              actualKey = removeIndexFieldName(actualKey);
              boolean isIn = false;
              for (String field : nonExsitList) {
                  if (actualKey.equals(field)) {
                      isIn = true;
                  } else if (actualKey.startsWith(field) && actualKey.charAt(field.length()) == '.') {
                      isIn = true;
                  }
              }
  
              return isIn;
          }
  
          return false;
  
      }
  
      public static boolean isCallFunc(String expectKey, Map<String, String> pregMatchList) {
  
  
          if (pregMatchList.size() > 0) {
  
              expectKey = removeIndexFieldName(expectKey);
              if (pregMatchList.containsKey(expectKey)) {
                  return true;
              }
          }
  
          return false;
  
      }
  
  
      /**
       * 获取匹配的list
       *
       * @return
       */
      public static List<String> calPregMatchList(String calFieldsConfig) {
  
          List<String> pregMatchList = new ArrayList<>();
  
          if (calFieldsConfig == null || !isJsonObjcet(calFieldsConfig)) {
              return pregMatchList;
          }
  
          JSONObject calFieldsObj = JSONObject.parseObject(calFieldsConfig);
  
          if (!calFieldsObj.containsKey(PREGMATCH_FIELDS)) {
              return pregMatchList;
          }
          pregMatchList = (List<String>) calFieldsObj.get(PREGMATCH_FIELDS);
  
          return pregMatchList;
  
      }
  
  
      /**
       * 获取匹配的list
       *
       * @return
       */
      public static List<String> calNonExsitList(String calFieldsConfig) {
  
          List<String> pregMatchList = new ArrayList<>();
  
          if (calFieldsConfig == null || !isJsonObjcet(calFieldsConfig)) {
              return pregMatchList;
          }
  
          JSONObject calFieldsObj = JSONObject.parseObject(calFieldsConfig);
  
          if (!calFieldsObj.containsKey(NON_EXSIT_FIELDS)) {
              return pregMatchList;
          }
          pregMatchList = (List<String>) calFieldsObj.get(NON_EXSIT_FIELDS);
  
          return pregMatchList;
  
      }
  
      public static List<String> getNumCheckList(String calFieldsConfig) {
  
          List<String> numCheckList = new ArrayList<>();
  
          if (calFieldsConfig == null || !isJsonObjcet(calFieldsConfig)) {
              return numCheckList;
          }
  
          JSONObject calFieldsObj = JSONObject.parseObject(calFieldsConfig);
  
          if (!calFieldsObj.containsKey(NUMCHECKFIELDS)) {
              return numCheckList;
          }
          numCheckList = (List<String>) calFieldsObj.get(NUMCHECKFIELDS);
  
          return numCheckList;
  
      }
  
  
      public static Map<String, String> getFuncList(String calFieldsConfig) {
  
          Map<String, String> matchList = new HashMap<>();
  
          if (calFieldsConfig == null || !isJsonObjcet(calFieldsConfig)) {
              return matchList;
          }
  
          JSONObject calFieldsObj = JSONObject.parseObject(calFieldsConfig);
  
          if (!calFieldsObj.containsKey(CALL_FUNC_FIELDS)) {
              return matchList;
          }
          matchList = (Map<String, String>) calFieldsObj.get(CALL_FUNC_FIELDS);
  
          return matchList;
  
      }
  
      /**
       * 实际结果预处理,可处理以下几类:1.忽略字段,2.字段正则匹配. 3.无序字段处理
       *
       * @param actual
       * @param calFieldsConfig
       * @return
       */
      public static JSONObject systemPreCal(String expect, String actual, String calFieldsConfig) {
  
  
          JSONObject allObj = new JSONObject();
          JSONObject resObj = new JSONObject();
          HashMap<String, List<String>> calMap = new HashMap<>();
  
  
          try {
              //会先进行处理
              if (calFieldsConfig == null || !isJsonObjcet(calFieldsConfig)) {
                  resObj.put(ACTUAL, actual);
                  resObj.put(EXPECT, expect);
                  resObj.put(IS_SUCCESS, true);
                  allObj.put(RES, resObj);
                  allObj.put(CAL, calMap);
                  return allObj;
              }
              JSONObject calFieldsObj = JSONObject.parseObject(calFieldsConfig);
              JSONObject actualObj = JSONObject.parseObject(actual);
              JSONObject expectObj = JSONObject.parseObject(expect);
  
              //处理忽略字段
              if (calFieldsObj.containsKey(IGNORE_FIELDS)) {
  
                  List<String> ignoreFieldsList = (List<String>) calFieldsObj.get(IGNORE_FIELDS);
  
                  if (ignoreFieldsList.size() > 0) {
                      if (!calMap.containsKey(IGNORE_CAL)) {
                          calMap.put(IGNORE_CAL, ignoreFieldsList);
                      }
  
                      for (String fieldName : ignoreFieldsList) {
                          List<String> fieldNameList = new ArrayList<>(Arrays.asList(fieldName.split("\\.")));
                          recursionCalJson(fieldNameList, expectObj, REMOVE_TYPE);
                          recursionCalJson(fieldNameList, actualObj, REMOVE_TYPE);
                      }
                  }
  
              }
  
              //处理COUNT字段,只比较数目，不比较内容
              if (calFieldsObj.containsKey(COUNT_FIELDS)) {
  
                  List<String> countFieldsList = (List<String>) calFieldsObj.get(COUNT_FIELDS);
  
                  if (countFieldsList.size() > 0) {
                      if (!calMap.containsKey(COUNT_CAL)) {
                          calMap.put(COUNT_CAL, countFieldsList);
                      }
  
                      for (String fieldName : countFieldsList) {
                          List<String> fieldNameList = new ArrayList<>(Arrays.asList(fieldName.split("\\.")));
                          recursionCalJson(fieldNameList, expectObj, COUNT_TYPE);
                          recursionCalJson(fieldNameList, actualObj, COUNT_TYPE);
                      }
                  }
  
              }
  
  
              //处理num check字段，既比较数目，又比较内容
              if (calFieldsObj.containsKey(NUMCHECKFIELDS)) {
  
                  List<String> countFieldsList = (List<String>) calFieldsObj.get(NUMCHECKFIELDS);
  
                  if (countFieldsList.size() > 0) {
                      if (!calMap.containsKey(NUM_CHECK_CAL)) {
                          calMap.put(NUM_CHECK_CAL, countFieldsList);
                      }
  
                      for (String fieldName : countFieldsList) {
                          List<String> fieldNameList = new ArrayList<>(Arrays.asList(fieldName.split("\\.")));
                          recursionCalJson(fieldNameList, expectObj, NUM_CHECK_TYPE);
                          recursionCalJson(fieldNameList, actualObj, NUM_CHECK_TYPE);
                      }
                  }
  
              }
  
              //处理排序字段
              if (calFieldsObj.containsKey(UNSORT_FIELDS)) {
  
  
                  List<String> sortFieldsList = (List<String>) calFieldsObj.get(UNSORT_FIELDS);
  
                  if (sortFieldsList.size() > 0) {
                      if (!calMap.containsKey(SORT_CAL)) {
                          calMap.put(SORT_CAL, sortFieldsList);
                      }
                      for (String fieldName : sortFieldsList) {
                          List<String> fieldNameList = new ArrayList<>(Arrays.asList(fieldName.split("\\.")));
  //                        recursionCalJson(fieldNameList, expectObj, SORT_TYPE);
                          recursionCalJson(fieldNameList, actualObj, SORT_TYPE);
                      }
                  }
              }
              resObj.put(ACTUAL, JSONObject.toJSONString(actualObj));
              resObj.put(EXPECT, JSONObject.toJSONString(expectObj));
              resObj.put(IS_SUCCESS, true);
          } catch (Exception e) {
              resObj.put(ACTUAL, actual);
              resObj.put(EXPECT, expect);
              resObj.put(IS_SUCCESS, false);
              resObj.put(MESSAGE, e.getMessage());
          }
  
          allObj.put(RES, resObj);
          allObj.put(CAL, calMap);
  
          return allObj;
  
      }
      public static void recursionCalJson(List<String> fieldNameList, JSONObject obj, String type) {
  
  
          //只支持obj为JSON的情况
          //一层
          if (fieldNameList.size() == 1) {
              String layer1 = fieldNameList.get(0);
              //如果命中
              if (obj.containsKey(layer1)) {
                  //处理
                  calJsonLeaf(obj, layer1, type);
              }
          }
  
          //多层
          if (fieldNameList.size() > 1) {
  
              String layer1 = fieldNameList.get(0);
              String layer2 = fieldNameList.get(1);
  
              //命中第一层
              if (obj.containsKey(layer1)) {
                  Object obj2 = obj.get(layer1);
  
                  //如果是JSONObject
                  if (obj2 instanceof JSONObject) {
                      JSONObject jobj2 = (JSONObject) obj2;
                      //如果命中
                      if (jobj2.containsKey(layer2)) {
                          fieldNameList.remove(0);
                          recursionCalJson(fieldNameList, jobj2, type);
                      }
                  }
                  //如果是jsonArr
                  else if (obj2 instanceof JSONArray) {
                      JSONArray jsonArrayobj2 = (JSONArray) obj2;
                      for (Object unitObj : jsonArrayobj2) {
                          JSONObject jobj2 = (JSONObject) unitObj;
                          List<String> tmpfieldNameList = cloneList(fieldNameList);
                          //如果命中
                          if (jobj2.containsKey(layer2)) {
                              tmpfieldNameList.remove(0);
                              recursionCalJson(tmpfieldNameList, jobj2, type);
                          }
                      }
  
                  }
              }
  
          }
      }
      public static void calJsonLeaf(JSONObject obj, String layer, String type) {
  
          if (type.equals(REMOVE_TYPE)) {
              obj.remove(layer);
          }
  
          if (type.equals(COUNT_TYPE)) {
              int count = 1;
              Object unitObj = obj.get(layer);
              if (unitObj instanceof JSONArray) {
                  count = ((JSONArray) unitObj).size();
              }
              String countValue = "数目为" + count;
              obj.put(layer, countValue);
          }
  
          if (type.equals(NUM_CHECK_TYPE)) {
              int count = 1;
              Object unitObj = obj.get(layer);
              if (unitObj instanceof JSONArray) {
                  count = ((JSONArray) unitObj).size();
              }
              String countValue = "数目为" + count;
              obj.put(layer + "_num", countValue);
          }
  
          if (type.equals(SORT_TYPE)) {
              Object unitObj = obj.get(layer);
  
              if (unitObj instanceof JSONArray) {
                  JSONArray jObj = (JSONArray) unitObj;
                  //对jObj进行排序
                  if (jObj.size() > 1) {
                      List<String> tmpList = new ArrayList<>();
                      for (Object tmpObj : jObj) {
                          JSONObject tmpjObj = (JSONObject) tmpObj;
                          tmpList.add(tmpjObj.toString());
                      }
                      tmpList.sort(Comparator.reverseOrder());
                      JSONArray newJObj = new JSONArray();
                      for (String str : tmpList) {
                          newJObj.add(JSONObject.parseObject(str));
                      }
                      obj.put(layer, newJObj);
                  }
  
              }
          }
  
      }
      public static List<String> cloneList(List<String> souceList) {
  
          List<String> desList = new ArrayList<>();
          for (String value : souceList) {
              desList.add(value);
          }
          return desList;
      }
  
  
      /**
       * 获取错误堆栈内容
       *
       * @param e
       * @return
       */
      public static String getErrorStackTrace(Exception e) {
          StringWriter sw = new StringWriter();
          e.printStackTrace(new PrintWriter(sw, true));
          return sw.toString();
      }
  
      public static String changeCostFormat(Long cost) {
  
          String time = "";
          //转换为秒
          if (cost == 0) {
              return "1s";
          }
  //        long hourGap = 3600*1000;
          long minGap = 60 * 1000;
          long secGap = 1000;
          Long hour = 0L;
          Long min = 0L;
          Long second = 0L;
  
  
  //        //转化为小时
  //        if (cost > hourGap){
  //            hour=cost/(hourGap);
  //            cost=cost%(hourGap);
  //        }
  
  
          //转化为分钟
          if (cost > minGap) {
              min = cost / (minGap);
              cost = cost % (minGap);
          }
  
  
          //转化为sec
          if (cost > secGap) {
              second = cost / (secGap);
          }
  //
  //        if (hour != 0){
  //            time += hour +"hour";
  //        }
          if (min != 0) {
              time += min + "min";
          }
          if (second == 0) {
              time += "1s";
          } else {
              time += second + "s";
          }
  
          return time;
      }
  
  
  
  }
  
  