private List<ValidationStamp> readValidationStamps(JsonNode validationStampIds) {
   List<ValidationStamp> validationStampList;
   if (validationStampIds.isArray()) {
     List<Integer> ids = new ArrayList<>();
     validationStampIds.forEach(id -> ids.add(id.asInt()));
     // Reading the validation stamps and then the names
     validationStampList =
         ids.stream()
             .map(id -> structureService.getValidationStamp(ID.of(id)))
             .collect(Collectors.toList());
   } else {
     throw new AutoPromotionPropertyCannotParseException(
         "Cannot get the list of validation stamps");
   }
   return validationStampList;
 }
  @Override
  public OntrackSVNIssueInfo getIssueInfo(String configurationName, String issueKey) {
    // Repository
    SVNRepository repository = svnService.getRepository(configurationName);
    // Issue service
    ConfiguredIssueService configuredIssueService = repository.getConfiguredIssueService();
    if (configuredIssueService == null) {
      // No issue service configured
      return OntrackSVNIssueInfo.empty(repository.getConfiguration());
    }
    // Gets the details about the issue
    Issue issue = configuredIssueService.getIssue(issueKey);

    // For each configured branch
    Map<String, BranchRevision> branchRevisions = new HashMap<>();
    svnService.forEachConfiguredBranch(
        config -> Objects.equals(configurationName, config.getConfiguration().getName()),
        (branch, branchConfig) -> {
          String branchPath = branchConfig.getCuredBranchPath();
          // List of linked issues
          Collection<String> linkedIssues =
              configuredIssueService
                  .getLinkedIssues(branch.getProject(), issue)
                  .stream()
                  .map(Issue::getKey)
                  .collect(Collectors.toList());
          // Gets the last raw revision on this branch
          issueRevisionDao
              .findLastRevisionByIssuesAndBranch(repository.getId(), linkedIssues, branchPath)
              .ifPresent(
                  revision ->
                      branchRevisions.put(
                          branchPath, new BranchRevision(branchPath, revision, false)));
        });

    // Until all revisions are complete in respect of their merges...
    while (!BranchRevision.areComplete(branchRevisions.values())) {
      // Gets the incomplete revisions
      Collection<BranchRevision> incompleteRevisions =
          branchRevisions
              .values()
              .stream()
              .filter(br -> !br.isComplete())
              .collect(Collectors.toList());
      // For each of them, gets the list of revisions it was merged to
      incompleteRevisions.forEach(
          br -> {
            List<Long> merges =
                revisionDao.getMergesForRevision(repository.getId(), br.getRevision());
            // Marks the current revision as complete
            branchRevisions.put(br.getPath(), br.complete());
            // Gets the revision info for each merged revision
            List<TRevision> revisions =
                merges
                    .stream()
                    .map(r -> revisionDao.get(repository.getId(), r))
                    .collect(Collectors.toList());
            // For each revision path, compares with current stored revision
            revisions.forEach(
                t -> {
                  String branch = t.getBranch();
                  // Existing branch revision?
                  BranchRevision existingBranchRevision = branchRevisions.get(branch);
                  if (existingBranchRevision == null
                      || t.getRevision() > existingBranchRevision.getRevision()) {
                    branchRevisions.put(branch, new BranchRevision(branch, t.getRevision(), true));
                  }
                });
          });
    }

    // We now have the last revision for this issue on each branch...
    List<OntrackSVNIssueRevisionInfo> issueRevisionInfos = new ArrayList<>();
    branchRevisions
        .values()
        .forEach(
            br -> {
              // Loads the revision info
              SVNRevisionInfo basicInfo = svnService.getRevisionInfo(repository, br.getRevision());
              SVNChangeLogRevision changeLogRevision =
                  svnService.createChangeLogRevision(repository, basicInfo);
              // Info to collect
              OntrackSVNIssueRevisionInfo issueRevisionInfo =
                  OntrackSVNIssueRevisionInfo.of(changeLogRevision);
              // Gets the branch from the branch path
              AtomicReference<Branch> rBranch = new AtomicReference<>();
              svnService.forEachConfiguredBranch(
                  config -> Objects.equals(configurationName, config.getConfiguration().getName()),
                  (candidate, branchConfig) -> {
                    String branchPath = branchConfig.getCuredBranchPath();
                    if (Objects.equals(br.getPath(), branchPath)) {
                      rBranch.set(candidate);
                    }
                  });
              Branch branch = rBranch.get();
              if (branch != null) {
                // Collects branch info
                SCMIssueCommitBranchInfo branchInfo = SCMIssueCommitBranchInfo.of(branch);
                // Gets the first copy event on this path after this revision
                SVNLocation firstCopy =
                    svnService.getFirstCopyAfter(repository, basicInfo.toLocation());
                // Identifies a possible build given the path/revision and the first copy
                Optional<Build> buildAfterCommit =
                    lookupBuild(basicInfo.toLocation(), firstCopy, branch);
                if (buildAfterCommit.isPresent()) {
                  Build build = buildAfterCommit.get();
                  // Gets the build view
                  BuildView buildView = structureService.getBuildView(build);
                  // Adds it to the list
                  branchInfo = branchInfo.withBuildView(buildView);
                  // Collects the promotions for the branch
                  branchInfo =
                      branchInfo.withBranchStatusView(
                          structureService.getEarliestPromotionsAfterBuild(build));
                }
                // OK
                issueRevisionInfo.add(branchInfo);
              }
              // OK
              issueRevisionInfos.add(issueRevisionInfo);
            });

    // Gets the list of revisions & their basic info (order from latest to oldest)
    List<SVNChangeLogRevision> revisions =
        svnService
            .getRevisionsForIssueKey(repository, issueKey)
            .stream()
            .map(
                revision ->
                    svnService.createChangeLogRevision(
                        repository, svnService.getRevisionInfo(repository, revision)))
            .collect(Collectors.toList());

    // OK
    return new OntrackSVNIssueInfo(
        repository.getConfiguration(),
        repository.getConfiguredIssueService().getIssueServiceConfigurationRepresentation(),
        issue,
        issueRevisionInfos,
        revisions);
  }