/**
  * Returns the configuration history entries for one {@link Slave}.
  *
  * @return history list for one {@link Slave}.
  * @throws IOException if {@link JobConfigHistoryConsts#HISTORY_FILE} might not be read or the
  *     path might not be urlencoded.
  */
 public final List<ConfigInfo> getSlaveConfigs() throws IOException {
   checkConfigurePermission();
   final ArrayList<ConfigInfo> configs = new ArrayList<ConfigInfo>();
   final ArrayList<HistoryDescr> values =
       new ArrayList<HistoryDescr>(getHistoryDao().getRevisions(slave).values());
   for (final HistoryDescr historyDescr : values) {
     final String timestamp = historyDescr.getTimestamp();
     final XmlFile oldRevision = getHistoryDao().getOldRevision(slave, timestamp);
     if (oldRevision.getFile() != null) {
       configs.add(ConfigInfo.create(slave.getNodeName(), true, historyDescr, true));
     } else if ("Deleted".equals(historyDescr.getOperation())) {
       configs.add(ConfigInfo.create(slave.getNodeName(), false, historyDescr, true));
     }
   }
   Collections.sort(configs, ParsedDateComparator.DESCENDING);
   return configs;
 }
 /**
  * Gets config history entries for the view options 'created', 'deleted' and 'jobs'. While 'jobs'
  * displays all available job config history entries, 'deleted' and 'created' only show the last
  * or the first one respectively.
  *
  * @param itemDir The job directory as File
  * @param folderName Something Jesse Glick came up with but never documented, probably the
  *     folderName.
  * @throws IOException If one of the entries cannot be read.
  */
 void getConfigsForType(File itemDir, String folderName) throws IOException {
   final String itemName =
       folderName.isEmpty() ? itemDir.getName() : folderName + "/" + itemDir.getName();
   final List<HistoryDescr> historyEntries =
       new ArrayList<HistoryDescr>(overViewhistoryDao.getJobHistory(itemName).values());
   if (historyEntries.isEmpty()) {
     return;
   }
   final boolean isADeletedJob = DeletedFileFilter.accepts(itemName);
   final boolean isNotADeletedJob = !isADeletedJob;
   if ("created".equals(type)) {
     if (isADeletedJob) {
       return;
     }
     HistoryDescr histDescr = historyEntries.get(0);
     if ("Created".equals(histDescr.getOperation())) {
       final ConfigInfo config = ConfigInfo.create(itemName, true, histDescr, true);
       configs.add(config);
     } else {
       // Why would the created entry not be the first one? Answer:
       // There's always a 'Changed' entry before the 'Created' entry,
       // because in the Jenkins core, when creating a new job,
       // the SaveableListener (which handles changes) fires
       // before the ItemListener (which handles creation, deletion etc.)
       // Older versions of the plugin didn't show this behaviour
       // since it was masked by some race condition.
       histDescr = historyEntries.get(1);
       if ("Created".equals(histDescr.getOperation())) {
         final ConfigInfo config = ConfigInfo.create(itemName, true, histDescr, true);
         configs.add(config);
       }
     }
   } else if ("deleted".equals(type)) {
     final HistoryDescr histDescr = historyEntries.get(historyEntries.size() - 1);
     if ("Deleted".equals(histDescr.getOperation())) {
       final ConfigInfo config = ConfigInfo.create(itemName, false, histDescr, false);
       configs.add(config);
     }
   } else {
     configs.addAll(
         HistoryDescrToConfigInfo.convert(itemName, true, historyEntries, isNotADeletedJob));
   }
 }