@JsonIgnore
  public long initiateAndGetByPrevMaxIterationId(ForeachStepOverview prev, long toReset) {
    if (prev == null || prev.details == null) {
      return 0;
    }

    long maxIterationId =
        prev.details.flatten(e -> true).values().stream()
            .flatMap(Collection::stream)
            .reduce(0L, Long::max);

    // We need to keep only succeeded instances as we will restart the remaining instances when
    // restarting all iterations from incomplete. When there is specific iteration to restart
    // we keep all terminal state instances.
    Map<WorkflowInstance.Status, List<Long>> toKeep =
        prev.details.flatten(
            toReset == 0
                ? (e -> e == WorkflowInstance.Status.SUCCEEDED)
                : (WorkflowInstance.Status::isTerminal));

    // checkpoint can be set to the first restartable instance id - 1
    List<Long> instanceIds =
        toKeep.values().stream().flatMap(Collection::stream).sorted().collect(Collectors.toList());
    checkpoint = instanceIds.size();
    for (int i = 0; i < instanceIds.size(); ++i) {
      if (instanceIds.get(i) != i + 1) {
        checkpoint = i;
        break;
      }
    }

    toKeep.forEach((status, ids) -> ids.forEach(i -> addOne(i, status, null)));
    refreshDetail();

    return maxIterationId;
  }
@Test
  public void testInitiateAndGetByPrevMaxIterationId() throws Exception {
    ForeachStepOverview prev =
        loadObject(
            "fixtures/instances/sample-foreach-step-overview-with-failed.json",
            ForeachStepOverview.class);
    ForeachStepOverview overview = new ForeachStepOverview();
    assertEquals(80121, overview.initiateAndGetByPrevMaxIterationId(prev, 0));
    assertEquals(
        Collections.singletonMap(
            WorkflowInstance.Status.SUCCEEDED,
            Arrays.asList(80110L, 80112L, 80113L, 80114L, 80115L)),
        overview.getDetails().flatten(e -> true));
    assertEquals(0, overview.getCheckpoint());

    overview = new ForeachStepOverview();
    assertEquals(80121, overview.initiateAndGetByPrevMaxIterationId(prev, 80115));
    Map<WorkflowInstance.Status, List<Long>> detailsMap = new HashMap<>();
    detailsMap.put(
        WorkflowInstance.Status.SUCCEEDED, Arrays.asList(80110L, 80112L, 80113L, 80114L, 80115L));
    detailsMap.put(WorkflowInstance.Status.FAILED, Arrays.asList(80117L, 80119L, 80120L, 80121L));
    assertEquals(detailsMap, overview.getDetails().flatten(e -> true));
    assertEquals(0, overview.getCheckpoint());

    overview = new ForeachStepOverview();
    assertEquals(0, overview.initiateAndGetByPrevMaxIterationId(null, 80115));
    assertEquals(0, overview.getCheckpoint());

    overview = new ForeachStepOverview();
    prev.getDetails().add(1, WorkflowInstance.Status.SUCCEEDED);
    prev.getDetails().add(2, WorkflowInstance.Status.STOPPED);
    prev.refreshDetail();
    assertEquals(80121, overview.initiateAndGetByPrevMaxIterationId(prev, 80115));
    assertEquals(2, overview.getCheckpoint());

    overview = new ForeachStepOverview();
    prev.getDetails().getInfo().clear();
    prev.getDetails()
        .getInfo()
        .put(
            WorkflowInstance.Status.STOPPED,
            Collections.singletonList(new ForeachDetails.Interval(1, 10000)));
    assertEquals(10000, overview.initiateAndGetByPrevMaxIterationId(prev, 80115));
    assertEquals(10000, overview.getCheckpoint());

    overview = new ForeachStepOverview();
    prev.getDetails().getInfo().clear();
    assertEquals(0, overview.initiateAndGetByPrevMaxIterationId(prev, 80115));
    assertEquals(0, overview.getCheckpoint());

    overview = new ForeachStepOverview();
    prev.getDetails()
        .getInfo()
        .put(
            WorkflowInstance.Status.SUCCEEDED,
            Collections.singletonList(new ForeachDetails.Interval(1, 10000)));
    assertEquals(10000, overview.initiateAndGetByPrevMaxIterationId(prev, 80115));
    assertEquals(10000, overview.getCheckpoint());

    overview = new ForeachStepOverview();
    prev.getDetails().getInfo().clear();
    prev.getDetails().add(1, WorkflowInstance.Status.SUCCEEDED);
    prev.getDetails().add(2, WorkflowInstance.Status.STOPPED);
    prev.getDetails().add(3, WorkflowInstance.Status.SUCCEEDED);
    prev.refreshDetail();
    assertEquals(3, overview.initiateAndGetByPrevMaxIterationId(prev, 80115));
    assertEquals(3, overview.getCheckpoint());

    overview = new ForeachStepOverview();
    prev.getDetails().getInfo().clear();
    prev.getDetails().add(1, WorkflowInstance.Status.SUCCEEDED);
    prev.getDetails().add(2, WorkflowInstance.Status.STOPPED);
    prev.refreshDetail();
    assertEquals(2, overview.initiateAndGetByPrevMaxIterationId(prev, 80115));
    assertEquals(2, overview.getCheckpoint());
  }