JAL-629 Added --opened arg which is like limiting --all to only the previously -...
authorBen Soares <b.soares@dundee.ac.uk>
Fri, 12 May 2023 14:34:06 +0000 (15:34 +0100)
committerBen Soares <b.soares@dundee.ac.uk>
Fri, 12 May 2023 14:34:06 +0000 (15:34 +0100)
src/jalview/bin/Commands.java
src/jalview/bin/argparser/Arg.java
src/jalview/bin/argparser/ArgParser.java
test/jalview/bin/CommandsTest.java
test/jalview/bin/argparser/ArgParserTest.java

index 679fbf4..50ff7c3 100644 (file)
@@ -693,6 +693,8 @@ public class Commands
         Cache.setPropsAreReadOnly(true);
         Cache.setProperty("EXPORT_EMBBED_BIOJSON", "false");
 
         Cache.setPropsAreReadOnly(true);
         Cache.setProperty("EXPORT_EMBBED_BIOJSON", "false");
 
+        Console.info("Writing " + file);
+
         switch (type)
         {
 
         switch (type)
         {
 
@@ -838,6 +840,9 @@ public class Commands
         Console.debug("Setting backups to " + backups);
         Cache.applicationProperties.put(BackupFiles.ENABLED,
                 Boolean.toString(backups));
         Console.debug("Setting backups to " + backups);
         Cache.applicationProperties.put(BackupFiles.ENABLED,
                 Boolean.toString(backups));
+
+        Console.info("Writing " + fileName);
+
         af.saveAlignment(fileName, ff);
         Console.debug("Returning backups to " + savedBackupsPreference);
         if (savedBackupsPreference != null)
         af.saveAlignment(fileName, ff);
         Console.debug("Returning backups to " + savedBackupsPreference);
         if (savedBackupsPreference != null)
index ba981fb..46de01b 100644 (file)
@@ -54,20 +54,23 @@ public enum Arg
   // Opening an alignment
   OPEN("Opens one or more alignment files or URLs in new alignment windows.",
           Opt.STRING, Opt.LINKED, Opt.INCREMENTDEFAULTCOUNTER, Opt.MULTI,
   // Opening an alignment
   OPEN("Opens one or more alignment files or URLs in new alignment windows.",
           Opt.STRING, Opt.LINKED, Opt.INCREMENTDEFAULTCOUNTER, Opt.MULTI,
-          Opt.GLOB, Opt.ALLOWSUBSTITUTIONS, Opt.INPUT),
+          Opt.GLOB, Opt.ALLOWSUBSTITUTIONS, Opt.INPUT, Opt.STORED),
   APPEND("Appends one or more alignment files or URLs to the open alignment window (or opens a new alignment if none already open).",
           Opt.STRING, Opt.LINKED, Opt.MULTI, Opt.GLOB,
           Opt.ALLOWSUBSTITUTIONS, Opt.INPUT),
   TITLE("Specifies the title for the open alignment window as string.",
           Opt.STRING, Opt.LINKED),
   APPEND("Appends one or more alignment files or URLs to the open alignment window (or opens a new alignment if none already open).",
           Opt.STRING, Opt.LINKED, Opt.MULTI, Opt.GLOB,
           Opt.ALLOWSUBSTITUTIONS, Opt.INPUT),
   TITLE("Specifies the title for the open alignment window as string.",
           Opt.STRING, Opt.LINKED),
-  COLOUR("Applies the colour scheme to the open alignment window. Valid values are:\n"
-          + "clustal,\n" + "blosum62,\n" + "pc-identity,\n" + "zappo,\n"
-          + "taylor,\n" + "gecos-flower,\n" + "gecos-blossom,\n"
-          + "gecos-sunset,\n" + "gecos-ocean,\n" + "hydrophobic,\n"
-          + "helix-propensity,\n" + "strand-propensity,\n"
-          + "turn-propensity,\n" + "buried-index,\n" + "nucleotide,\n"
-          + "nucleotide-ambiguity,\n" + "purine-pyrimidine,\n"
-          + "rna-helices,\n" + "t-coffee-scores,\n" + "sequence-id.",
+  COLOUR("color", // being a bit soft on the Americans!
+          "Applies the colour scheme to the open alignment window. Valid values are:\n"
+                  + "clustal,\n" + "blosum62,\n" + "pc-identity,\n"
+                  + "zappo,\n" + "taylor,\n" + "gecos-flower,\n"
+                  + "gecos-blossom,\n" + "gecos-sunset,\n"
+                  + "gecos-ocean,\n" + "hydrophobic,\n"
+                  + "helix-propensity,\n" + "strand-propensity,\n"
+                  + "turn-propensity,\n" + "buried-index,\n"
+                  + "nucleotide,\n" + "nucleotide-ambiguity,\n"
+                  + "purine-pyrimidine,\n" + "rna-helices,\n"
+                  + "t-coffee-scores,\n" + "sequence-id.",
           Opt.STRING, Opt.LINKED, Opt.ALLOWALL),
   FEATURES("Add a feature file or URL to the open alignment.", Opt.STRING,
           Opt.LINKED, Opt.MULTI, Opt.ALLOWSUBSTITUTIONS),
           Opt.STRING, Opt.LINKED, Opt.ALLOWALL),
   FEATURES("Add a feature file or URL to the open alignment.", Opt.STRING,
           Opt.LINKED, Opt.MULTI, Opt.ALLOWSUBSTITUTIONS),
@@ -173,6 +176,8 @@ public enum Arg
           Opt.UNARY, Opt.MULTI, Opt.NOACTION),
   ALL("Apply the following output arguments to all sets of linked arguments.",
           Opt.BOOLEAN, Opt.MULTI, Opt.NOACTION),
           Opt.UNARY, Opt.MULTI, Opt.NOACTION),
   ALL("Apply the following output arguments to all sets of linked arguments.",
           Opt.BOOLEAN, Opt.MULTI, Opt.NOACTION),
+  OPENED("Apply the following output arguments to all of the last --open'ed set of linked arguments.",
+          Opt.BOOLEAN, Opt.MULTI, Opt.NOACTION),
   QUIT("After all files have been opened, appended and output, quit Jalview. In ‑‑headless mode this already happens.",
           Opt.UNARY),
 
   QUIT("After all files have been opened, appended and output, quit Jalview. In ‑‑headless mode this already happens.",
           Opt.UNARY),
 
@@ -256,6 +261,7 @@ public enum Arg
                   // input (i.e. --open or --append)
     OUTPUT, // This Arg provides an output filename. With Opt.ALLOWALL *.ext is
             // shorthand for --all --output={basename}.ext
                   // input (i.e. --open or --append)
     OUTPUT, // This Arg provides an output filename. With Opt.ALLOWALL *.ext is
             // shorthand for --all --output={basename}.ext
+    STORED, // This Arg resets and creates a new set of "opened" linkedIds
   }
 
   private final String[] argNames;
   }
 
   private final String[] argNames;
index 3ca5d3d..7132e89 100644 (file)
@@ -55,6 +55,9 @@ public class ArgParser
   // the linkedId string used to match all linkedIds seen so far
   protected static final String MATCHALLLINKEDIDS = "*";
 
   // the linkedId string used to match all linkedIds seen so far
   protected static final String MATCHALLLINKEDIDS = "*";
 
+  // the linkedId string used to match all of the last --open'ed linkedIds
+  protected static final String MATCHOPENEDLINKEDIDS = "open*";
+
   // the counter added to the default linked id prefix
   private int defaultLinkedIdCounter = 0;
 
   // the counter added to the default linked id prefix
   private int defaultLinkedIdCounter = 0;
 
@@ -110,12 +113,18 @@ public class ArgParser
   // or ALL linkedIds
   private boolean allLinkedIds = false;
 
   // or ALL linkedIds
   private boolean allLinkedIds = false;
 
+  // flag to say whether the default linkedId is the current default linked id
+  // or OPENED linkedIds
+  private boolean openedLinkedIds = false;
+
   protected static final Map<String, Arg> argMap;
 
   protected Map<String, ArgValuesMap> linkedArgs = new HashMap<>();
 
   protected List<String> linkedOrder = new ArrayList<>();
 
   protected static final Map<String, Arg> argMap;
 
   protected Map<String, ArgValuesMap> linkedArgs = new HashMap<>();
 
   protected List<String> linkedOrder = new ArrayList<>();
 
+  protected List<String> storedLinkedIds = new ArrayList<>();
+
   protected List<Arg> argList = new ArrayList<>();
 
   private static final char ARGFILECOMMENT = '#';
   protected List<Arg> argList = new ArrayList<>();
 
   private static final char ARGFILECOMMENT = '#';
@@ -380,6 +389,18 @@ public class ArgParser
         else if (a == Arg.ALL)
         {
           allLinkedIds = !negated;
         else if (a == Arg.ALL)
         {
           allLinkedIds = !negated;
+          openedLinkedIds = false;
+        }
+        else if (a == Arg.OPENED)
+        {
+          openedLinkedIds = !negated;
+          allLinkedIds = false;
+        }
+
+        if (a.hasOption(Opt.STORED))
+        {
+          // reset the lastOpenedLinkedIds list
+          this.storedLinkedIds = new ArrayList<>();
         }
 
         // this is probably only Arg.NEW and Arg.OPEN
         }
 
         // this is probably only Arg.NEW and Arg.OPEN
@@ -398,20 +419,36 @@ public class ArgParser
           if (linkedId == null)
           {
             if (a.hasOption(Opt.OUTPUT) && a.hasOption(Opt.ALLOWALL)
           if (linkedId == null)
           {
             if (a.hasOption(Opt.OUTPUT) && a.hasOption(Opt.ALLOWALL)
-                    && val.startsWith(OUTPUTWILDCARD))
+                    && val.startsWith(MATCHALLLINKEDIDS))
             {
               // --output=*.ext is shorthand for --all --output {basename}.ext
               // (or --image=*.ext)
               allLinkedIds = true;
             {
               // --output=*.ext is shorthand for --all --output {basename}.ext
               // (or --image=*.ext)
               allLinkedIds = true;
+              openedLinkedIds = false;
               linkedId = MATCHALLLINKEDIDS;
               linkedId = MATCHALLLINKEDIDS;
-              String oldval = val;
-              val = LINKEDIDBASENAME
-                      + val.substring(OUTPUTWILDCARD.length() - 1);
+              val = LINKEDIDDIRNAME + File.separator + LINKEDIDBASENAME
+                      + val.substring(MATCHALLLINKEDIDS.length());
+            }
+            else if (a.hasOption(Opt.OUTPUT) && a.hasOption(Opt.ALLOWALL)
+                    && val.startsWith(MATCHOPENEDLINKEDIDS))
+            {
+              // --output=open*.ext is shorthand for --opened --output
+              // {basename}.ext
+              // (or --image=open*.ext)
+              openedLinkedIds = true;
+              allLinkedIds = false;
+              linkedId = MATCHOPENEDLINKEDIDS;
+              val = LINKEDIDDIRNAME + File.separator + LINKEDIDBASENAME
+                      + val.substring(MATCHOPENEDLINKEDIDS.length());
             }
             else if (allLinkedIds && a.hasOption(Opt.ALLOWALL))
             {
               linkedId = MATCHALLLINKEDIDS;
             }
             }
             else if (allLinkedIds && a.hasOption(Opt.ALLOWALL))
             {
               linkedId = MATCHALLLINKEDIDS;
             }
+            else if (openedLinkedIds && a.hasOption(Opt.ALLOWALL))
+            {
+              linkedId = MATCHOPENEDLINKEDIDS;
+            }
             else
             {
               // use default linkedId for linked arguments
             else
             {
               // use default linkedId for linked arguments
@@ -514,9 +551,12 @@ public class ArgParser
           setBoolean(linkedId, avs, true, argIndex);
         }
 
           setBoolean(linkedId, avs, true, argIndex);
         }
 
-        // remove the '*' linkedId that should be empty if it was created
-        if (MATCHALLLINKEDIDS.equals(linkedId)
+        // remove the '*' or 'open*' linkedId that should be empty if it was
+        // created
+        if ((MATCHALLLINKEDIDS.equals(linkedId)
                 && linkedArgs.containsKey(linkedId))
                 && linkedArgs.containsKey(linkedId))
+                || (MATCHOPENEDLINKEDIDS.equals(linkedId)
+                        && linkedArgs.containsKey(linkedId)))
         {
           linkedArgs.remove(linkedId);
         }
         {
           linkedArgs.remove(linkedId);
         }
@@ -930,16 +970,52 @@ public class ArgParser
   }
 
   // the following methods look for the "*" linkedId and add the argvalue to all
   }
 
   // the following methods look for the "*" linkedId and add the argvalue to all
-  // linkedId ArgValues if it does
+  // linkedId ArgValues if it does.
+  // This version inserts the subvals sv into all created values
   private void addValue(String linkedId, ArgValues avs, SubVals sv,
           String v, int argIndex, boolean doSubs)
   {
   private void addValue(String linkedId, ArgValues avs, SubVals sv,
           String v, int argIndex, boolean doSubs)
   {
+    this.argValueOperation(Op.ADDVALUE, linkedId, avs, sv, v, false,
+            argIndex, doSubs);
+  }
+
+  private void NOTaddValue(String linkedId, ArgValues avs, SubVals sv,
+          String v, int argIndex, boolean doSubs)
+  {
     Arg a = avs.arg();
     Arg a = avs.arg();
-    if (MATCHALLLINKEDIDS.equals(linkedId) && a.hasOption(Opt.ALLOWALL))
+
+    List<String> wildcardLinkedIds = null;
+    if (a.hasOption(Opt.ALLOWALL))
     {
     {
-      for (String id : getLinkedIds())
+      switch (linkedId)
       {
       {
-        if (id == null || MATCHALLLINKEDIDS.equals(id))
+      case MATCHALLLINKEDIDS:
+        wildcardLinkedIds = getLinkedIds();
+        break;
+      case MATCHOPENEDLINKEDIDS:
+        wildcardLinkedIds = this.storedLinkedIds;
+        break;
+      }
+    }
+
+    // if we're not a wildcard linkedId and the arg is marked to be stored, add
+    // to storedLinkedIds
+    if (linkedId != null && wildcardLinkedIds == null
+            && a.hasOption(Opt.STORED)
+            && !storedLinkedIds.contains(linkedId))
+    {
+      storedLinkedIds.add(linkedId);
+    }
+
+    // if we are a wildcard linkedId, apply the arg and value to all appropriate
+    // linkedIds
+    if (wildcardLinkedIds != null)
+    {
+      for (String id : wildcardLinkedIds)
+      {
+        // skip incorrectly stored wildcard ids!
+        if (id == null || MATCHALLLINKEDIDS.equals(id)
+                || MATCHOPENEDLINKEDIDS.equals(id))
           continue;
         ArgValuesMap avm = linkedArgs.get(id);
         if (a.hasOption(Opt.REQUIREINPUT)
           continue;
         ArgValuesMap avm = linkedArgs.get(id);
         if (a.hasOption(Opt.REQUIREINPUT)
@@ -972,12 +1048,54 @@ public class ArgParser
   private void addValue(String linkedId, ArgValues avs, String v,
           int argIndex, boolean doSubs)
   {
   private void addValue(String linkedId, ArgValues avs, String v,
           int argIndex, boolean doSubs)
   {
+    this.argValueOperation(Op.ADDVALUE, linkedId, avs, null, v, false,
+            argIndex, doSubs);
+  }
+
+  // the following methods look for the "*" linkedId and add the argvalue to all
+  // linkedId ArgValues if it does.
+  private void NOTaddValue(String linkedId, ArgValues avs, String v,
+          int argIndex, boolean doSubs)
+  {
     Arg a = avs.arg();
     Arg a = avs.arg();
-    if (MATCHALLLINKEDIDS.equals(linkedId) && a.hasOption(Opt.ALLOWALL))
+    if (linkedId != null && a.hasOption(Opt.STORED)
+            && !storedLinkedIds.contains(linkedId))
     {
     {
-      for (String id : getLinkedIds())
+      storedLinkedIds.add(linkedId);
+    }
+
+    List<String> wildcardLinkedIds = null;
+    if (a.hasOption(Opt.ALLOWALL))
+    {
+      switch (linkedId)
       {
       {
-        if (id == null || MATCHALLLINKEDIDS.equals(id))
+      case MATCHALLLINKEDIDS:
+        wildcardLinkedIds = getLinkedIds();
+        break;
+      case MATCHOPENEDLINKEDIDS:
+        wildcardLinkedIds = this.storedLinkedIds;
+        break;
+      }
+    }
+
+    // if we're not a wildcard linkedId and the arg is marked to be stored, add
+    // to storedLinkedIds
+    if (linkedId != null && wildcardLinkedIds == null
+            && a.hasOption(Opt.STORED)
+            && !storedLinkedIds.contains(linkedId))
+    {
+      storedLinkedIds.add(linkedId);
+    }
+
+    // if we are a wildcard linkedId, apply the arg and value to all appropriate
+    // linkedIds
+    if (wildcardLinkedIds != null)
+    {
+      for (String id : wildcardLinkedIds)
+      {
+        // skip incorrectly stored wildcard ids!
+        if (id == null || MATCHALLLINKEDIDS.equals(id)
+                || MATCHOPENEDLINKEDIDS.equals(id))
           continue;
         ArgValuesMap avm = linkedArgs.get(id);
         // don't set an output if there isn't an input
           continue;
         ArgValuesMap avm = linkedArgs.get(id);
         // don't set an output if there isn't an input
@@ -1001,12 +1119,52 @@ public class ArgParser
   private void setBoolean(String linkedId, ArgValues avs, boolean b,
           int argIndex)
   {
   private void setBoolean(String linkedId, ArgValues avs, boolean b,
           int argIndex)
   {
+    this.argValueOperation(Op.SETBOOLEAN, linkedId, avs, null, null, b,
+            argIndex, false);
+  }
+
+  private void NOTsetBoolean(String linkedId, ArgValues avs, boolean b,
+          int argIndex)
+  {
     Arg a = avs.arg();
     Arg a = avs.arg();
-    if (MATCHALLLINKEDIDS.equals(linkedId) && a.hasOption(Opt.ALLOWALL))
+    if (linkedId != null && a.hasOption(Opt.STORED)
+            && !storedLinkedIds.contains(linkedId))
     {
     {
-      for (String id : getLinkedIds())
+      storedLinkedIds.add(linkedId);
+    }
+
+    List<String> wildcardLinkedIds = null;
+    if (a.hasOption(Opt.ALLOWALL))
+    {
+      switch (linkedId)
+      {
+      case MATCHALLLINKEDIDS:
+        wildcardLinkedIds = getLinkedIds();
+        break;
+      case MATCHOPENEDLINKEDIDS:
+        wildcardLinkedIds = this.storedLinkedIds;
+        break;
+      }
+    }
+
+    // if we're not a wildcard linkedId and the arg is marked to be stored, add
+    // to storedLinkedIds
+    if (linkedId != null && wildcardLinkedIds == null
+            && a.hasOption(Opt.STORED)
+            && !storedLinkedIds.contains(linkedId))
+    {
+      storedLinkedIds.add(linkedId);
+    }
+
+    // if we are a wildcard linkedId, apply the arg and value to all appropriate
+    // linkedIds
+    if (wildcardLinkedIds != null)
+    {
+      for (String id : wildcardLinkedIds)
       {
       {
-        if (id == null || MATCHALLLINKEDIDS.equals(id))
+        // skip incorrectly stored wildcard ids!
+        if (id == null || MATCHALLLINKEDIDS.equals(id)
+                || MATCHOPENEDLINKEDIDS.equals(id))
           continue;
         ArgValuesMap avm = linkedArgs.get(id);
         if (a.hasOption(Opt.REQUIREINPUT)
           continue;
         ArgValuesMap avm = linkedArgs.get(id);
         if (a.hasOption(Opt.REQUIREINPUT)
@@ -1026,12 +1184,51 @@ public class ArgParser
 
   private void setNegated(String linkedId, ArgValues avs, boolean b)
   {
 
   private void setNegated(String linkedId, ArgValues avs, boolean b)
   {
+    this.argValueOperation(Op.SETNEGATED, linkedId, avs, null, null, b, 0,
+            false);
+  }
+
+  private void NOTsetNegated(String linkedId, ArgValues avs, boolean b)
+  {
     Arg a = avs.arg();
     Arg a = avs.arg();
-    if (MATCHALLLINKEDIDS.equals(linkedId) && a.hasOption(Opt.ALLOWALL))
+    if (linkedId != null && a.hasOption(Opt.STORED)
+            && !storedLinkedIds.contains(linkedId))
     {
     {
-      for (String id : getLinkedIds())
+      storedLinkedIds.add(linkedId);
+    }
+
+    List<String> wildcardLinkedIds = null;
+    if (a.hasOption(Opt.ALLOWALL))
+    {
+      switch (linkedId)
       {
       {
-        if (id == null || MATCHALLLINKEDIDS.equals(id))
+      case MATCHALLLINKEDIDS:
+        wildcardLinkedIds = getLinkedIds();
+        break;
+      case MATCHOPENEDLINKEDIDS:
+        wildcardLinkedIds = this.storedLinkedIds;
+        break;
+      }
+    }
+
+    // if we're not a wildcard linkedId and the arg is marked to be stored, add
+    // to storedLinkedIds
+    if (linkedId != null && wildcardLinkedIds == null
+            && a.hasOption(Opt.STORED)
+            && !storedLinkedIds.contains(linkedId))
+    {
+      storedLinkedIds.add(linkedId);
+    }
+
+    // if we are a wildcard linkedId, apply the arg and value to all appropriate
+    // linkedIds
+    if (wildcardLinkedIds != null)
+    {
+      for (String id : wildcardLinkedIds)
+      {
+        // skip incorrectly stored wildcard ids!
+        if (id == null || MATCHALLLINKEDIDS.equals(id)
+                || MATCHOPENEDLINKEDIDS.equals(id))
           continue;
         ArgValuesMap avm = linkedArgs.get(id);
         if (a.hasOption(Opt.REQUIREINPUT)
           continue;
         ArgValuesMap avm = linkedArgs.get(id);
         if (a.hasOption(Opt.REQUIREINPUT)
@@ -1049,12 +1246,46 @@ public class ArgParser
 
   private void incrementCount(String linkedId, ArgValues avs)
   {
 
   private void incrementCount(String linkedId, ArgValues avs)
   {
+    this.argValueOperation(Op.INCREMENTCOUNT, linkedId, avs, null, null,
+            false, 0, false);
+  }
+
+  private void NOTincrementCount(String linkedId, ArgValues avs)
+  {
     Arg a = avs.arg();
     Arg a = avs.arg();
-    if (MATCHALLLINKEDIDS.equals(linkedId) && a.hasOption(Opt.ALLOWALL))
+
+    List<String> wildcardLinkedIds = null;
+    if (a.hasOption(Opt.ALLOWALL))
     {
     {
-      for (String id : getLinkedIds())
+      switch (linkedId)
       {
       {
-        if (id == null || MATCHALLLINKEDIDS.equals(id))
+      case MATCHALLLINKEDIDS:
+        wildcardLinkedIds = getLinkedIds();
+        break;
+      case MATCHOPENEDLINKEDIDS:
+        wildcardLinkedIds = this.storedLinkedIds;
+        break;
+      }
+    }
+
+    // if we're not a wildcard linkedId and the arg is marked to be stored, add
+    // to storedLinkedIds
+    if (linkedId != null && wildcardLinkedIds == null
+            && a.hasOption(Opt.STORED)
+            && !storedLinkedIds.contains(linkedId))
+    {
+      storedLinkedIds.add(linkedId);
+    }
+
+    // if we are a wildcard linkedId, apply the arg and value to all appropriate
+    // linkedIds
+    if (wildcardLinkedIds != null)
+    {
+      for (String id : wildcardLinkedIds)
+      {
+        // skip incorrectly stored wildcard ids!
+        if (id == null || MATCHALLLINKEDIDS.equals(id)
+                || MATCHOPENEDLINKEDIDS.equals(id))
           continue;
         ArgValuesMap avm = linkedArgs.get(id);
         if (a.hasOption(Opt.REQUIREINPUT)
           continue;
         ArgValuesMap avm = linkedArgs.get(id);
         if (a.hasOption(Opt.REQUIREINPUT)
@@ -1070,6 +1301,149 @@ public class ArgParser
     }
   }
 
     }
   }
 
+  private enum Op
+  {
+    ADDVALUE, SETBOOLEAN, SETNEGATED, INCREMENTCOUNT
+  }
+
+  // The following operations look for the "*" and "open*" linkedIds and add the
+  // argvalue to all appropriate linkedId ArgValues if it does.
+  // If subvals are supplied, they are inserted into all new set values.
+  private void argValueOperation(Op op, String linkedId, ArgValues avs,
+          SubVals sv, String v, boolean b, int argIndex, boolean doSubs)
+  {
+    Arg a = avs.arg();
+
+    List<String> wildcardLinkedIds = null;
+    if (a.hasOption(Opt.ALLOWALL))
+    {
+      switch (linkedId)
+      {
+      case MATCHALLLINKEDIDS:
+        wildcardLinkedIds = getLinkedIds();
+        break;
+      case MATCHOPENEDLINKEDIDS:
+        wildcardLinkedIds = this.storedLinkedIds;
+        break;
+      }
+    }
+
+    // if we're not a wildcard linkedId and the arg is marked to be stored, add
+    // to storedLinkedIds
+    if (linkedId != null && wildcardLinkedIds == null
+            && a.hasOption(Opt.STORED)
+            && !storedLinkedIds.contains(linkedId))
+    {
+      storedLinkedIds.add(linkedId);
+    }
+
+    // if we are a wildcard linkedId, apply the arg and value to all appropriate
+    // linkedIds
+    if (wildcardLinkedIds != null)
+    {
+      for (String id : wildcardLinkedIds)
+      {
+        // skip incorrectly stored wildcard ids!
+        if (id == null || MATCHALLLINKEDIDS.equals(id)
+                || MATCHOPENEDLINKEDIDS.equals(id))
+          continue;
+        ArgValuesMap avm = linkedArgs.get(id);
+        // don't set an output if there isn't an input
+        if (a.hasOption(Opt.REQUIREINPUT)
+                && !avm.hasArgWithOption(Opt.INPUT))
+          continue;
+
+        ArgValues tavs = avm.getOrCreateArgValues(a);
+        switch (op)
+        {
+
+        case ADDVALUE:
+          String val = v;
+          if (sv != null)
+          {
+            if (doSubs)
+            {
+              val = makeSubstitutions(v, id);
+              sv = new SubVals(sv, val);
+            }
+            tavs.addValue(sv, val, argIndex);
+          }
+          else
+          {
+            if (doSubs)
+            {
+              val = makeSubstitutions(v, id);
+            }
+            tavs.addValue(val, argIndex);
+          }
+          finaliseStoringArgValue(id, tavs);
+          break;
+
+        case SETBOOLEAN:
+          tavs.setBoolean(b, argIndex);
+          finaliseStoringArgValue(id, tavs);
+          break;
+
+        case SETNEGATED:
+          tavs.setNegated(b);
+          break;
+
+        case INCREMENTCOUNT:
+          tavs.incrementCount();
+          break;
+
+        default:
+          break;
+
+        }
+
+      }
+    }
+    else // no wildcard linkedId -- do it simpler
+    {
+      switch (op)
+      {
+      case ADDVALUE:
+        String val = v;
+        if (sv != null)
+        {
+          if (doSubs)
+          {
+            val = makeSubstitutions(v, linkedId);
+            sv = new SubVals(sv, val);
+          }
+          avs.addValue(sv, val, argIndex);
+        }
+        else
+        {
+          if (doSubs)
+          {
+            val = makeSubstitutions(v, linkedId);
+          }
+          avs.addValue(val, argIndex);
+        }
+        finaliseStoringArgValue(linkedId, avs);
+        break;
+
+      case SETBOOLEAN:
+        avs.setBoolean(b, argIndex);
+        finaliseStoringArgValue(linkedId, avs);
+        break;
+
+      case SETNEGATED:
+        avs.setNegated(b);
+        break;
+
+      case INCREMENTCOUNT:
+        avs.incrementCount();
+        break;
+
+      default:
+        break;
+      }
+    }
+  }
+
   private ArgValuesMap getOrCreateLinkedArgValuesMap(String linkedId)
   {
     if (linkedArgs.containsKey(linkedId)
   private ArgValuesMap getOrCreateLinkedArgValuesMap(String linkedId)
   {
     if (linkedArgs.containsKey(linkedId)
index fed1976..8767098 100644 (file)
@@ -24,10 +24,6 @@ public class CommandsTest
 {
   private static final String testfiles = "test/jalview/bin/argparser/testfiles";
 
 {
   private static final String testfiles = "test/jalview/bin/argparser/testfiles";
 
-  private static final String png1 = testfiles + "/dir1/test1.png";
-
-  private static final String png2 = testfiles + "/dir2/test1.png";
-
   @BeforeClass(alwaysRun = true)
   public static void setUpBeforeClass() throws Exception
   {
   @BeforeClass(alwaysRun = true)
   public static void setUpBeforeClass() throws Exception
   {
@@ -224,7 +220,8 @@ public class CommandsTest
   }
 
   @Test(groups = "Functional", dataProvider = "allLinkedIdsData")
   }
 
   @Test(groups = "Functional", dataProvider = "allLinkedIdsData")
-  public void allLinkedIdsTest(String cmdLine, String[] filenames)
+  public void allLinkedIdsTest(String cmdLine, String[] filenames,
+          String[] nonfilenames)
   {
     String[] args = cmdLine.split("\\s+");
     Jalview.main(args);
   {
     String[] args = cmdLine.split("\\s+");
     Jalview.main(args);
@@ -236,6 +233,15 @@ public class CommandsTest
               "File '" + filename + "' was not created");
     }
     cleanupFiles(filenames);
               "File '" + filename + "' was not created");
     }
     cleanupFiles(filenames);
+    if (nonfilenames != null)
+    {
+      for (String nonfilename : nonfilenames)
+      {
+        File nonfile = new File(nonfilename);
+        Assert.assertFalse(nonfile.exists(),
+                "File " + nonfilename + " exists when it shouldn't!");
+      }
+    }
   }
 
   @DataProvider(name = "allLinkedIdsData")
   }
 
   @DataProvider(name = "allLinkedIdsData")
@@ -244,22 +250,109 @@ public class CommandsTest
     return new Object[][] {
         //
         /*
     return new Object[][] {
         //
         /*
+         */
         { "--open=test/jalview/bin/argparser/testfiles/*.fa --substitutions --all --output={dirname}/{basename}.stk --close",
         { "--open=test/jalview/bin/argparser/testfiles/*.fa --substitutions --all --output={dirname}/{basename}.stk --close",
-            Arg.OUTPUT, new String[]
+            new String[]
             { "test/jalview/bin/argparser/testfiles/test1.stk",
                 "test/jalview/bin/argparser/testfiles/test2.stk",
             { "test/jalview/bin/argparser/testfiles/test1.stk",
                 "test/jalview/bin/argparser/testfiles/test2.stk",
-                "test/jalview/bin/argparser/testfiles/test3.stk", } },
-        */
+                "test/jalview/bin/argparser/testfiles/test3.stk", },
+            null },
         { "--open=test/jalview/bin/argparser/testfiles/*.fa --substitutions --all --image={dirname}/{basename}.png --close",
             new String[]
             { "test/jalview/bin/argparser/testfiles/test1.png",
                 "test/jalview/bin/argparser/testfiles/test2.png",
         { "--open=test/jalview/bin/argparser/testfiles/*.fa --substitutions --all --image={dirname}/{basename}.png --close",
             new String[]
             { "test/jalview/bin/argparser/testfiles/test1.png",
                 "test/jalview/bin/argparser/testfiles/test2.png",
-                "test/jalview/bin/argparser/testfiles/test3.png", } },
+                "test/jalview/bin/argparser/testfiles/test3.png", },
+            null },
         { "--open=test/jalview/bin/argparser/testfiles/*.fa --all --output={dirname}/{basename}.stk --close",
             new String[]
             { "test/jalview/bin/argparser/testfiles/test1.stk",
                 "test/jalview/bin/argparser/testfiles/test2.stk",
         { "--open=test/jalview/bin/argparser/testfiles/*.fa --all --output={dirname}/{basename}.stk --close",
             new String[]
             { "test/jalview/bin/argparser/testfiles/test1.stk",
                 "test/jalview/bin/argparser/testfiles/test2.stk",
-                "test/jalview/bin/argparser/testfiles/test3.stk", } },
+                "test/jalview/bin/argparser/testfiles/test3.stk", },
+            new String[]
+            { "test/jalview/bin/argparser/testfiles/dir1/test1.stk",
+                "test/jalview/bin/argparser/testfiles/dir1/test2.stk",
+                "test/jalview/bin/argparser/testfiles/dir2/test1.stk",
+                "test/jalview/bin/argparser/testfiles/dir2/test2.stk",
+                "test/jalview/bin/argparser/testfiles/dir2/test3.stk",
+                "test/jalview/bin/argparser/testfiles/dir3/subdir/test0.stk",
+                "test/jalview/bin/argparser/testfiles/dir3/subdir/test1.stk",
+                "test/jalview/bin/argparser/testfiles/dir3/subdir/test2.stk",
+                "test/jalview/bin/argparser/testfiles/dir3/subdir/test3.stk", }, },
+        { "--open=test/jalview/bin/argparser/**/*.fa --all --output={dirname}/{basename}.stk --close",
+            new String[]
+            { "test/jalview/bin/argparser/testfiles/test1.stk",
+                "test/jalview/bin/argparser/testfiles/test2.stk",
+                "test/jalview/bin/argparser/testfiles/test3.stk",
+                "test/jalview/bin/argparser/testfiles/dir1/test1.stk",
+                "test/jalview/bin/argparser/testfiles/dir1/test2.stk",
+                "test/jalview/bin/argparser/testfiles/dir2/test1.stk",
+                "test/jalview/bin/argparser/testfiles/dir2/test2.stk",
+                "test/jalview/bin/argparser/testfiles/dir2/test3.stk",
+                "test/jalview/bin/argparser/testfiles/dir3/subdir/test0.stk",
+                "test/jalview/bin/argparser/testfiles/dir3/subdir/test1.stk",
+                "test/jalview/bin/argparser/testfiles/dir3/subdir/test2.stk",
+                "test/jalview/bin/argparser/testfiles/dir3/subdir/test3.stk", },
+            null },
+        { "--open=test/jalview/bin/argparser/**/*.fa --output=*.stk --close",
+            new String[]
+            { "test/jalview/bin/argparser/testfiles/test1.stk",
+                "test/jalview/bin/argparser/testfiles/test2.stk",
+                "test/jalview/bin/argparser/testfiles/test3.stk",
+                "test/jalview/bin/argparser/testfiles/dir1/test1.stk",
+                "test/jalview/bin/argparser/testfiles/dir1/test2.stk",
+                "test/jalview/bin/argparser/testfiles/dir2/test1.stk",
+                "test/jalview/bin/argparser/testfiles/dir2/test2.stk",
+                "test/jalview/bin/argparser/testfiles/dir2/test3.stk",
+                "test/jalview/bin/argparser/testfiles/dir3/subdir/test0.stk",
+                "test/jalview/bin/argparser/testfiles/dir3/subdir/test1.stk",
+                "test/jalview/bin/argparser/testfiles/dir3/subdir/test2.stk",
+                "test/jalview/bin/argparser/testfiles/dir3/subdir/test3.stk", },
+            null },
+        { "--open=test/jalview/bin/argparser/testfiles/dir1/*.fa --open=test/jalview/bin/argparser/testfiles/dir2/*.fa --output=*.stk --close",
+            new String[]
+            { "test/jalview/bin/argparser/testfiles/dir1/test1.stk",
+                "test/jalview/bin/argparser/testfiles/dir1/test2.stk",
+                "test/jalview/bin/argparser/testfiles/dir2/test1.stk",
+                "test/jalview/bin/argparser/testfiles/dir2/test2.stk",
+                "test/jalview/bin/argparser/testfiles/dir2/test3.stk", },
+            new String[]
+            { "test/jalview/bin/argparser/testfiles/test1.stk",
+                "test/jalview/bin/argparser/testfiles/test2.stk",
+                "test/jalview/bin/argparser/testfiles/test3.stk",
+                "test/jalview/bin/argparser/testfiles/dir3/subdir/test0.stk",
+                "test/jalview/bin/argparser/testfiles/dir3/subdir/test1.stk",
+                "test/jalview/bin/argparser/testfiles/dir3/subdir/test2.stk",
+                "test/jalview/bin/argparser/testfiles/dir3/subdir/test3.stk", }, },
+        { "--open=test/jalview/bin/argparser/testfiles/dir1/*.fa --open=test/jalview/bin/argparser/testfiles/dir2/*.fa --output=open*.stk --close",
+            new String[]
+            { "test/jalview/bin/argparser/testfiles/dir2/test1.stk",
+                "test/jalview/bin/argparser/testfiles/dir2/test2.stk",
+                "test/jalview/bin/argparser/testfiles/dir2/test3.stk", },
+            new String[]
+            { "test/jalview/bin/argparser/testfiles/test1.stk",
+                "test/jalview/bin/argparser/testfiles/test2.stk",
+                "test/jalview/bin/argparser/testfiles/test3.stk",
+                "test/jalview/bin/argparser/testfiles/dir1/test1.stk",
+                "test/jalview/bin/argparser/testfiles/dir1/test2.stk",
+                "test/jalview/bin/argparser/testfiles/dir3/subdir/test0.stk",
+                "test/jalview/bin/argparser/testfiles/dir3/subdir/test1.stk",
+                "test/jalview/bin/argparser/testfiles/dir3/subdir/test2.stk",
+                "test/jalview/bin/argparser/testfiles/dir3/subdir/test3.stk", }, },
+        { "--open=test/jalview/bin/argparser/testfiles/dir1/*.fa --open=test/jalview/bin/argparser/testfiles/dir2/*.fa --opened --output={dirname}/{basename}.stk --close",
+            new String[]
+            { "test/jalview/bin/argparser/testfiles/dir2/test1.stk",
+                "test/jalview/bin/argparser/testfiles/dir2/test2.stk",
+                "test/jalview/bin/argparser/testfiles/dir2/test3.stk", },
+            new String[]
+            { "test/jalview/bin/argparser/testfiles/test1.stk",
+                "test/jalview/bin/argparser/testfiles/test2.stk",
+                "test/jalview/bin/argparser/testfiles/test3.stk",
+                "test/jalview/bin/argparser/testfiles/dir1/test1.stk",
+                "test/jalview/bin/argparser/testfiles/dir1/test2.stk",
+                "test/jalview/bin/argparser/testfiles/dir3/subdir/test0.stk",
+                "test/jalview/bin/argparser/testfiles/dir3/subdir/test1.stk",
+                "test/jalview/bin/argparser/testfiles/dir3/subdir/test2.stk",
+                "test/jalview/bin/argparser/testfiles/dir3/subdir/test3.stk", }, },
         //
     };
   }
         //
     };
   }
index 17f19b7..259acac 100644 (file)
@@ -273,7 +273,7 @@ public class ArgParserTest
 
   @Test(groups = "Functional", dataProvider = "allLinkedIdsData")
   public void allLinkedIdsTest(String commandLineArgs, Arg a,
 
   @Test(groups = "Functional", dataProvider = "allLinkedIdsData")
   public void allLinkedIdsTest(String commandLineArgs, Arg a,
-          String[] values)
+          String[] values, String[] nonvalues)
   {
     String[] args = commandLineArgs.split("\\s+");
     ArgParser argparser = new ArgParser(args);
   {
     String[] args = commandLineArgs.split("\\s+");
     ArgParser argparser = new ArgParser(args);
@@ -316,18 +316,20 @@ public class ArgParserTest
         */
         { "--open=test/jalview/bin/argparser/testfiles/*.fa --substitutions --all --image={dirname}/{basename}.png --close",
             Arg.CLOSE, new String[]
         */
         { "--open=test/jalview/bin/argparser/testfiles/*.fa --substitutions --all --image={dirname}/{basename}.png --close",
             Arg.CLOSE, new String[]
-            { null, null,
-                null } },
+            { null, null, null },
+            null },
         { "--open=test/jalview/bin/argparser/testfiles/*.fa --substitutions --all --output={dirname}/{basename}.stk --close",
             Arg.OUTPUT, new String[]
             { "test/jalview/bin/argparser/testfiles/test1.stk",
                 "test/jalview/bin/argparser/testfiles/test2.stk",
         { "--open=test/jalview/bin/argparser/testfiles/*.fa --substitutions --all --output={dirname}/{basename}.stk --close",
             Arg.OUTPUT, new String[]
             { "test/jalview/bin/argparser/testfiles/test1.stk",
                 "test/jalview/bin/argparser/testfiles/test2.stk",
-                "test/jalview/bin/argparser/testfiles/test3.stk", } },
+                "test/jalview/bin/argparser/testfiles/test3.stk", },
+            null },
         { "--open=test/jalview/bin/argparser/testfiles/*.fa --substitutions --all --image={dirname}/{basename}.png --close",
             Arg.IMAGE, new String[]
             { "test/jalview/bin/argparser/testfiles/test1.png",
                 "test/jalview/bin/argparser/testfiles/test2.png",
         { "--open=test/jalview/bin/argparser/testfiles/*.fa --substitutions --all --image={dirname}/{basename}.png --close",
             Arg.IMAGE, new String[]
             { "test/jalview/bin/argparser/testfiles/test1.png",
                 "test/jalview/bin/argparser/testfiles/test2.png",
-                "test/jalview/bin/argparser/testfiles/test3.png", } },
+                "test/jalview/bin/argparser/testfiles/test3.png", },
+            null },
         //
     };
   }
         //
     };
   }