package com.metservice.kanban.csv; import static org.apache.commons.io.FileUtils.copyFile; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.Reader; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.regex.Pattern; import com.metservice.kanban.model.WorkItem; import com.metservice.kanban.model.WorkItemType; //TODO This class needs more unit tests. public class KanbanCsvFile { private static final int MAX_TEMPORARY_FILES = 25; private final File file; private final WorkItemType workItemType; public KanbanCsvFile(File file, WorkItemType workItemType) { this.file = file; this.workItemType = workItemType; } public WorkItemType getWorkItemType() { return workItemType; } public List<WorkItem> read() throws IOException { if (!file.exists()) { return new ArrayList<WorkItem>(); } else { return read(new FileReader(file)); } } private List<WorkItem> read(Reader reader) throws IOException { KanbanCsvReader csvReader = new KanbanCsvReader(reader, workItemType); try { List<WorkItem> workItems = csvReader.read(); csvReader.close(); return workItems; } catch (IOException e) { throw new IOException("failure reading " + file, e); } catch (RuntimeException e) { throw new RuntimeException("failure reading " + file, e); } finally { csvReader.closeQuietly(); } } public void write(List<WorkItem> workItems) throws IOException { File temporaryFile = new File(file.getAbsolutePath() + "." + System.currentTimeMillis() + ".temp"); KanbanCsvWriter workItemWriter = new KanbanCsvWriter(new FileWriter(temporaryFile), workItemType); try { workItemWriter.write(workItems); workItemWriter.close(); } catch (IOException e) { throw new IOException("failure writing " + file, e); } catch (RuntimeException e) { throw new RuntimeException("failure writing " + file, e); } finally { workItemWriter.closeQuietly(); } file.delete(); copyFile(temporaryFile, file); cleanUpTemproaryFiles(); } /** * Keep the newest {@link #MAX_TEMPORARY_FILES} ( * {@value #MAX_TEMPORARY_FILES}) temporary files and delete the rest. */ public void cleanUpTemproaryFiles() { File directory = file.getParentFile(); List<String> files = Arrays.asList(directory.list()); Collections.sort(files); Collections.reverse(files); Pattern tempFilePattern = Pattern.compile(file.getName() + "\\.\\d+\\.temp"); int tempFilesFound = 0; File fileToClean; for (String aFile : files) { fileToClean = new File(directory.getAbsolutePath() + File.separatorChar + aFile); if (tempFilePattern.matcher(aFile).matches()) { tempFilesFound++; if (tempFilesFound > MAX_TEMPORARY_FILES) { fileToClean.delete(); } } } } @Override public String toString() { return file.toString(); } }