import java.io.File;
import java.io.FilenameFilter;
-public class BackupFileFilter implements FilenameFilter
+public class BackupFilenameFilter implements FilenameFilter
{
public String base;
public String extension;
- public BackupFileFilter(String base, String template, int digits,
+ public BackupFilenameFilter(String base, String template, int digits,
String extension)
{
this.base = base;
@Override
public boolean accept(File file, String filename)
{
+ // CHECK THIS IS NOT ALWAYS THE PARENT DIR
if (file.isDirectory())
{
return true;
}
else
{
- int numcharstart = template.indexOf(BackupFiles.NUM_PLACEHOLDER);
- String templateStart = template;
- String templateEnd = "";
- if (numcharstart > -1)
- {
- templateStart = template.substring(0, numcharstart);
- templateEnd = template.substring(numcharstart + BackupFiles.NUM_PLACEHOLDER.length());
- }
- int startLength = base.length() + templateStart.length();
- int endLength = templateEnd.length() + extension.length();
- if (filename.length() == startLength + digits + endLength
- && filename.startsWith(base + templateStart)
- && filename.endsWith(templateEnd + extension)
- && filename
- .substring(startLength,
- filename.length() - endLength + 1)
- .matches("[0-9]+"))
- {
- return true;
- }
-
+ BackupFilenameParts bffp = new BackupFilenameParts(filename, base,
+ template, digits, extension);
+ return bffp.isBackupFile();
}
- return false;
}
}
+
+class BackupFilenameParts
+{
+ File file;
+
+ String base;
+
+ String templateStart;
+
+ int num;
+
+ int digits;
+
+ String templateEnd;
+
+ String extension;
+
+ boolean isBackupFile;
+
+ public BackupFilenameParts(File file, String base, String template, int digits,
+ String extension)
+ {
+ this(file.getName(), base, template, digits, extension);
+ }
+
+ public BackupFilenameParts(String filename, String base, String template,
+ int digits, String extension)
+ {
+ this.isBackupFile = false;
+
+ if (!(filename.startsWith(base) && filename.endsWith(extension)))
+ {
+ return;
+ }
+
+ int numcharstart = template.indexOf(BackupFiles.NUM_PLACEHOLDER);
+ String templateStart = template;
+ String templateEnd = "";
+ if (numcharstart > -1)
+ {
+ templateStart = template.substring(0, numcharstart);
+ templateEnd = template.substring(numcharstart + BackupFiles.NUM_PLACEHOLDER.length());
+ }
+ int startLength = base.length() + templateStart.length();
+ int endLength = templateEnd.length() + extension.length();
+ String numString = filename.substring(startLength, filename.length() - endLength + 1);
+
+ if (filename.length() >= startLength + digits + endLength
+ && filename.startsWith(base + templateStart)
+ && filename.endsWith(templateEnd + extension)
+ && numString.matches("[0-9]+"))
+ {
+ this.file = file;
+ this.base = base;
+ this.templateStart = templateStart;
+ this.num = Integer.parseInt(numString);
+ this.digits = digits;
+ this.templateStart = templateStart;
+ this.templateEnd = templateEnd;
+ this.isBackupFile = true;
+ }
+
+ }
+
+ public static String getBackupFilename(int index, String base,
+ String template,
+ int digits, String extension)
+ {
+ String numString = String.format("%0" + digits + "d", index);
+ String backupSuffix = template.replaceAll(BackupFiles.NUM_PLACEHOLDER,
+ numString);
+ String backupfilename = base + backupSuffix + extension;
+ return backupfilename;
+ }
+
+ public boolean isBackupFile()
+ {
+ return this.isBackupFile;
+ }
+
+ public int indexNum()
+ {
+ return this.num;
+ }
+}
\ No newline at end of file
import java.io.File;
import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.TreeMap;
+
+/*
+ * BackupFiles used for manipulating (naming rolling/deleting) backup/version files when an alignment or project file is saved.
+ * User configurable options are:
+ * BACKUPFILES_ENABLED - boolean flag as to whether to use this mechanism or act as before, including overwriting files as saved.
+ * BACKUPFILES_SUFFIX - a template to insert just before the file extension. Use '%n' to be replaced by a 0-led SUFFIX_DIGITS long integer.
+ * BACKUPFILES_ROLL_MAX - the maximum number of backupfiles to keep for any one alignment or project file.
+ * BACKUPFILES_SUFFIX_DIGITS - the number of digits to insert replace %n with (e.g. BACKUPFILES_SUFFIX_DIGITS = 3 would make "001", "002", etc)
+ * BACKUPFILES_REVERSE_ORDER - if true then "logfile" style numbering and file rolling will occur. If false then ever-increasing version numbering will occur, but old files will still be deleted if there are more than ROLL_MAX backup files.
+ */
public class BackupFiles
{
if (reverseOrder)
{
// backup style numbering
- for (int m = 0; m < max; m++)
+
+ int tempMax = max;
+ // max == -1 means no limits
+ if (max == -1)
{
- int n = max - m;
- numString = String.format("%0" + digits + "d", n);
- String backupSuffix = suffix.replaceAll(NUM_PLACEHOLDER, numString);
- String backupfilename = dir + File.separatorChar + basename
- + backupSuffix + extension;
+ // do something cleverer here (possibly)!
+ tempMax = 10000;
+ }
+
+ for (int m = 0; m < tempMax; m++)
+ {
+ int n = tempMax - m;
+ String backupfilename = dir + File.separatorChar
+ + BackupFilenameParts.getBackupFilename(n, basename, suffix,
+ digits, extension);
File backupfile_n = new File(backupfilename);
if (!backupfile_n.exists())
// reached)
// find existing backup files
- BackupFileFilter bff = new BackupFileFilter(basename, suffix, digits,
+ BackupFilenameFilter bff = new BackupFilenameFilter(basename, suffix,
+ digits,
extension);
File[] backupFiles = dirFile.listFiles(bff);
-
+ int nextIndexNum;
+ if (backupFiles.length == 0)
+ {
+ nextIndexNum = 1;
+ } else {
+
+ // and sort them (based on integer found in the suffix) using a
+ // precomputed Hashmap for speed
+ HashMap bfHashMap = new HashMap<Integer, File>();
+ for (int i = 0; i < backupFiles.length; i++)
+ {
+ File f = backupFiles[i];
+ BackupFilenameParts bfp = new BackupFilenameParts(f, basename, suffix, digits, extension);
+ bfHashMap.put(bfp.indexNum(), f);
+ }
+ TreeMap<Integer, File> bfTreeMap = new TreeMap<>();
+ bfTreeMap.putAll(bfHashMap);
+
+ bfTreeMap.values().toArray(backupFiles);
+
+ // max value of -1 means keep all backup files
+ if (bfTreeMap.size() >= max && max != -1)
+ {
+ // need to delete some files to keep number of backups to designated
+ // max
+ int numToDelete = bfTreeMap.size() - max;
+ File[] filesToDelete = Arrays.copyOfRange(backupFiles, 0,
+ numToDelete - 1);
+
+ /******************************************
+ * CONFIRM THESE DELETIONS WITH THE USER! *
+ ******************************************/
+ for (int i = 0; i < filesToDelete.length; i++)
+ {
+ File toDelete = filesToDelete[i];
+ toDelete.delete();
+ }
+
+ }
+
+ nextIndexNum = bfTreeMap.lastKey() + 1;
+
+ // Let's make the new backup file!! yay, got there at last!
+ String nextBackupFilename = dir + File.separatorChar
+ + BackupFilenameParts.getBackupFilename(nextIndexNum,
+ basename, suffix, digits, extension);
+ File nextBackupFile = new File(nextBackupFilename);
+ ret = ret && file.renameTo(nextBackupFile);
+ }
}
return ret;