JAL-1551 spotless
[jalview.git] / src / jalview / io / BackupFiles.java
index 2039d3c..c67c307 100644 (file)
@@ -29,8 +29,14 @@ import java.nio.file.StandardCopyOption;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
 
 import jalview.bin.Cache;
 import jalview.bin.Console;
@@ -105,6 +111,117 @@ public class BackupFiles
 
   private static final String oldTempFileSuffix = "_oldfile_tobedeleted";
 
+  // thread pool used for completablefutures
+  private static final ExecutorService executorService = Executors
+          .newFixedThreadPool(3);
+
+  private static List<BackupFiles> savesInProgress = new ArrayList<>();
+
+  private CompletableFuture<Boolean> myFuture = null;
+
+  private boolean addSaveInProgress()
+  {
+    if (savesInProgress.contains(this))
+    {
+      return false;
+    }
+    else
+    {
+      this.setMyFuture();
+      savesInProgress.add(this);
+      return true;
+    }
+  }
+
+  private boolean removeSaveInProgress(boolean ret)
+  {
+    if (savesInProgress.contains(this))
+    {
+      this.getMyFuture().complete(ret);
+      // remove all occurrences
+      while (savesInProgress.remove(this))
+      {
+      }
+      return true;
+    }
+    return false;
+  }
+
+  private static CompletableFuture<Boolean> getNewFuture()
+  {
+    return new CompletableFuture<Boolean>()
+    {
+    };
+  }
+
+  private CompletableFuture<Boolean> getMyFuture()
+  {
+    return this.myFuture;
+  }
+
+  private void setMyFuture()
+  {
+    this.myFuture = getNewFuture();
+  }
+
+  public static boolean hasSavesInProgress()
+  {
+    boolean has = false;
+    for (CompletableFuture cf : savesInProgressCompletableFutures(true))
+    {
+      has |= !cf.isDone();
+    }
+    return has;
+  }
+
+  public static List<File> savesInProgressFiles(boolean all)
+  {
+    List<File> files = new ArrayList<>();
+    for (BackupFiles bfile : savesInProgress)
+    {
+      if (all || !bfile.getMyFuture().isDone())
+        files.add(bfile.getFile());
+    }
+    return files;
+  }
+
+  public static List<CompletableFuture<Boolean>> savesInProgressCompletableFutures(
+          boolean all)
+  {
+    List<CompletableFuture<Boolean>> cfs = new ArrayList<>();
+    for (BackupFiles bfile : savesInProgress)
+    {
+      if (all || !bfile.getMyFuture().isDone())
+        cfs.add(bfile.getMyFuture());
+    }
+    return cfs;
+  }
+
+  public static Future<Boolean> allSaved()
+  {
+    CompletableFuture<Boolean> f = new CompletableFuture<>();
+
+    executorService.submit(() -> {
+      for (BackupFiles buf : savesInProgress)
+      {
+        boolean allSaved = true;
+        try
+        {
+          allSaved &= buf.getMyFuture().get();
+        } catch (InterruptedException e)
+        {
+          Console.debug("InterruptedException waiting for files to save",
+                  e);
+        } catch (ExecutionException e)
+        {
+          Console.debug("ExecutionException waiting for files to save", e);
+        }
+        f.complete(allSaved);
+      }
+    });
+    return f;
+  }
+
   public BackupFiles(String filename)
   {
     this(new File(filename));
@@ -115,7 +232,17 @@ public class BackupFiles
   public BackupFiles(File file)
   {
     classInit();
+    if (file.getParentFile() == null)
+    {
+      // filename probably in pwd represented with no parent -- fix it before
+      // it's a problem
+      file = file.getAbsoluteFile();
+    }
     this.file = file;
+
+    // add this file from the save in progress stack
+    addSaveInProgress();
+
     BackupFilesPresetEntry bfpe = BackupFilesPresetEntry
             .getSavedBackupEntry();
     this.suffix = bfpe.suffix;
@@ -131,7 +258,8 @@ public class BackupFiles
       if (file != null)
       {
         String tempfilename = file.getName();
-        File tempdir = file.getParentFile();
+        File tempdir = file.getAbsoluteFile().getParentFile();
+        tempdir.mkdirs();
         Console.trace(
                 "BACKUPFILES [file!=null] attempting to create temp file for "
                         + tempfilename + " in dir " + tempdir);
@@ -161,7 +289,7 @@ public class BackupFiles
     this.setTempFile(temp);
   }
 
-  public static void classInit()
+  private static void classInit()
   {
     Console.initLogger();
     Console.trace("BACKUPFILES classInit");
@@ -819,6 +947,9 @@ public class BackupFiles
       tidyUpFiles();
     }
 
+    // remove this file from the save in progress stack
+    removeSaveInProgress(rename);
+
     return rename;
   }
 
@@ -890,6 +1021,11 @@ public class BackupFiles
     return ret;
   }
 
+  public File getFile()
+  {
+    return file;
+  }
+
   public static boolean moveFileToFile(File oldFile, File newFile)
   {
     Console.initLogger();