public Map<String, ParamDefinition> generateStaticStepParamDefs(
      WorkflowSummary workflowSummary, Step stepDefinition, StepRuntime stepRuntime) {
    Map<String, ParamDefinition> allParamDefs = new LinkedHashMap<>();

    // Start with default step level params if present
    Map<String, ParamDefinition> globalDefault = defaultParamManager.getDefaultStepParams();

    if (globalDefault != null) {
      ParamsMergeHelper.mergeParams(
          allParamDefs,
          globalDefault,
          ParamsMergeHelper.MergeContext.stepCreate(ParamSource.SYSTEM_DEFAULT));
    }
    // Merge in injected params returned by step if present (template schema)
    Map<String, ParamDefinition> injectedParams =
        stepRuntime.injectRuntimeParams(workflowSummary, stepDefinition);
    if (injectedParams != null) {
      maybeOverrideParamType(injectedParams);
      ParamsMergeHelper.mergeParams(
          allParamDefs,
          injectedParams,
          ParamsMergeHelper.MergeContext.stepCreate(ParamSource.TEMPLATE_SCHEMA));
    }
    // Merge in params applicable to step type
    Optional<Map<String, ParamDefinition>> defaultStepTypeParams =
        defaultParamManager.getDefaultParamsForType(stepDefinition.getType());
    defaultStepTypeParams.ifPresent(
        stepTypeParams ->
            ParamsMergeHelper.mergeParams(
                allParamDefs,
                stepTypeParams,
                ParamsMergeHelper.MergeContext.stepCreate(ParamSource.SYSTEM_DEFAULT)));

    // Final merge from step definition
    if (stepDefinition.getParams() != null) {
      maybeOverrideParamType(stepDefinition.getParams());
      ParamsMergeHelper.mergeParams(
          allParamDefs,
          stepDefinition.getParams(),
          ParamsMergeHelper.MergeContext.stepCreate(ParamSource.DEFINITION));
    }
    return allParamDefs;
  }
@Test
  public void testStaticStepParamMerge() {
    Map<String, ParamDefinition> stepParams = new LinkedHashMap<>();
    when(defaultParamManager.getDefaultStepParams())
        .thenReturn(singletonMap("p1", ParamDefinition.buildParamDefinition("p1", "d1")));
    when(stepRuntime.injectRuntimeParams(any(), any()))
        .thenReturn(singletonMap("p2", ParamDefinition.buildParamDefinition("p2", "d2")));
    when(defaultParamManager.getDefaultParamsForType(any()))
        .thenReturn(
            Optional.of(singletonMap("p3", ParamDefinition.buildParamDefinition("p3", "d3"))));
    ((TypedStep) step).setParams(stepParams);
    stepParams.put("p4", ParamDefinition.buildParamDefinition("p4", "d4"));
    Map<String, ParamDefinition> mergedStepParamDefs =
        paramsManager.generateStaticStepParamDefs(workflowSummary, step, stepRuntime);

    Assert.assertEquals("d1", mergedStepParamDefs.get("p1").asStringParamDef().getValue());
    Assert.assertEquals("d2", mergedStepParamDefs.get("p2").asStringParamDef().getValue());
    Assert.assertEquals("d3", mergedStepParamDefs.get("p3").asStringParamDef().getValue());
    Assert.assertEquals("d4", mergedStepParamDefs.get("p4").asStringParamDef().getValue());
  }