工具集合-脚本合并(Groovy)

说明:只针对于groovy脚本,只能将两个脚本合并起来,不会进行去重,内容不会重复,然后也可以进行执行,验证脚本语法也没问题。2个以上也可以的,只是用了最笨的方法实现了需求。别去看怎么写的了,能套死你。而且脚本中仅支持以下注解,Test注解可以多个,其他的不行,没有那么的人性化,有啥问题可以问我。

"@BeforeProcess", "@BeforeThread", "@Before", "@Test
package org.ngrinder.script.controller;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.entity.ContentType;
import org.ngrinder.script.common.DataTypeConstant;
import org.ngrinder.script.common.FileConstant;
import org.ngrinder.script.common.FileStatusEnum;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.*;

/**
 * 脚本处理工具类,目前只支持Groovy脚本
 *
 * @Author xiaoxin
 * @Date 2021/8/24 14:49
 * @Version 1.0
 */

@Slf4j
@Component
public class MergeFileUtil {

	/**
	 * 读取文件,传过来的是多个文件的数组形式,读取到文件之后合并起来,返回最终合并的文件
	 * 1.获取单个文件
	 * 2.获取import字符串
	 * 3.获取文件中的全局变量
	 * 4.获取文件中的代码片段
	 * 5.对变量和代码片段进行更换名称
	 * 6.存进集合并返回
	 * 7.取出方法内的代码片段
	 * 8.获取多多个文件的全部集合
	 * 9.进行合并为集合
	 * 10.创建文件,输入数据
	 */
	public MultipartFile readFile(List<Map<String, String>> file) throws FileException, Exception {

		String str;

		//代码文本拼接
		StringBuffer sb = new StringBuffer();
		//开头是import的集合
		List<String> startList = new ArrayList<>();
		//开头是public修饰符的代码文本行
		List<String> pulblicGlobalList = new ArrayList<>();
		//全局变量集合
		List<String> globalList = new ArrayList<>();
		//代码片段集合
		List<Map<String, List<String>>> codeList = new ArrayList<>();
		//更改过的全局变量集合、代码片段集合
		Map<String, List<List<Map<String, String>>>> replaceFile;
		//合并文本集合
		List<Map<String, List<List<Map<String, String>>>>> mergeList = new ArrayList<>();

		//判断文件名是否重复

//		if (!judgeName(file)) {
//			throw new FileException(103,"文件名字重复");
//		}

		if (file.get(0).keySet().size() == 1) {
			throw new FileException(FileStatusEnum.UP_TO_TWO.getCode(), FileStatusEnum.UP_TO_TWO.getMsg());
		}

		if (file.get(0).keySet().size() > 3) {
			throw new FileException(FileStatusEnum.UP_TO_TREE.getCode(), FileStatusEnum.UP_TO_TREE.getMsg());
		}

		Set<String> strings = file.get(0).keySet();
		for (String s : strings) {

			//获取import开头的
			startList = getImportStr(file.get(0).get(s));

			//获取去public开头的
			pulblicGlobalList = getPublicStr(file.get(0).get(s));

			//获取全局变量集合
			List<String> GVList = getOverAll(importStart(pulblicGlobalList), globalList);

			Map<String, List<String>> kvHashMap = new HashMap<>();
			List<String> objects1 = new ArrayList<>();

			//获取注解的代码文本集合
			List<String> ANList = getAnnotation(file.get(0).get(s));

			for (int j = 0; j < ANList.size(); j++) {
				objects1.add(ANList.get(j));
				kvHashMap.put(String.valueOf(j), objects1);
			}
			codeList.add(kvHashMap);

			//通过全局变量和文本获取修改过名称的全局变量集合、代码片段集合
			replaceFile = replaceFile(s, GVList, objects1);
			mergeList.add(replaceFile);
		}

		//调用合并方法,返回真正的file文件
		MultipartFile multipartFile = mergeFileCode(mergeList, startList);
		return multipartFile;
	}


	private List<String> getOverAll(List<String> pulblicGlobalList, List<String> globalList) {

		for (String a : pulblicGlobalList) {
			if (globalObject(a)) {
				//判断尾部,如果尾部没有分号,则自动追加一个分号,为了后面的步骤流程
				String substring = a.substring(a.length() - 1);
				if (!substring.equals(FileConstant.BRANCH)) {
					a = a + FileConstant.BRANCH;
				}
				globalList.add(a);
			}
		}
		return globalList;
	}

	/**
	 * 判断字符串开头是否是import
	 *
	 * @param str
	 * @return
	 */
	public boolean decideStart(String str) {
		boolean flag = false;
		if (str.indexOf(FileConstant.IMPORT) == 0) {
			flag = true;
		}
		return flag;
	}

	/**
	 * 判断字符串开头是否以public
	 *
	 * @param str
	 * @return
	 */
	public boolean publicStart(String str) {
		boolean flag = false;
		//对字符串去除前后空格
		String trim = str.trim();
		if (trim.indexOf(FileConstant.PUBLIC) == 0) {
			flag = true;
		}
		return flag;
	}


	/**
	 * 暂时弃用,因为目前groovy脚本很多尾部没有分号
	 * 判断字符串结尾是否符合规则
	 *
	 * @param str
	 * @return
	 */
	public boolean decideEnding(String str) {
		boolean flag = false;
		String substring = str.substring(str.length());
		if (substring.equals(FileConstant.BRANCH)) {
			flag = true;
		}
		return flag;
	}


	/**
	 * 获取全局变量
	 *
	 * @param str
	 * @return
	 */
	public boolean globalObject(String str) {
		boolean flag = false;
		String s = str.substring(str.length() - 1);
		if (!s.equals(FileConstant.BRACKETS_LEFT)) {
			flag = true;
		}
		return flag;
	}

	/**
	 * 对顶部的import引入的文件文本进行筛选
	 * 使用hashSet去除相同的
	 *
	 * @param list
	 * @return
	 */
	public List<String> importStart(List list) {
		HashSet h = new HashSet(list);
		list.clear();
		list.addAll(h);

		return list;
	}

	/**
	 * 判断文件名字是否重复
	 *
	 * @param
	 * @return
	 */
	public boolean judgeName(List<Map<String, String>> file) {
		List<String> list = new ArrayList<>();
		for (int i = 0; i < file.size(); i++) {
			Set<String> strings = file.get(i).keySet();
			for (String s : strings) {
				list.add(s);
			}
		}
		HashSet<String> set = new HashSet<>(list);
		Boolean result = set.size() == list.size() ? true : false;

		return result;
	}


	/**
	 * 对代码块中的变量、代码文本进行名称替换
	 *
	 * @param constant 全局变量集合
	 * @return 修改过的file的全局变量集合、代码文本集合
	 * @methodCode 代码文本集合
	 */
	public Map<String, List<List<Map<String, String>>>> replaceFile(String fileName, List<String> constant, List<String> methodCode) {

		//原数据
		String originParam = null;
		//克隆数据
		String cloneParam = null;
		//全局变量集合
		List<String> globalList = new ArrayList<>();
		//不符合条件的代码文本集合
		List<String> nonConformity = new ArrayList<>();
		//克隆数据集合
		List<Map<String, String>> cloneParamList = new ArrayList<>();
		//分割数组
		String[] split;
		//替换后的代码文本集合
		List<String> methodCodeList = new ArrayList<>();
		//返回值list
		List<List<Map<String, String>>> returnList = new ArrayList<>();
		//存放原始数据和克隆数据
		Map<String, String> map = new HashMap<>();

		Map<String, String> cloneParamMap = new HashMap<>();

		//随机数
		int randomNum = new Random().nextInt(100);
		for (int t = 0; t < constant.size(); t++) {
			split = constant.get(t).split("\\s+");
			for (int i = 0; i < split.length; i++) {
				//判断字符串中是否有 “=”等号
				if (split[i].equals(FileConstant.EQUAL)) {
					originParam = split[i - 1];
					cloneParam = originParam + "_" + randomNum;
					log.info("原始数据+克隆数据{}" + originParam + "----------" + cloneParam);
					String replace = constant.get(t).replace(originParam, cloneParam);
					cloneParamMap.put(replace, replace);
					map.put(originParam, cloneParam);
					globalList.add(originParam);
					break;
				}

				//尾部是分号
				if (split[i].indexOf(FileConstant.BRANCH) >= 0) {
					String str = split[i].substring(split[i].length() - 1, split[i].length());
					//判断尾部是分号,且字符串中没有等号的
					if (!(split[i].equals(FileConstant.EQUAL)) && (str.equals(FileConstant.BRANCH))) {
						String substring = split[i].substring(0, split[i].length() - 1);
						originParam = substring;
						cloneParam = (originParam + "_" + randomNum);
						log.info("原始数据+克隆数据{}" + originParam + "----------" + cloneParam);
						String replace = constant.get(t).replace(originParam, cloneParam);
						cloneParamMap.put(replace, replace);
						map.put(originParam, cloneParam);
						globalList.add(originParam);
						break;
					}
				}
			}
		}

		cloneParamList.add(cloneParamMap);


		List<String> list1 = replaceData(map, methodCode);

		//去重的符合条件的代码块集合
		List<String> list = importStart(list1);

		for (String v : list) {
			System.out.println("{去重集合数据是}" + v);
		}

		//取出除方法之外以及大括号之外的代码块
		List<Map<String, String>> indoorCodeOutList = getIndoorCodeOut(list);

		//返回数据
		Map<String, List<List<Map<String, String>>>> maps = new HashMap<>();
		//方法内的代码集合
		returnList.add(indoorCodeOutList);
		//克隆的全局遍历集合
		returnList.add(cloneParamList);
		//fileName是文件名为了区分
		maps.put(fileName, returnList);
		return maps;
	}

	/**
	 * 获取不符合条件的字符串集合
	 *
	 * @param nonConformity 不符合条件的字符串集合
	 * @param global        全局变量集合
	 * @return
	 */
	@Deprecated
	public List<String> screen(List<String> nonConformity, List<String> global) {
		ArrayList<String> objects = new ArrayList<>();
		List<String> list1 = importStart(nonConformity);
		for (String s : list1) {
			for (int j = 0; j < global.size(); j++) {
				if (s.indexOf(global.get(j)) >= 0) {
					objects.add(s);
				}
			}
		}
		list1.removeAll(objects);
		return list1;
	}


	/**
	 * 获取方法内的代码块集合
	 *
	 * @param getIndoorList
	 * @return
	 */
	public static List<Map<String, String>> getIndoorCodeOut(List<String> getIndoorList) {

		Map<String, String> map = new HashMap<>();
		List<Map<String, String>> list = new ArrayList<>();

		for (int i = 0; i < getIndoorList.size(); i++) {
			//先对传进来的字符串进行分组
			String s = getIndoorList.get(i);
			String[] split = s.split("\\s+");
			for (int j = 0; j < split.length; j++) {
				switch (split[j]) {
					case FileConstant.BEFORETHREAD:
						String substring1 = s.substring(s.indexOf(FileConstant.BRACKETS_LEFT), s.length() - 1);
						map.put(FileConstant.BEFORETHREAD, substring1.substring(1));
						break;
					case FileConstant.BEFOREPROCESS:
						String substring2 = s.substring(s.indexOf(FileConstant.BRACKETS_LEFT), s.length() - 1);
						map.put(FileConstant.BEFOREPROCESS, substring2.substring(1));
						break;
					case FileConstant.BEFORE:
						String substring3 = s.substring(s.indexOf(FileConstant.BRACKETS_LEFT), s.length() - 1);
						map.put(FileConstant.BEFORE, substring3.substring(1));
						break;
					case FileConstant.TEST:
						String substring4 = s.substring(s.indexOf(FileConstant.BRACKETS_LEFT), s.length() - 1);
						String str = substring4.substring(1).trim();
						String substring = str.trim().substring(0, str.length());
						if (map.get(FileConstant.TEST) != null) {
							String o = (String) map.get(FileConstant.TEST);
							map.put(FileConstant.TEST, o + "\n" + substring);
						} else {
							map.put(FileConstant.TEST, "\n" + substring);
						}
						break;
				}
				break;
			}
		}
		list.add(map);


		return list;
	}

	/**
	 * 合并文件
	 *
	 * @param list list解释:
	 *             list内得第一个map:key是文件名字,以文件名字来区分是哪个文件得,保证唯一,前面得方法已经判断了是否重复
	 *             list内得第一个map:value则是对应得有几个文件得数据
	 *             List<List<Map<String, String>>>解释:
	 *             是每个文件得数据,里面同样用到了list,因为有全局变量、代码块、或者其他,且他们自己得数据也有多个
	 *             里面得map则是记录,例如before注解类里面得代码块,标记代码块是哪个注解里面得
	 * @return 文件类
	 */
	public MultipartFile mergeFileCode(List<Map<String, List<List<Map<String, String>>>>> list, List<String> importList) throws Exception {

		//创建空的文件
		String fileName = createFile();
		//全局变量集合
		List<String> globalList = new ArrayList<>();
		//@BeforeThread集合
		List<String> beforeThreadList = new ArrayList<>();
		//@Before集合
		List<String> beforeList = new ArrayList<>();
		//@BeforeProcess集合
		List<String> beforeProcessList = new ArrayList<>();
		//@Test集合
		List<String> testList = new ArrayList<>();
		//beforeThreadMap
		Map<String, List<String>> beforeThreadMap = new HashMap<>();
		//beforeMap
		Map<String, List<String>> beforeMap = new HashMap<>();
		//beforeProcessMap
		Map<String, List<String>> beforeProcessMap = new HashMap<>();
		//testMap
		Map<String, List<String>> testMap = new HashMap<>();


		//循环获取集合中的map,每一个map都是一个file文件,map中的key则是文件名,用文件名区别
		for (int l = 0; l < list.size(); l++) {
			//这里获取得key是文件名,通过key,也就是文件名遍历
			for (String key : list.get(l).keySet()) {
				List<List<Map<String, String>>> lists = list.get(l).get(key);
				//通过key(文件名)获取该文件对应得list集合数据,其中包括了多个list,对应得是全局变量得list、和代码块得list
				for (int i = 0; i < lists.size(); i++) {
					List<Map<String, String>> maps = lists.get(i);
					for (int j = 0; j < maps.size(); j++) {
						Map<String, String> map = maps.get(j);
						for (String s : map.keySet()) {

							//key和value相等就说明是全局变量,添加到全局变量得集合中
							if (s.equals(map.get(s))) {
								globalList.add(s);
							} else {
								//不相等就说明是代码块得数据,进来直接switch
								switch (s) {
									case FileConstant.BEFORETHREAD:
										beforeThreadList.add(map.get(s));
										beforeThreadMap.put(s, beforeThreadList);
										break;
									case FileConstant.BEFORE:
										beforeList.add(map.get(s));
										beforeMap.put(s, beforeList);
										break;
									case FileConstant.BEFOREPROCESS:
										beforeProcessList.add(map.get(s));
										beforeProcessMap.put(s, beforeProcessList);
										break;
									case FileConstant.TEST:
										testList.add(map.get(s));
										testMap.put(s, testList);
										break;
								}
							}
						}
					}
				}
			}
		}


		//import数据
		for (String a : importStart(importList)) {
			System.out.println(a);
		}

		//全局变量数据
		for (String a : importStart(globalList)) {
			System.out.println(a);
		}

		//beforeThread数据
		for (String s : beforeThreadMap.keySet()) {
			for (String a : importStart(beforeThreadMap.get(s))) {
				System.out.println(a);
			}
		}

		//before数据
		for (String s : beforeMap.keySet()) {
			for (String a : importStart(beforeMap.get(s))) {
				System.out.println(a);
			}
		}

		//beforeProcess数据
		for (String s : beforeProcessMap.keySet()) {
			for (String a : importStart(beforeProcessMap.get(s))) {
				System.out.println(a);
			}
		}

		//test数据
		for (String s : testMap.keySet()) {
			for (String a : importStart(testMap.get(s))) {
				System.out.println(a);
			}
		}

		//以上集合数据进行重组,为写入数据最准备
		List<String> codeList = getStrings(beforeThreadMap, beforeMap, beforeProcessMap, testMap);

		//写入数据
		MultipartFile multipartFile = writeFileCode(fileName, globalList, importList, codeList);
		return multipartFile;
	}

	private List<String> getStrings(Map<String, List<String>> beforeThreadMap,
									Map<String, List<String>> beforeMap,
									Map<String, List<String>> beforeProcessMap,
									Map<String, List<String>> testMap) {
		List<String> codeList = new ArrayList<>();
		String recombination = recombination(beforeThreadMap);
		String recombination1 = recombination(beforeMap);
		String recombination2 = recombination(beforeProcessMap);
		String recombination3 = recombination(testMap);
		codeList.add(recombination);
		codeList.add(recombination1);
		codeList.add(recombination2);
		codeList.add(recombination3);
		return codeList;
	}


	/**
	 * 数据重组,将数据外围包裹上注解、方法、修饰符、符号大括号
	 *
	 * @param map
	 * @return
	 */
	public String recombination(Map<String, List<String>> map) {
		String str = null;
		for (String s : map.keySet()) {
			switch (s) {
				case FileConstant.BEFORETHREAD:
					StringBuffer sb1 = new StringBuffer();
					sb1.append(FileConstant.BEFORETHREAD);
					sb1.append("\n");
					sb1.append(FileConstant.startBeforeThread + FileConstant.CURVES + FileConstant.BRACKETS_LEFT);
					sb1.append("\n");
					for (int i = 0; i < map.get(s).size(); i++) {
						String split = split(map.get(s).get(i));
						sb1.append(split);
						sb1.append("\n");
					}
					sb1.append(FileConstant.BRACKETS_RIGHT);
					str = sb1.toString();
					break;
				case FileConstant.BEFORE:
					StringBuffer sb2 = new StringBuffer();
					sb2.append(FileConstant.BEFORE);
					sb2.append("\n");
					sb2.append(FileConstant.startBefore + FileConstant.CURVES + FileConstant.BRACKETS_LEFT);
					sb2.append("\n");
					for (int i = 0; i < map.get(s).size(); i++) {
						sb2.append(map.get(s).get(i));
						sb2.append("\n");
					}
					sb2.append(FileConstant.BRACKETS_RIGHT);
					str = sb2.toString();
					break;
				case FileConstant.BEFOREPROCESS:
					StringBuffer sb3 = new StringBuffer();
					sb3.append(FileConstant.BEFOREPROCESS);
					sb3.append("\n");
					sb3.append(FileConstant.startBeforeProcess + FileConstant.CURVES + FileConstant.BRACKETS_LEFT);
					sb3.append("\n");
					for (int i = 0; i < map.get(s).size(); i++) {
						sb3.append(map.get(s).get(i));
						sb3.append("\n");
					}
					sb3.append(FileConstant.BRACKETS_RIGHT);
					str = sb3.toString();
					break;
				case FileConstant.TEST:
					StringBuffer sb4 = new StringBuffer();
					sb4.append(FileConstant.TEST);
					sb4.append("\n");
					sb4.append(FileConstant.startTest + FileConstant.CURVES + FileConstant.BRACKETS_LEFT);
					sb4.append("\n");
					for (int i = 0; i < map.get(s).size(); i++) {
						String s1 = updateGolaData(map.get(s).get(i));
						sb4.append(s1);
						sb4.append("\n");
					}
					sb4.append(FileConstant.BRACKETS_RIGHT);
					str = sb4.toString();
					break;
			}

		}
		return str;
	}

	/**
	 * 向文件写入信息
	 *
	 * @param fileName
	 * @param globalList
	 * @param codeList
	 * @throws Exception
	 */
	public MultipartFile writeFileCode(String fileName,
									   List<String> globalList,
									   List<String> importList,
									   List<String> codeList) throws Exception {
		//根据传过来的fileName查询文件是否存在,不存在则抛出异常
		File file = new File(FileConstant.FILE_DIR_PATH + "/" + fileName);
		if (!file.exists()) {
			throw new FileException(FileStatusEnum.FILE_NOT_NO.getCode(), FileStatusEnum.FILE_NOT_NO.getMsg());
		} else {
			//存在则输入数据
			FileWriter fw = new FileWriter(file.getAbsoluteFile());
			BufferedWriter bw = new BufferedWriter(fw);
			for (String a : importStart(importList)) {
				try {
					bw.write(a);
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			bw.write("\r\n");
			bw.write(FileConstant.RUN_WITH);
			bw.write("\r\n");
			bw.write(FileConstant.CLAZZ + " " + FileConstant.TEST_RUNER + FileConstant.BRACKETS_LEFT);
			bw.write("\r\n");//换行符
			for (String b : importStart(globalList)) {
				try {
					bw.write(b);
					bw.write("\r\n");
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			for (String c : importStart(codeList)) {
				try {
					bw.write(c);
					bw.write("\r\n");
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			bw.write(FileConstant.BRACKETS_RIGHT);
			bw.close();
		}
		FileInputStream fileInputStream = new FileInputStream(file);
		MultipartFile multipartFile = new MockMultipartFile(file.getName(), file.getName(),
			ContentType.APPLICATION_OCTET_STREAM.toString(), fileInputStream);

		return multipartFile;
	}

	/**
	 * 创建合并脚本
	 *
	 * @return
	 * @throws Exception
	 */
	public String createFile() throws Exception {
		//在服务器上创建文件夹,如果在本地启动,则直接是在tomcat的bin文件下创建了
		File dir = new File(FileConstant.FILE_DIR_PATH);
		if (!dir.exists()) {
			dir.mkdirs();
		}
		String s = randomNum(5);
		File file = new File(FileConstant.FILE_PATH + "_" + s + FileConstant.SUFFIX);

		if (!file.exists()) {
			file.createNewFile();
			log.info("{文件创建成功}");
		} else {
			throw new FileException(FileStatusEnum.FILE_EXIST.getCode(), FileStatusEnum.FILE_EXIST.getMsg());
		}
		return file.getName();
	}

	/**
	 * 随机数
	 *
	 * @return
	 */
	public String randomNum(int number) {
		Random rand = new Random();
		char[] letters = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
			'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
			'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'r',
			'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
		String str = "";
		int index;
		boolean[] flags = new boolean[letters.length];//默认为false
		for (int i = 0; i < number; i++) {
			do {
				index = rand.nextInt(letters.length);
			} while (flags[index] == true);
			char c = letters[index];
			str += c;
			flags[index] = true;
		}
		return str;
	}

	/**
	 * 查询字符串中有多少个同样的字符串出现过,返回count
	 *
	 * @param str
	 * @param key
	 * @return
	 */
	public int getCount(String str, String key) {
		if (str == null || key == null || "".equals(str.trim()) || "".equals(key.trim())) {
			return 0;
		}
		int count = 0;
		int index = 0;
		while ((index = str.indexOf(key, index)) != -1) {
			index = index + key.length();
			count++;
		}
		return count;
	}


	public List<String> getAnnotation(String str) {

		Map<String, String> map = new HashMap<>();

		List<String> list = new ArrayList<>();
		for (String a : FileConstant.annotationArray) {
			if (a.equals(FileConstant.BEFOREPROCESS)) {
				String substring1 = str.substring(str.indexOf(a));
				String substring = substring1.substring(0, substring1.indexOf(FileConstant.BRACKETS_RIGHT));
				list.add((substring + FileConstant.BRACKETS_RIGHT).trim());
				String replace = str.replace(a, "");
				map.put(FileConstant.BEFORETHREAD, replace);
			}

			if (a.equals(FileConstant.BEFORETHREAD)) {
				String beforeThread = map.get(FileConstant.BEFORETHREAD);
				String substring1 = beforeThread.substring(beforeThread.indexOf(a));
				String substring = substring1.substring(0, substring1.indexOf(FileConstant.BRACKETS_RIGHT));
				list.add((substring + FileConstant.BRACKETS_RIGHT).trim());
				String before = beforeThread.replace(a, "");
				map.put(FileConstant.BEFORE, before);
			}

			if (a.equals(FileConstant.BEFORE)) {
				String before = map.get(FileConstant.BEFORE);
				String before1 = getBefore(before);
				//获取@Before到文本最后的位置
				String substring = before.substring(before.indexOf(a), before.length() - 1);
				String substring2 = substring.substring(0, substring.indexOf(FileConstant.BRACKETS_LEFT));
				list.add(substring2 + FileConstant.BRACKETS_LEFT + "\r\n" + (before1 + FileConstant.BRACKETS_RIGHT).trim());
			}
		}

		//获取test注解文本
		List<String> testStr = getTestStr(str);
		for (String c : testStr) {
			list.add(c);
		}
		return list;
	}


	/**
	 * 获取@Test注解的文本
	 *
	 * @param str 原始字符串
	 * @return list 返回list集合
	 */
	public List<String> getTestStr(String str) {
		int i;
		String substring1;
		int count;
		String reverse;
		List<String> testList = new ArrayList<>();

		//首先获取第一个@Test注解的位置,如何@Test根据indexOf获取的位置是第一个
		i = str.indexOf(FileConstant.TEST);

		String trim = str.trim();
		//从第一个注解位置截取到最后一位,获取到则是@Test注解的全部代码块,可以理解成一个list,或者是单个,不包括整个类开始和结束的大括号
		substring1 = trim.substring(i, trim.length() - 1);

		//判断test注解有多少个
		count = getCount(substring1, FileConstant.TEST);

		Map<String, String> strMap = new HashMap<>();

		//对字符串进行反转
		reverse = revString(substring1);

		for (int a = 0; a < count; a++) {

			if (a == 0) {
				//通过括号和反转test注解获取字符串中,全部的@Test部分,不包括类的大括号
				String substring2 = reverse.substring(reverse.indexOf(FileConstant.BRACKETS_RIGHT), reverse.indexOf(FileConstant.REVERSE_TEST));
				testList.add(FileConstant.TEST + revString(substring2));
				//substring方法,获取剩余的字符串,添加到map中
				String s = subString(reverse, reverse.indexOf(FileConstant.REVERSE_TEST), reverse.length());
				strMap.put(FileConstant.REVERSE_TEST, s.replaceFirst(FileConstant.REVERSE_TEST, "").trim());
			}
			if (a > 0) {
				String testStr = strMap.get(FileConstant.REVERSE_TEST);
				String substring2 = testStr.substring(testStr.indexOf(FileConstant.BRACKETS_RIGHT), testStr.indexOf(FileConstant.REVERSE_TEST));
				testList.add(FileConstant.TEST + revString(substring2));
				String s = subString(testStr, testStr.indexOf(FileConstant.REVERSE_TEST), testStr.length());
				strMap.put(FileConstant.REVERSE_TEST, s.replaceFirst(FileConstant.REVERSE_TEST, "").trim());
			}
		}

		return testList;
	}


	/**
	 * 已弃用,循环删除多个下标出现乱码
	 * 删除指定下标的字符串
	 *
	 * @param str        原始字符串
	 * @param startIndex 开始下标
	 * @param endIndex   结束下标
	 * @return
	 */
	@Deprecated
	public String replaceStr(String str, int startIndex, int endIndex) {

		Map<String, String> map = new HashMap<>();
		char[] chars = str.toCharArray();
		for (int i = 0; i <= endIndex; i++) {
			if (i == 0) {
				String replace = str.replace(chars[i], '~');
				String replace1 = replace.replace("~", "");
				map.put("str", replace1);
			} else {
				String str1 = map.get("str");
				String replace = str1.replace(chars[i], '~');
				String replace1 = replace.replace("~", "");
				map.put("str", replace1);
			}
		}
		return str;
	}


	/**
	 * 根据下标截取
	 *
	 * @param str
	 * @param startIndex
	 * @param endIndex
	 * @return
	 */
	public String subString(String str, int startIndex, int endIndex) {
		String substring = str.substring(startIndex, endIndex);
		return substring;
	}


	/**
	 * 将字符串反转
	 *
	 * @param str
	 * @return
	 */
	public String revString(String str) {
		StringBuffer sb = new StringBuffer(str);
		//将缓冲区的内容反转
		sb.reverse();
		return sb.toString();
	}

	/**
	 * 对全局代码块中的全局变量进行全局修改名称,避免重复
	 *
	 * @param map
	 * @param list
	 * @return
	 */
	public List<String> replaceData(Map<String, String> map, List<String> list) {

		//返回list
		List<String> resultList;
		//map集合,key是原始数据,vaue是克隆数据
		Set<String> strings = map.keySet();
		//随机标识
		String s1 = randomNum(5);

		//将list中的数据全部拿出来,以唯一标识拼接,拼接成一个字符串,因为循环去改数据有bug
		StringBuffer sb = new StringBuffer();
		for (String a : list) {
			sb.append(a);
			sb.append(s1);
		}
		String replace = null;
		List<String> objects = new ArrayList<>();

		//将map转为集合
		for (String s : strings) {
			objects.add(s);
		}

		//循环去修改字符串中的全局变量,对合成的字符串全体修改
		for (int i = 0; i < objects.size(); i++) {
			if (i == 0) {
				StringBuffer s5 = new StringBuffer(sb);
				replace = s5.toString().replace(objects.get(i), map.get(objects.get(i)));
			} else {
				replace = replace.replace(objects.get(i), map.get(objects.get(i)));
			}
		}

		//上面修改完后根据刚刚生成的随机字符进行分割成数组返回
		String[] split = replace.split(s1);
		resultList = new ArrayList<>(Arrays.asList(split));
		for (String a : resultList) {
			System.out.println("对代码块中更换数据:" + a);
		}
		for (String n : resultList) {
			System.out.println("" + n);
		}

		return resultList;
	}

	/**
	 * 根据传过来的多个文件,形成一个文件夹名字
	 *
	 * @param str
	 * @return
	 */
	public String makeFileName(String str) {

		StringBuffer sb = new StringBuffer();
		//根据逗号进行分割
		String[] split = str.split(FileConstant.COMMA);
		for (String s : split) {
			String substring = s.substring(0, s.lastIndexOf(FileConstant.SUFFIX));
			sb.append(substring);
			sb.append(FileConstant.SLASH);
		}
		return sb.toString().substring(0, sb.length() - 1);
	}


	/**
	 * 获取import开头的数据
	 *
	 * @param str 原始字符串
	 * @return
	 */
	public List<String> getImportStr(String str) {

		List<String> list = new ArrayList<>();
		String sb = str.substring(0, str.indexOf(FileConstant.RUNWITH));
		String[] split = sb.split("\n");
		for (String b : split) {
			if (StrUtil.startWith(b, FileConstant.IMPORT)) {
				list.add(b);
			}
		}

		return list;
	}


	/**
	 * 获取开头是全局变量
	 *
	 * @param str
	 * @return
	 */
	public List<String> getPublicStr(String str) {
		List<String> list = new ArrayList<>();
		String[] split = str.split("\n");
		for (String b : split) {
			String trim = b.trim();
			if (!StrUtil.endWith(trim, FileConstant.BRACKETS_LEFT) && !trim.contains(FileConstant.CURVES_LEFT) && !trim.contains(FileConstant.CURVES_RIGHT)) {
				for (String c : FileConstant.MODIFIER) {
					if (StrUtil.startWith(trim, c)) {
						list.add(b.trim());
					}
					//根据数据类型
					if (isDataType(trim)) {
						list.add(b.trim());
					}
				}
			}
		}
		return list;
	}


	/**
	 * 判断字符串中是否右等号何分号的
	 *
	 * @param str
	 * @return
	 */
	public boolean isEquaBranch(String str) {
		boolean flag = false;
		if ((str.indexOf(FileConstant.EQUAL) >= 0) && (str.substring(str.length() - 1).equals(FileConstant.BRANCH))) {
			flag = true;
		}
		return flag;
	}

	/**
	 * 根据数据类型判断
	 *
	 * @param str
	 * @return
	 */
	public boolean isDataType(String str) {
		boolean flag = false;
		if (str.indexOf(DataTypeConstant.INT_1) >= 0) {
			flag = true;
		}
		if (str.indexOf(DataTypeConstant.BYTE_1) >= 0) {
			flag = true;
		}
		if (str.indexOf(DataTypeConstant.SHORT_1) >= 0) {
			flag = true;
		}
		if (str.indexOf(DataTypeConstant.LONG_1) >= 0) {
			flag = true;
		}
		if (str.indexOf(DataTypeConstant.FLOAT_1) >= 0) {
			flag = true;
		}
		if (str.indexOf(DataTypeConstant.DOUBLE_1) >= 0) {
			flag = true;
		}
		if (str.indexOf(DataTypeConstant.CHAR_1) >= 0) {
			flag = true;
		}
		if (str.indexOf(DataTypeConstant.BOOLEAN_1) >= 0) {
			flag = true;
		}
		if (str.indexOf(DataTypeConstant.STRING_1) >= 0) {
			flag = true;
		}
		if (str.indexOf(DataTypeConstant.DEF_1) >= 0) {
			flag = true;
		}
		if (str.indexOf(DataTypeConstant.VAR_1) >= 0) {
			flag = true;
		}
		if (str.indexOf(DataTypeConstant.LEF_1) >= 0) {
			flag = true;
		}
		if (str.indexOf(DataTypeConstant.INTEGER_2) >= 0) {
			flag = true;
		}
		if (str.indexOf(DataTypeConstant.BYTE_2) >= 0) {
			flag = true;
		}
		if (str.indexOf(DataTypeConstant.SHORT_2) >= 0) {
			flag = true;
		}
		if (str.indexOf(DataTypeConstant.LONG_2) >= 0) {
			flag = true;
		}
		if (str.indexOf(DataTypeConstant.FLOAT_2) >= 0) {
			flag = true;
		}
		if (str.indexOf(DataTypeConstant.DOUBLE_2) >= 0) {
			flag = true;
		}
		if (str.indexOf(DataTypeConstant.CHARACTER_2) >= 0) {
			flag = true;
		}
		if (str.indexOf(DataTypeConstant.BOOLEAN_2) >= 0) {
			flag = true;
		}
		return flag;
	}

	/**
	 * 获取before字符串
	 *
	 * @param s
	 * @return
	 */
	public String getBefore(String s) {

		char prefix = '{';

		char suffix = '}';

		String beforeCode = null;

		List<Integer> list = new ArrayList<>();

		//传过来的字符串,Before注解肯定是排在最前面的,那么只需要获取其他注解的位置,下标最小的则视为是在Before后面的注解,然后根据此注解作为endSplit
		int a = s.indexOf(FileConstant.BEFOREPROCESS);
		int b = s.indexOf(FileConstant.TEST);
		int c = s.indexOf(FileConstant.BEFORETHREAD);

		if (a != -1) {
			list.add(a);
		}
		if (b != -1) {
			list.add(b);
		}
		if (c != -1) {
			list.add(c);
		}
		//对集合进行排序,排第一个的则是最小的
		Collections.sort(list);

		Map<Integer, String> map = new LinkedHashMap<>();
		map.put(a, FileConstant.BEFOREPROCESS);
		map.put(b, FileConstant.TEST);
		map.put(c, FileConstant.BEFORETHREAD);

		//等于0则代表后面没用方法了,也没用方法了。
		if (a == -1 && b == -1 && c == -1) {
			String substring = s.substring(s.indexOf(prefix), s.length() - 1).trim();
			beforeCode = StrUtil.unWrap(substring, prefix, suffix);

		} else if (a + b + c >= 0) {
			String s1 = map.get(list.get(0));
			String substring1 = s.substring(s.indexOf(FileConstant.BEFORE), s.length() - 1);
			System.out.println(substring1);
			String substring = substring1.substring(substring1.indexOf(prefix), substring1.indexOf(s1)).trim();
			beforeCode = StrUtil.unWrap(substring, prefix, suffix);
		}
		return beforeCode;
	}


	/**
	 * 对@BeforeThread注解当中的方法中的record方法,当中的第二个参数为指定的测试方法,现在指定为test
	 * 对合成的代码当中,全部改为test一样的,因为全局变量修改代码块的时候如果测试方法是一样的,则会进行
	 * 覆盖掉
	 *
	 * @param str
	 * @return
	 */
	public String split(String str) {

		String substring;
		String substring1 = null;
		String joint = null;

		String[] split = str.split("\n");
		for (String s : split) {
			if (s.indexOf(FileConstant.RECORD) >= 0) {
				//获取左边括号的位置何右边的位置
				int i = s.indexOf(FileConstant.CURVES_LEFT);
				int i1 = s.indexOf(FileConstant.COMMA);
				//获取到形参里面的参数
				substring = s.substring(i + 1, i1);

				//获取到原始数据
				substring1 = s.substring(i, s.length());

				//进行拼接
				joint = FileConstant.CURVES_LEFT + substring + FileConstant.COMMA + "\"test\")";
			}
		}

		String replace1 = str.replace(substring1, joint);

		return replace1;
	}


	/**
	 * 主要是获取局部变量的字段
	 *
	 * @param str
	 * @return
	 */
	public String updateGolaData(String str) {

		String replace = null;
		//1.对字符串进行分割,以行数分割
		String[] split = str.split("\n");
		//局部字符串集合
		List<String> list = new ArrayList<>();

		//局部变量集合
		List<String> localList = new ArrayList<>();

		//判断,符合条件的则视为局部变量
		for (String s : split) {
			int i = s.indexOf(FileConstant.EQUAL);
			int i1 = s.indexOf(FileConstant.EQUAL_TWO);
			if (i >= 0 && i1 <= 0) {
				list.add(s);
			}
		}
		for (int i = 0; i < list.size(); i++) {
			//对字符串进行分割
			String trim = list.get(i).trim();
			//以空格分割
			String[] split1 = trim.split("\\s+");
			if (split1[2].equals(FileConstant.EQUAL)) {
				//获取局部变量数据
				localList.add(split1[1]);
			}
		}
		//对代码块进行替换数据.替换局部变量数据
		for (String localStr : localList) {
			int localStr1 = str.indexOf("localStr");
			if (localStr1 >= 0) {
				throw new FileException(FileStatusEnum.NON_CONFORMITY.getCode(), FileStatusEnum.NON_CONFORMITY.getMsg());
			}

			//小于零则代表局部变量名是符合规则的,并不是单个字符,或者在代码块中有存在的
			if (localStr1 < 0) {
				String s1 = randomNum(4);
				replace = str.replace(localStr, localStr + "_" + s1);
			}
		}
		//如果没有全局变量,则返回原始数据
		if (localList.size() == 0) {
			replace = str;
		}

		return replace;
	}

}

常量类:

package org.ngrinder.script.common;

/**
 * @Author xiaoxin
 * @Date 2021/9/8 9:26
 * @Version 1.0
 */

public class DataTypeConstant {

	/**
	 * 数据类型
	 */
	public static final String INT_1 = "int";
	public static final String BYTE_1 = "byte";
	public static final String SHORT_1 = "short";
	public static final String LONG_1 = "long";
	public static final String FLOAT_1 = "float";
	public static final String DOUBLE_1 = "double";
	public static final String CHAR_1 = "char";
	public static final String BOOLEAN_1 = "boolean";
	public static final String STRING_1 = "String";
	public static final String DEF_1 = "def";
	public static final String VAR_1 = "var";
	public static final String LEF_1 = "lef";
	public static final String INTEGER_2 = "Integer";
	public static final String LONG_2 = "Long";
	public static final String BOOLEAN_2 = "Boolean";
	public static final String SHORT_2 = "Short";
	public static final String CHARACTER_2 = "Character";
	public static final String BYTE_2 = "Byte";
	public static final String FLOAT_2 = "Float";
	public static final String DOUBLE_2 = "Double";


}
package org.ngrinder.script.common;

/**
 * @Author xiaoxin
 * @Date 2021/9/7 17:28
 * @Version 1.0
 */

public class FileConstant {

	/**
	 * 类开头注解
	 */
	public static final String RUNWITH = "@RunWith";

	/**
	 * class
	 */
	public static final String CLAZZ = "class";

	/**
	 * code
	 */
	public static final String CODE = "code";

	/**
	 * msg
	 */
	public static final String MSG = "msg";

	/**
	 * 左小括号
	 */
	public static final String CURVES_LEFT = "(";

	/**
	 * 右小括号
	 */
	public static final String CURVES_RIGHT = ")";

	/**
	 * 括号
	 */
	public static final String CURVES = "()";

	/**
	 * 逗号
	 */
	public static final String COMMA = ",";

	/**
	 * 合成生成的类名
	 */
	public static final String TEST_RUNER = "TestRuner";
	/**
	 * 左大括号
	 */
	public static final String BRACKETS_LEFT = "{";
	/**
	 * 右大括号
	 */
	public static final String BRACKETS_RIGHT = "}";

	/**
	 *
	 */
	public static final String SLASH = "/";

	/**
	 * 注解数组
	 */
	public static final String[] annotationArray = {"@BeforeProcess", "@BeforeThread", "@Before", "@Test"};

	/**
	 * 类之外的import文件引入
	 */
	public static final String IMPORT = "import";
	/**
	 * @Before注解
	 */
	public static final String BEFORE = "@Before";
	/**
	 * @test注解
	 */
	public static final String TEST = "@Test";

	public static final String PUBLIC = "public";
	/**
	 * @BeforeProcess注解
	 */
	public static final String BEFOREPROCESS = "@BeforeProcess";
	/**
	 * @BeforeThread注解
	 */
	public static final String BEFORETHREAD = "@BeforeThread";

	/**
	 * test注解反转
	 */
	public static final String REVERSE_TEST = "tseT@";
	/**
	 * 尾部分号
	 */
	public static final String BRANCH = ";";
	/**
	 * 相等
	 */
	public static final String EQUAL = "=";

	public static final String SPOT = ".";

	/**
	 *
	 */
	public static final String EQUAL_TWO = "==";

	public static final String RUN_WITH = "@RunWith(GrinderRunner)";
	/**
	 * 类上的注解
	 */
//	public static final String[] RUN_WITH = {"@RunWith(GrinderRunner)", "@RunWith(GrinderRunner.class)"};
	/**
	 * 类开头
	 */
	public static final String[] START_CLASS = {"public", "class"};
	/**
	 * 修饰符
	 */
	public static final String[] MODIFIER = {"public", "private", "protected", "default"};

	/**
	 * 方法开头字符串
	 */
	public static final String startBeforeThread = "public void beforeThread";

	public static final String startBefore = "public void before";

	public static final String startBeforeProcess = "public static void beforeProcess";

	public static final String startTest = "public void test";

	/**
	 * 文件路径
	 */
	public static final String FILE_DIR_PATH = "/home/ngrinder/scriptFile";

	public static final String FILE_DIR_PATHS = "/home/ngrinder/scriptFile/";

	/**
	 * 文件路径加文件首字母
	 */
	public static final String FILE_PATH = "/home/ngrinder/scriptFile/FuseScript";

	/**
	 * 文件后缀
	 */
	public static final String SUFFIX = ".groovy";

	/**
	 * 全局record方法
	 */
	public static final String RECORD = "record";


	public static final String DESCRIBE = "合成脚本测试";

	public static final String EXCEPTION = "Exception";

	public static final String ERROR = "ERROR";




}
package org.ngrinder.script.common;

/**
 * @Author xiaoxin
 * @Date 2021/9/8 9:42
 * @Version 1.0
 */

public enum FileStatusEnum {

	UP_TO_TWO(1001,"最少为2个文件才可以进行合并"),

	UP_TO_TREE(1002, "目前仅支持最多合成三个文件"),

	FILE_EXIST(1003, "文件已存在"),

	FILE_NOT_NO(1004, "文件不存在"),

	FORBID_MERGE(1005,"已合并的脚本不能再一次进行合并,请选择其他脚本"),

	NON_CONFORMITY(1006,"局部变量命名不符合合并规则,请手动进行更改,不得以单个字符、以及变量名和方法内的代码块有任何的重复"),

	SCRIPT_FILE_VALID_SUCCESS(1007,"操作完成,验证脚本正常"),

	SCRIPT_FILE_VALID_ERROR(1008,"验证失败,当前脚本可能存在语法或其他问题,请查看详细信息");

	private int code;

	private String msg;

	private FileStatusEnum(int code, String msg) {
		this.code = code;
		this.msg = msg;
	}

	private FileStatusEnum(int code) {
		this.code = code;
	}

	private FileStatusEnum(String msg) {
		this.msg = msg;
	}

	public int getCode() {
		return code;
	}

	public void setCode(int code) {
		this.code = code;
	}

	public String getMsg() {
		return msg;
	}

	public void setMsg(String msg) {
		this.msg = msg;
	}

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值