private void updateGeneratedJobs(
      final AbstractBuild<?, ?> build, BuildListener listener, Set<GeneratedJob> freshJobs)
      throws IOException {
    // Update Project
    Set<GeneratedJob> generatedJobs =
        extractGeneratedObjects(build.getProject(), GeneratedJobsAction.class);
    Set<GeneratedJob> added = Sets.difference(freshJobs, generatedJobs);
    Set<GeneratedJob> existing = Sets.intersection(generatedJobs, freshJobs);
    Set<GeneratedJob> removed = Sets.difference(generatedJobs, freshJobs);

    logItems(listener, "Adding items", added);
    logItems(listener, "Existing items", existing);
    logItems(listener, "Removing items", removed);

    // Update unreferenced jobs
    for (GeneratedJob removedJob : removed) {
      Item removedItem =
          getLookupStrategy().getItem(build.getProject(), removedJob.getJobName(), Item.class);
      if (removedItem != null && removedJobAction != RemovedJobAction.IGNORE) {
        if (removedJobAction == RemovedJobAction.DELETE) {
          try {
            removedItem.delete();
          } catch (InterruptedException e) {
            listener.getLogger().println(String.format("Delete item failed: %s", removedJob));
            if (removedItem instanceof AbstractProject) {
              listener.getLogger().println(String.format("Disabling item instead: %s", removedJob));
              ((AbstractProject) removedItem).disable();
            }
          }
        } else {
          if (removedItem instanceof AbstractProject) {
            ((AbstractProject) removedItem).disable();
          }
        }
      }
    }

    updateGeneratedJobMap(build.getProject(), Sets.union(added, existing), removed);
  }