public Map<String, Parameter> generateMergedWorkflowParams(
      WorkflowInstance instance, RunRequest request) {
    Workflow workflow = instance.getRuntimeWorkflow();
    Map<String, ParamDefinition> allParamDefs = new LinkedHashMap<>();
    Map<String, ParamDefinition> defaultWorkflowParams =
        defaultParamManager.getDefaultWorkflowParams();

    // merge workflow params for start
    if (request.isFreshRun()) {
      // merge default workflow params
      ParamsMergeHelper.mergeParams(
          allParamDefs,
          defaultWorkflowParams,
          ParamsMergeHelper.MergeContext.workflowCreate(ParamSource.SYSTEM_DEFAULT, request));

      // merge defined workflow params
      if (workflow.getParams() != null) {
        ParamsMergeHelper.mergeParams(
            allParamDefs,
            workflow.getParams(),
            ParamsMergeHelper.MergeContext.workflowCreate(ParamSource.DEFINITION, request));
      }
    }

    // merge workflow params from previous instance for restart
    if (!request.isFreshRun() && instance.getParams() != null) {
      Map<String, ParamDefinition> previousParamDefs =
          instance.getParams().entrySet().stream()
              .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().toDefinition()));

      // remove reserved params, which should be injected again by the system.
      for (String paramName : Constants.RESERVED_PARAM_NAMES) {
        previousParamDefs.remove(paramName);
      }

      ParamsMergeHelper.mergeParams(
          allParamDefs,
          previousParamDefs,
          ParamsMergeHelper.MergeContext.workflowCreate(ParamSource.SYSTEM, false));
    }

    // merge run params
    if (request.getRunParams() != null) {
      ParamSource source = getParamSource(request.getInitiator(), request.isFreshRun());
      ParamsMergeHelper.mergeParams(
          allParamDefs,
          request.getRunParams(),
          ParamsMergeHelper.MergeContext.workflowCreate(source, request));
    }

    // merge user provided restart run params
    getUserRestartParam(request)
        .ifPresent(
            userRestartParams -> {
              ParamSource source = getParamSource(request.getInitiator(), request.isFreshRun());
              ParamsMergeHelper.mergeParams(
                  allParamDefs,
                  userRestartParams,
                  ParamsMergeHelper.MergeContext.workflowCreate(source, request));
            });

    // cleanup any placeholder params and convert to params
    return ParamsMergeHelper.convertToParameters(ParamsMergeHelper.cleanupParams(allParamDefs));
  }
@Test
  public void testSubRestartConfigRunChangedParamMerge() {
    Map<String, Object> meta =
        Collections.singletonMap(Constants.METADATA_SOURCE_KEY, "SUBWORKFLOW");
    LongParameter param =
        LongParameter.builder()
            .name("TARGET_RUN_DATE")
            .value(1000L)
            .evaluatedResult(1000L)
            .evaluatedTime(123L)
            .mode(ParamMode.MUTABLE_ON_START_RESTART)
            .meta(meta)
            .build();
    Map<String, Object> restartMeta =
        Collections.singletonMap(Constants.METADATA_SOURCE_KEY, "DEFINITION");
    Map<String, ParamDefinition> restartParams =
        singletonMap(
            "TARGET_RUN_DATE",
            param.toDefinition().asLongParamDef().toBuilder()
                .value(1001L)
                .mode(ParamMode.MUTABLE)
                .meta(restartMeta)
                .build());
    RunRequest request =
        RunRequest.builder()
            .initiator(new SubworkflowInitiator())
            .currentPolicy(RunPolicy.RESTART_FROM_SPECIFIC)
            .runParams(restartParams)
            .restartConfig(
                RestartConfig.builder().addRestartNode("sample-wf-map-params", 1, "foo").build())
            .build();
    Map<String, Parameter> instanceParams = new LinkedHashMap<>();
    instanceParams.put("TARGET_RUN_DATE", param);
    workflowInstance.setParams(instanceParams);
    Map<String, Parameter> workflowParams =
        paramsManager.generateMergedWorkflowParams(workflowInstance, request);
    Assert.assertFalse(workflowParams.isEmpty());
    Assert.assertEquals(
        Long.valueOf(1001L), workflowParams.get("TARGET_RUN_DATE").asLongParam().getValue());
    Assert.assertEquals(ParamSource.SUBWORKFLOW, workflowParams.get("TARGET_RUN_DATE").getSource());
    Assert.assertEquals(
        ParamMode.MUTABLE_ON_START_RESTART, workflowParams.get("TARGET_RUN_DATE").getMode());
  }