public static void mergeOutputDataParams(
      Map<String, Parameter> allParams, Map<String, Parameter> params) {
    params.forEach(
        (name, param) -> {
          if (!allParams.containsKey(name)) {
            throw new MaestroValidationException(
                "Invalid output parameter [%s], not defined in params", name);
          }
          MergeContext context = MergeContext.stepCreate(ParamSource.OUTPUT_PARAMETER);
          if (param.getType() == ParamType.MAP && param.isLiteral()) {
            ParamDefinition baseDef = allParams.get(name).toDefinition();
            Map<String, ParamDefinition> baseMap = baseDef.asMapParamDef().getValue();
            ParamDefinition toMergeDef = param.toDefinition();
            Map<String, ParamDefinition> toMergeMap = toMergeDef.asMapParamDef().getValue();

            mergeParams(baseMap, toMergeMap, context);
            Parameter mergedParam =
                buildMergedParamDefinition(name, toMergeDef, baseDef, context, baseMap)
                    .toParameter();
            populateEvaluatedResultAndTime(mergedParam, param.getEvaluatedTime());
            allParams.put(name, mergedParam);
          } else if (param.getType() == ParamType.STRING_MAP && param.isLiteral()) {
            ParamDefinition baseDef = allParams.get(name).toDefinition();
            Map<String, String> baseMap = baseDef.asStringMapParamDef().getValue();
            ParamDefinition toMergeDef = param.toDefinition();
            Map<String, String> toMergeMap = toMergeDef.asStringMapParamDef().getValue();

            baseMap.putAll(toMergeMap);
            Parameter mergedParam =
                buildMergedParamDefinition(name, toMergeDef, baseDef, context, baseMap)
                    .toParameter();
            populateEvaluatedResultAndTime(mergedParam, param.getEvaluatedTime());
            allParams.put(name, mergedParam);
          } else {
            ParamDefinition paramDefinition =
                ParamsMergeHelper.buildMergedParamDefinition(
                    name,
                    param.toDefinition(),
                    allParams.get(name).toDefinition(),
                    MergeContext.stepCreate(ParamSource.OUTPUT_PARAMETER),
                    param.getValue());
            Parameter parameter = paramDefinition.toParameter();
            parameter.setEvaluatedResult(param.getEvaluatedResult());
            parameter.setEvaluatedTime(param.getEvaluatedTime());
            allParams.put(name, parameter);
          }
        });
  }
@Test
  public void testMergeOutputDataParamsStringMapParam() throws JsonProcessingException {
    Map<String, Parameter> allParams =
        parseParamMap(
            "{\"string_map_param\":{\"evaluated_result\":{\"a\":\"b\",\"b\":\"d\"},"
                + "\"evaluated_time\":1626893775979,\"type\":\"STRING_MAP\",\"value\":{\"a\":\"b\",\"b\":\"d\"}}}");
    Map<String, Parameter> paramsToMerge =
        parseParamMap(
            "{\"string_map_param\":{\"evaluated_result\":{\"c\":\"e\",\"d\":\"f\"},\"evaluated_time\":1626893775979,\"type\":\"STRING_MAP\",\"value\":{\"c\":\"e\",\"d\":\"f\"}}}");
    ParamsMergeHelper.mergeOutputDataParams(allParams, paramsToMerge);
    Map<String, String> mergedStringMap = allParams.get("string_map_param").getValue();
    Map<String, String> mergedEvaluated = allParams.get("string_map_param").getEvaluatedResult();
    assertEquals(4, mergedStringMap.size());
    for (String key : new String[] {"a", "b", "c", "d"}) {
      assertTrue(mergedStringMap.containsKey(key));
      assertTrue(mergedEvaluated.containsKey(key));
    }
  }