class LinkageMonitor {

  @VisibleForTesting
  static String messageForNewErrors(
      Set<LinkageProblem> snapshotProblems,
      Set<LinkageProblem> baselineProblems,
      ClassPathResult classPathResult) {
    Set<LinkageProblem> newProblems = Sets.difference(snapshotProblems, baselineProblems);
    Builder<ClassPathEntry> problematicJars = ImmutableSet.builder();

    ImmutableListMultimap<String, LinkageProblem> groupedBySymbolProblem =
        Multimaps.index(newProblems, problem -> problem.formatSymbolProblem());
    StringBuilder message =
        new StringBuilder(
            "Newly introduced problem"
                + (groupedBySymbolProblem.keySet().size() > 1 ? "s" : "")
                + ":\n");
    for (String problem : groupedBySymbolProblem.keySet()) {
      message.append(problem + "\n");

      for (LinkageProblem linkageProblem : groupedBySymbolProblem.get(problem)) {
        // This is null for ClassNotFound error.
        if (linkageProblem.getTargetClass() != null) {
          problematicJars.add(linkageProblem.getTargetClass().getClassPathEntry());
        }

        ClassFile sourceClass = linkageProblem.getSourceClass();
        message.append(
            String.format(
                "  referenced from %s (%s)\n",
                sourceClass.getBinaryName(), sourceClass.getClassPathEntry()));
        problematicJars.add(sourceClass.getClassPathEntry());
      }
    }

    message.append("\n");
    message.append(classPathResult.formatDependencyPaths(problematicJars.build()));

    return message.toString();
  }

}