JAL-3141 Code checkout. Not compiling.
authorBen Soares <bsoares@dundee.ac.uk>
Wed, 24 Oct 2018 12:23:27 +0000 (13:23 +0100)
committerBen Soares <bsoares@dundee.ac.uk>
Wed, 24 Oct 2018 12:23:27 +0000 (13:23 +0100)
src/jalview/io/BackupFilenameFilter.java
src/jalview/io/BackupFiles.java

index 647e250..8cf7cbf 100644 (file)
@@ -3,7 +3,7 @@ package jalview.io;
 import java.io.File;
 import java.io.FilenameFilter;
 
-public class BackupFileFilter implements FilenameFilter
+public class BackupFilenameFilter implements FilenameFilter
 {
 
   public String base;
@@ -14,7 +14,7 @@ public class BackupFileFilter implements FilenameFilter
 
   public String extension;
 
-  public BackupFileFilter(String base, String template, int digits,
+  public BackupFilenameFilter(String base, String template, int digits,
           String extension)
   {
     this.base = base;
@@ -26,35 +26,102 @@ public class BackupFileFilter implements FilenameFilter
   @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
index da5209b..39cd23e 100644 (file)
@@ -4,6 +4,19 @@ import jalview.bin.Cache;
 
 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
 {
@@ -159,13 +172,21 @@ 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())
@@ -209,11 +230,60 @@ public class BackupFiles
       // 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;