JAL-629 --argfile=glob implemented. Remove reference seq from pAE Matrix annotation...
authorBen Soares <b.soares@dundee.ac.uk>
Thu, 9 Mar 2023 16:29:19 +0000 (16:29 +0000)
committerBen Soares <b.soares@dundee.ac.uk>
Thu, 9 Mar 2023 16:29:19 +0000 (16:29 +0000)
src/jalview/bin/ArgParser.java
src/jalview/bin/Jalview.java
src/jalview/util/FileUtils.java [new file with mode: 0644]
src/jalview/ws/datamodel/alphafold/PAEContactMatrix.java

index 65d0026..3b08013 100644 (file)
@@ -36,6 +36,8 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 
+import jalview.util.FileUtils;
+
 public class ArgParser
 {
   private static final String NEGATESTRING = "no";
@@ -44,7 +46,8 @@ public class ArgParser
 
   private static enum Opt
   {
-    BOOLEAN, STRING, UNARY, MULTI, LINKED, NODUPLICATEVALUES, BOOTSTRAP
+    BOOLEAN, STRING, UNARY, MULTI, LINKED, NODUPLICATEVALUES, BOOTSTRAP,
+    GLOB
   }
 
   // These bootstrap args are simply parsed before a full parse of arguments and
@@ -124,7 +127,7 @@ public class ArgParser
       CLOSE.setOptions(Opt.UNARY, Opt.LINKED);
       DEBUG.setOptions(Opt.BOOLEAN, Opt.BOOTSTRAP);
       QUIET.setOptions(Opt.UNARY, Opt.MULTI, Opt.BOOTSTRAP);
-      ARGFILE.setOptions(Opt.STRING, Opt.MULTI, Opt.BOOTSTRAP);
+      ARGFILE.setOptions(Opt.STRING, Opt.MULTI, Opt.BOOTSTRAP, Opt.GLOB);
     }
 
     private final String[] argNames;
@@ -1031,27 +1034,39 @@ public class ArgParser
     }
   }
 
-  public static ArgParser parseArgFiles(List<String> argFilenames)
+  public static ArgParser parseArgFiles(List<String> argFilenameGlobs)
+  {
+    List<File> argFiles = new ArrayList<>();
+
+    for (String pattern : argFilenameGlobs)
+    {
+      // I don't think we want to dedup files, making life easier
+      argFiles.addAll(FileUtils.getFilesFromGlob(pattern));
+    }
+
+    return parseArgFileList(argFiles);
+  }
+
+  public static ArgParser parseArgFileList(List<File> argFiles)
   {
     List<String> argsList = new ArrayList<>();
-    for (String argFilename : argFilenames)
+    for (File argFile : argFiles)
     {
-      File argFile = new File(argFilename);
       if (!argFile.exists())
       {
-        System.err
-                .println("--" + Arg.ARGFILE.name().toLowerCase(Locale.ROOT)
-                        + "=\"" + argFilename + "\": File does not exist.");
+        System.err.println(
+                "--" + Arg.ARGFILE.name().toLowerCase(Locale.ROOT) + "=\""
+                        + argFile.getPath() + "\": File does not exist.");
         System.exit(2);
       }
       try
       {
-        argsList.addAll(Files.readAllLines(Paths.get(argFilename)));
+        argsList.addAll(Files.readAllLines(Paths.get(argFile.getPath())));
       } catch (IOException e)
       {
-        System.err.println(
-                "--" + Arg.ARGFILE.name().toLowerCase(Locale.ROOT) + "=\""
-                        + argFilename + "\": File could not be read.");
+        System.err.println("--"
+                + Arg.ARGFILE.name().toLowerCase(Locale.ROOT) + "=\""
+                + argFile.getPath() + "\": File could not be read.");
         System.exit(3);
       }
     }
@@ -1063,14 +1078,14 @@ public class ArgParser
     // only need one
     private static Map<Arg, List<String>> bootstrapArgMap = new HashMap<>();
 
-    private BootstrapArgs(String[] args)
+    public static BootstrapArgs getBootstrapArgs(String[] args)
     {
-      init(args);
+      return new BootstrapArgs(args);
     }
 
-    public static BootstrapArgs getBootstrapArgs(String[] args)
+    private BootstrapArgs(String[] args)
     {
-      return new BootstrapArgs(args);
+      init(args);
     }
 
     private void init(String[] args)
index 87c4ad5..b5def09 100755 (executable)
@@ -428,7 +428,7 @@ public class Jalview
         System.exit(0);
       }
 
-      if (argparser.isSet(Arg.HEADLESS))
+      if (bootstrapArgs.contains(Arg.HEADLESS))
       {
         System.setProperty("java.awt.headless", "true");
         // new
diff --git a/src/jalview/util/FileUtils.java b/src/jalview/util/FileUtils.java
new file mode 100644 (file)
index 0000000..5bc6570
--- /dev/null
@@ -0,0 +1,105 @@
+package jalview.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileSystems;
+import java.nio.file.FileVisitOption;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.PathMatcher;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.List;
+
+public class FileUtils
+{
+  /*
+   * Given string glob pattern (see
+   * https://docs.oracle.com/javase/7/docs/api/java/nio/file/FileSystem.html#getPathMatcher(java.lang.String)
+   * ) return a List of Files that match the pattern.
+   * Note this is a java style glob, not necessarily a bash-style glob, though there are sufficient similarities. 
+   */
+  public static List<File> getFilesFromGlob(String pattern)
+  {
+    List<File> files = new ArrayList<>();
+
+    /*
+     * For efficiency of the Files.walkFileTree, let's find the longest path that doesn't need globbing.
+     * We look for the first glob character * { ? and then look for the last File.separator before that.
+     * Then we can reset the path to look at and shorten the globbing pattern.
+     * Relative paths can be used in pattern, which work from the pwd (though these are converted into
+     * full paths in the match). 
+     */
+    int firstGlobChar = -1;
+    boolean foundGlobChar = false;
+    for (char c : new char[] { '*', '{', '?' })
+    {
+      if (pattern.indexOf(c) > -1
+              && (pattern.indexOf(c) < firstGlobChar || !foundGlobChar))
+      {
+        firstGlobChar = pattern.indexOf(c);
+        foundGlobChar = true;
+      }
+    }
+    int lastFS = pattern.lastIndexOf(File.separatorChar, firstGlobChar);
+    if (foundGlobChar)
+    {
+      String pS = pattern.substring(0, lastFS + 1);
+      String rest = pattern.substring(lastFS + 1);
+      Path parentDir = Paths.get(pS).toAbsolutePath();
+      if (parentDir.toFile().exists())
+      {
+        try
+        {
+          String glob = "glob:" + parentDir.toString() + File.separator
+                  + rest;
+          PathMatcher pm = FileSystems.getDefault().getPathMatcher(glob);
+          int maxDepth = rest.contains("**") ? Integer.MAX_VALUE
+                  : (int) (rest.chars()
+                          .filter(ch -> ch == File.separatorChar).count())
+                          + 1;
+          Files.walkFileTree(parentDir,
+                  EnumSet.of(FileVisitOption.FOLLOW_LINKS), maxDepth,
+                  new SimpleFileVisitor<Path>()
+                  {
+                    @Override
+                    public FileVisitResult visitFile(Path path,
+                            BasicFileAttributes attrs) throws IOException
+                    {
+                      if (pm.matches(path))
+                      {
+                        files.add(path.toFile());
+                      }
+                      return FileVisitResult.CONTINUE;
+                    }
+
+                    @Override
+                    public FileVisitResult visitFileFailed(Path file,
+                            IOException exc) throws IOException
+                    {
+                      return FileVisitResult.CONTINUE;
+                    }
+                  });
+        } catch (IOException e)
+        {
+          e.printStackTrace();
+        }
+      }
+    }
+    else
+    {
+      // no wildcards
+      File f = new File(pattern);
+      if (f.exists())
+      {
+        files.add(f);
+      }
+    }
+
+    return files;
+  }
+}
\ No newline at end of file
index d1a2e9d..cefdbd2 100644 (file)
@@ -224,8 +224,8 @@ public class PAEContactMatrix implements ContactMatrixI
   public String getAnnotLabel()
   {
     StringBuilder label = new StringBuilder("pAE Matrix");
-    if (this.getReferenceSeq() != null)
-      label.append(":").append(this.getReferenceSeq().getDisplayId(false));
+    // if (this.getReferenceSeq() != null)
+    // label.append(":").append(this.getReferenceSeq().getDisplayId(false));
     return label.toString();
   }