@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
  @VisibleForTesting
  static List<WorkflowRollupOverview> getRollupsForStepsFromPreviousRuns(
      String workflowId,
      Long workflowInstanceId,
      WorkflowInstanceAggregatedInfo aggregatedInfo,
      Map<String, StepTransition> runtimeDag,
      Set<String> foreachAndSubworkflowStepIds) {

    List<WorkflowRollupOverview> rollupOverviews = new ArrayList<>();

    Set<Map.Entry<String, StepAggregatedView>> aggregatedStepsInfo =
        aggregatedInfo.getStepAggregatedViews().entrySet();
    for (Map.Entry<String, StepAggregatedView> entry : aggregatedStepsInfo) {
      String stepId = entry.getKey();

      if (runtimeDag.containsKey(stepId)
          || (foreachAndSubworkflowStepIds != null
              && foreachAndSubworkflowStepIds.contains(stepId))) {
        // we want to reset any steps that would've been restarted, so we don't want to add those
        // we also want to skip foreach and subworkflow steps from aggregated view because
        // we calculate rollups for those separately
        continue;
      }

      StepInstance.Status status = entry.getValue().getStatus();

      WorkflowRollupOverview.CountReference ref = new WorkflowRollupOverview.CountReference();
      ref.setCnt(1);
      if (status.isOverview()) {
        ref.setRef(
            Collections.singletonMap(
                getReference(workflowId, entry.getValue().getWorkflowRunId()),
                Collections.singletonList(getReference(workflowInstanceId, stepId, 0L))));
      }

      rollupOverviews.add(WorkflowRollupOverview.of(1L, Collections.singletonMap(status, ref)));
    }

    return rollupOverviews;
  }
@Test
  public void testGetRollupsForStepsFromPreviousRuns() {
    Map<String, StepAggregatedView> stepMap = new HashMap<>();
    stepMap.put(
        "step1",
        StepAggregatedView.builder()
            .status(StepInstance.Status.SUCCEEDED)
            .workflowRunId(1L)
            .build());
    stepMap.put(
        "step2",
        StepAggregatedView.builder()
            .status(StepInstance.Status.FATALLY_FAILED)
            .workflowRunId(1L)
            .build());
    WorkflowInstanceAggregatedInfo aggregatedInfo = new WorkflowInstanceAggregatedInfo();
    aggregatedInfo.setStepAggregatedViews(stepMap);

    Map<String, StepTransition> runtimeDag = new LinkedHashMap<>();
    runtimeDag.put("step3", new StepTransition());
    runtimeDag.put("step4", new StepTransition());
    runtimeDag.put("step5", new StepTransition());

    Set<String> foreachAndSubworkflowStepIds = new HashSet<>(Collections.singletonList("step4"));

    List<WorkflowRollupOverview> rollups =
        RollupAggregationHelper.getRollupsForStepsFromPreviousRuns(
            "workflow_id", 1L, aggregatedInfo, runtimeDag, foreachAndSubworkflowStepIds);

    assertEquals(2, rollups.size());

    assertNotNull(rollups.get(0).getOverview().get(StepInstance.Status.FATALLY_FAILED));
    assertNotNull(rollups.get(1).getOverview().get(StepInstance.Status.SUCCEEDED));

    // empty aggregated info steps
    rollups =
        RollupAggregationHelper.getRollupsForStepsFromPreviousRuns(
            "workflow_id",
            1L,
            new WorkflowInstanceAggregatedInfo(),
            runtimeDag,
            foreachAndSubworkflowStepIds);

    assertEquals(0, rollups.size());

    // empty foreach and subworkflow steps list
    rollups =
        RollupAggregationHelper.getRollupsForStepsFromPreviousRuns(
            "workflow_id", 1L, aggregatedInfo, runtimeDag, new HashSet<>());

    assertEquals(2, rollups.size());

    // empty runtimeDAG
    rollups =
        RollupAggregationHelper.getRollupsForStepsFromPreviousRuns(
            "workflow_id", 1L, aggregatedInfo, new HashMap<>(), foreachAndSubworkflowStepIds);

    assertEquals(2, rollups.size());

    // scenario where some skipped because in runtimeDag, and some because of foreach or subworkflow
    stepMap.put(
        "step3",
        StepAggregatedView.builder()
            .status(StepInstance.Status.SUCCEEDED)
            .workflowRunId(1L)
            .build());
    stepMap.put(
        "step4",
        StepAggregatedView.builder()
            .status(StepInstance.Status.SUCCEEDED)
            .workflowRunId(1L)
            .build());
    stepMap.put(
        "step5",
        StepAggregatedView.builder()
            .status(StepInstance.Status.SUCCEEDED)
            .workflowRunId(1L)
            .build());
    stepMap.put(
        "step6",
        StepAggregatedView.builder()
            .status(StepInstance.Status.SUCCEEDED)
            .workflowRunId(1L)
            .build());
    stepMap.put(
        "step7",
        StepAggregatedView.builder().status(StepInstance.Status.STOPPED).workflowRunId(1L).build());

    foreachAndSubworkflowStepIds.add("step6");

    rollups =
        RollupAggregationHelper.getRollupsForStepsFromPreviousRuns(
            "workflow_id", 1L, aggregatedInfo, runtimeDag, foreachAndSubworkflowStepIds);

    assertEquals(3, rollups.size());
    assertNotNull(rollups.get(0).getOverview().get(StepInstance.Status.STOPPED));
  }