content: package com.alibaba.markovdemo.engine.stages;
  
  import com.alibaba.fastjson.JSONObject;
  
  import com.alibaba.markovdemo.BO.TestRespone;
  import com.alibaba.markovdemo.engine.plugins.IPlugin;
  import com.alibaba.markovdemo.engine.plugins.PluginFactory;
  import com.alibaba.markovdemo.engine.plugins.PluginLayout;
  import com.google.gson.Gson;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  import org.springframework.stereotype.Service;
  import sun.reflect.generics.reflectiveObjects.NotImplementedException;
  import org.codehaus.groovy.util.ListHashMap;
  
  import java.util.*;
  
  @Service
  public class BaseStage {
  
      private static final Logger LOGGER = LoggerFactory.getLogger(BaseStage.class);
  
      public StageName name;
      public Long scenarioId;
      public Long testcaseId;
      static final String BeforeExecKey = "before_exec";
      static final String ExecKey = "exec";
      static final String AfterExecKey = "after_exec";
      static final String PLUGIN_TYPE_KEY = "plugin_type";
      static final String PLUGIN_NAME_KEY = "plugin_name";
      static final String DISPLAY_NAME_KEY = "display_name";
  
      Map<String,List<RunData>> stageRunDataMap = new HashMap<>();
      //输入对象
      Object inputObj;
      //stage参数
      Map<StageName,Object> stageParams;
      //plugin_name => IPlugin
      Map<String, IPlugin> pluginNameMap = new HashMap<>();
  
      //一个stage阶段可能执行多个数据组
      public String groupName;
  
      //1:单次 2:回归
      public String runType = "1";
  
      public LinkedList<JSONObject> pluginList = new LinkedList<>();
  
  
      public Map<String, LinkedList<JSONObject>> pluginMap = new HashMap<>();
  
      //中间结果收集
      public List<LogInfo> logCollection = new ArrayList<>();
  
      //存放stage的数据,包括输入/输出/期望/执行结果/校验内容
      public RunData runData = new RunData();
  
      //将所有存在信息都进行保存
      public List<RunData> runDataList = new ArrayList<>();
  
      public JSONObject stageJsonObj;
  
      public Long getScenarioId() {
          return scenarioId;
      }
  
      public void setScenarioId(Long scenarioId) {
          this.scenarioId = scenarioId;
      }
  
      public Long getTestcaseId() {
          return testcaseId;
      }
  
      public void setTestcaseId(Long testcaseId) {
          this.testcaseId = testcaseId;
      }
  
      public Map<String, LinkedList<JSONObject>> getPluginMap() {
          return pluginMap;
      }
  
      public void setPluginMap(Map<String, LinkedList<JSONObject>> map) {
          pluginMap = map;
      }
      public JSONObject getStageJsonObj() {
          return stageJsonObj;
      }
  
      public void setStageJsonObj(JSONObject stageJsonObj) {
          this.stageJsonObj = stageJsonObj;
      }
  
      public Map<StageName, Object> getStageParams() {
          return stageParams;
      }
  
      public String getRunType() {
          return runType;
      }
  
      public void setRunType(String runType) {
          this.runType = runType;
      }
      public List<RunData> getRunDataList() {
          return runDataList;
      }
  
      public void setRunDataList(List<RunData> runDataList) {
          this.runDataList = runDataList;
      }
  
      public void setStageParams(
          Map<StageName, Object> stageParams) {
          this.stageParams = stageParams;
      }
  
      public LogInfo findByPluginName(String pluginName){
  
          if (logCollection.size() > 0) {
              for(LogInfo search : logCollection){
                  if (search.getPluginName().equals(pluginName)){
                      return search;
                  }
              }
          }
          return null;
      }
      public String getGroupName() {
          return groupName;
      }
  
      public void setGroupName(String groupName) {
          this.groupName = groupName;
      }
  
  
      public void init() {
          throw new NotImplementedException();
      }
  
      public StageName getName() {
          return name;
      }
  
      public void setName(StageName name) {
          this.name = name;
      }
  
  
  
      public void setRunData() {
          //转化为string OR JsonString
          this.runData = runData;
          runData.setResult(1);
          Gson gosn = new Gson();
          runData.setInput(gosn.toJson(inputObj));
          runData.setScenarioId(scenarioId);
          runData.setTestcaseId(testcaseId);
      }
  
      public void setRunDataCheckConf(String calFieldsConfig){
          this.runData.setCalFieldsConfig(calFieldsConfig);
      }
  
      public Map<String, List<RunData>> getStageRunDataMap() {
          return stageRunDataMap;
      }
  
      public void setStageRunDataMap(Map<String, List<RunData>> stageRunDataMap) {
          this.stageRunDataMap = stageRunDataMap;
      }
  
      public List<LogInfo> getLogCollection() {
          return logCollection;
      }
  
      public void setLogCollection(List<LogInfo> logCollection) {
          this.logCollection = logCollection;
      }
  
      public void setPrepareData(String data){
          runData.setInput(data);
      }
  
  
      public TestRespone setTestRespone(TestRespone testRespone){
  
          return testRespone;
      }
  
  
      /**
       * 函数功能:整合展示日志,对于check阶段,需要加入input/output/expect/result/log.其他阶段只有input/output/log
       * @param data
       * @param stageName
       * @return
       */
      public String logFormat(RunData data, StageName stageName){
  
          String showLog = "";
  
          showLog += "======================[INPUT]======================\n";
  
          showLog += "======================[OUTPUT]======================\n";
  
          showLog += "======================[LOG]======================\n";
          showLog +=  data.getLog() + "\n";
  
          return showLog;
      }
  
      public void setIputData(Object inputObj){
          this.inputObj = inputObj;
      }
  
      /**
       * 函数功能:收集中间结果Log,将本阶段所有log进行收集
       * @param data
       * @param pluginName
       */
      public void startLogCollect(RunData data, String pluginName){
          LogInfo logInfo = new LogInfo();
          logInfo.setStageName(name);
          logInfo.setGroupName(groupName);
          logInfo.setPluginName(pluginName);
          logInfo.setRunData(data);
          logInfo.setLog(logFormat(data, name));
          logCollection.add(logInfo);
      }
  
      public void beforeExec() {
          //TODO:在每个流程执行时,有些会有预先默认的系统插件,比如占位符替换
          LOGGER.debug(String.format("beforeExec start"));
          pluginExec(BeforeExecKey);
      }
  
      public void afterExec() {
  
          LOGGER.debug(String.format("afterExec start"));
          pluginExec(AfterExecKey);
      }
  
      //1.执行pluginList. 2.收集中间结果
      public void exec(){
          LOGGER.debug(String.format("exec start"));
          pluginExec(ExecKey);
      }
  
  
      /**
       * 函数功能:单个plugin插件执行
       * @param key
       */
      public void pluginExec(String key){
  
          LinkedList<JSONObject> plugins = pluginMap.get(key);
          IPlugin p;
          if("exec".equals(key)){
              runDataList = new ArrayList<>();
          }
  
          for (JSONObject pluginObj : plugins) {
  
              String pluginName = (String)pluginObj.get("plugin_name");
              LOGGER.info("[执行插件:" + pluginName + "]");
  
              p = pluginNameMap.get(pluginName);
              //第一个插件使用控制器传进来的,之后的插件获取上个插件的结果
              p.setPluginParams(pluginObj);
              p.setRunData(runData);
  
  
              p.setStageParamsObj(stageParams);
  
              p.beforeExec();
  
              LOGGER.debug(String.format("Plugin {0} executed beforeExec method.", p.getName()));
  
              p.exec();
              LOGGER.debug(String.format("Plugin {0} executed exec method.", p.getName()));
              //搜集插件结果集
              if("exec".equals(key)){
                  runDataList.add((RunData) runData.clone());
              }
              p.afterExec();
              LOGGER.debug(String.format("Plugin {0} executed afterExec method.", p.getName()));
  
              //收集插件list的中间结果
              startLogCollect(runData,p.getName());
  
              //进行一次output设置为input
              runData.setInput(p.getRunData().getOutput());
          }
      }
  
      public void cleanup() {
          throw new NotImplementedException();
      }
  
      /**
       * 函数功能:插件添加
       * @param pluginObj
       */
      public void addPlugin(JSONObject pluginObj) {
  
          this.pluginList.add(pluginObj);
      }
  
      /**
       * 函数功能:插件初始化
       * @param stageName
       * @param stageJsonObj
       * @return
       */
      public BaseStage build(StageName stageName, JSONObject stageJsonObj) {
  
          this.name = stageName;
          this.stageJsonObj = stageJsonObj;
          String[] execList = {BeforeExecKey,ExecKey,AfterExecKey};
          //plugin_name => IPlugin
          pluginNameMap = new HashMap<>();
          for(String execName : execList){
              pluginList = new LinkedList<>();
              if (stageJsonObj.containsKey(execName) && stageJsonObj.get(execName) instanceof JSONObject){
                  stageJsonObj = (JSONObject)stageJsonObj.get(execName);
                  stageJsonObj.putAll(this.stageJsonObj);
                  if (stageJsonObj.containsKey("pluginList")) {
                      for (Object obj : stageJsonObj.getJSONArray("pluginList")) {
                          JSONObject jsObj = (JSONObject) obj;
                          String pluginName = (String)jsObj.get("plugin_name");
                          if (!pluginNameMap.containsKey(pluginName)){
                              IPlugin plugin = PluginFactory.getPlugin(jsObj ,stageJsonObj);
                              pluginNameMap.put(pluginName,plugin);
                          }
                          this.addPlugin(jsObj);
                      }
                  }
              }
              this.pluginMap.put(execName, pluginList);
          }
  
          return this;
      }
  
      /**
       * 函数功能:build出pipeline阶段中的布局对象,主要是插件信息,在prepareData/send/get/check阶段使用到
       * @return
       */
      public List<PluginLayout> buildLayout(){
  
          List<PluginLayout> pluginLayoutList = new ArrayList<>();
          String[] execList = {BeforeExecKey,ExecKey,AfterExecKey};
          for (String execKey : execList){
              if (this.stageJsonObj.containsKey(execKey) && stageJsonObj.get(execKey) instanceof JSONObject){
  
                  JSONObject execJson = (JSONObject)stageJsonObj.get(execKey);
  
                  if (execJson.containsKey("pluginList")) {
                      for (Object obj : execJson.getJSONArray("pluginList")) {
                          PluginLayout pluginLayout = new PluginLayout();
                          JSONObject jobj = (JSONObject)obj;
                          pluginLayout.setPluginName(jobj.containsKey(PLUGIN_NAME_KEY)? (String)jobj.get(PLUGIN_NAME_KEY) :"");
                          pluginLayout.setDisplayName(jobj.containsKey(DISPLAY_NAME_KEY)? (String)jobj.get(DISPLAY_NAME_KEY) :"");
                          pluginLayout.setPluginType(jobj.containsKey(PLUGIN_TYPE_KEY)? (String)jobj.get(PLUGIN_TYPE_KEY) :"");
                          pluginLayoutList.add(pluginLayout);
                      }
                  }
              }
          }
  
          return pluginLayoutList;
      }
  
      public RunData getRunData() {
          return runData;
      }
  
      
      /**
       * 插件功能:/整合当前阶段所有的log,以map的格式返回,传递给testRespone
       * @param logCollection
       * @return
       */
      public HashMap<StageName,ListHashMap<String, String>> mergeResponeLog(List<LogInfo> logCollection){
  
          StageName stageName;
          String pluginName;
          String log;
          HashMap<StageName,ListHashMap<String, String>> allLogCollection = new HashMap<>();
          ListHashMap<String, String> logList;
          String key;
  
          if (logCollection.size() > 0){
  
              for (LogInfo logInfo : logCollection){
  
                  stageName = logInfo.getStageName();
  
                  if (!allLogCollection.containsKey(stageName)){
                      logList = new ListHashMap<>();
                      allLogCollection.put(stageName,logList );
                  }
                  else {
                      logList = allLogCollection.get(stageName);
                  }
  
                  pluginName = logInfo.getPluginName();
  
                  key = pluginName;
                  log = logInfo.getLog();
                  logList.put(key,log);
  
              }
          }
  
          return allLogCollection;
      }
  }
  
  
  