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 testCalculateTimezonesWithTriggersAndTimeInitiator() throws IOException {
    WorkflowDefinition definition =
        loadObject(
            "fixtures/parameters/sample-wf-with-time-triggers.json", WorkflowDefinition.class);
    workflow = definition.getWorkflow();
    workflowInstance.setRuntimeWorkflow(workflow);
    paramsManager = new ParamsManager(defaultsManager);
    Step step = Mockito.mock(Step.class);
    when(step.getType()).thenReturn(StepType.TITUS);
    RunProperties runProperties = new RunProperties();
    runProperties.setOwner(User.builder().name("demo").build());
    workflowInstance.setRunProperties(runProperties);
    TimeInitiator initiator = new TimeInitiator();
    initiator.setTimezone("Asia/Tokyo");
    RunRequest request =
        RunRequest.builder()
            .initiator(initiator)
            .currentPolicy(RunPolicy.START_FRESH_NEW_RUN)
            .build();
    Map<String, Parameter> workflowParams =
        paramsManager.generateMergedWorkflowParams(workflowInstance, request);

    paramExtensionRepo.reset(
        Collections.emptyMap(),
        Collections.emptyMap(),
        InstanceWrapper.from(workflowInstance, request));
    paramEvaluator.evaluateWorkflowParameters(workflowParams, workflow.getId());
    paramExtensionRepo.clear();

    // if triggers and initiator both, use first trigger timezone for default tz, and initiator for
    // the workflow tz
    Assert.assertEquals("Asia/Tokyo", workflowParams.get("WORKFLOW_CRON_TIMEZONE").asString());
    Assert.assertEquals("US/Pacific", workflowParams.get("DSL_DEFAULT_TZ").asString());
    Assert.assertEquals("demo", workflowParams.get("owner").asString());
  }