JAL-4353 Add secondary Types for Args, for STRUCTUREIMAGE Type and restrict structure...
[jalview.git] / src / jalview / bin / argparser / ArgParser.java
index 6e53770..fe73053 100644 (file)
@@ -31,10 +31,8 @@ import java.util.EnumSet;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.List;
-import java.util.Locale;
 import java.util.Map;
 
-import jalview.bin.Cache;
 import jalview.bin.Console;
 import jalview.bin.Jalview;
 import jalview.bin.Jalview.ExitCode;
@@ -121,6 +119,46 @@ public class ArgParser
   private static final String LINKEDIDDIRNAME = "{dirname}";
 
   /**
+   * On-the-fly substitution (not made at argument parsing time)! the current
+   * structure filename extension
+   */
+  private static final String STRUCTUREEXTENSION = "{structureextension}";
+
+  /**
+   * On-the-fly substitution (not made at argument parsing time)! the current
+   * structure filename base
+   */
+  private static final String STRUCTUREBASENAME = "{structurebasename}";
+
+  /**
+   * On-the-fly substitution (not made at argument parsing time)! the current
+   * structure filename dir path
+   */
+  private static final String STRUCTUREDIRNAME = "{structuredirname}";
+
+  /**
+   * On-the-fly substitution (not made at argument parsing time)! increment the
+   * on-the-fly counter and substitute the incremented value
+   */
+  private static final String INCREMENTONTHEFLYCOUNTER = "{++m}";
+
+  /**
+   * On-the-fly substitution (not made at argument parsing time)! the current
+   * substitute with the on-the-fly counter
+   */
+  private static final String ONTHEFLYCOUNTER = "{m}";
+
+  /**
+   * the string used for on-the-fly structure filename substitutions
+   */
+  private String currentStructureFilename = null;
+
+  /**
+   * the counter used for on-the-fly {m} substitutions
+   */
+  private int ontheflyCounter = 0;
+
+  /**
    * the current argfile
    */
   private String argFile = null;
@@ -151,12 +189,6 @@ public class ArgParser
   private boolean allLinkedIds = false;
 
   /**
-   * flag to say whether the default linkedId is the current default linked id
-   * or OPENED linkedIds
-   */
-  private boolean openedLinkedIds = false;
-
-  /**
    * flag to say whether the structure arguments should be applied to all
    * structures with this linked id
    */
@@ -256,7 +288,8 @@ public class ArgParser
           mixedExamples[1] = arg;
         }
       }
-      else if (arg.startsWith("-") || arg.equals("open"))
+      else if ((arg.startsWith("-") && !arg.equals(STDOUTFILENAME))
+              || arg.equals("open"))
       {
         d = true;
         if (mixedExamples[0] == null)
@@ -285,9 +318,13 @@ public class ArgParser
     }
 
     if (bsa != null)
+    {
       this.bootstrapArgs = bsa;
+    }
     else
+    {
       this.bootstrapArgs = BootstrapArgs.getBootstrapArgs(args);
+    }
     parse(args, initsubstitutions, allowPrivate);
   }
 
@@ -516,12 +553,6 @@ public class ArgParser
         else if (a == Arg.ALL)
         {
           allLinkedIds = !negated;
-          openedLinkedIds = false;
-        }
-        else if (a == Arg.OPENED)
-        {
-          openedLinkedIds = !negated;
-          allLinkedIds = false;
         }
         else if (a == Arg.ALLSTRUCTURES)
         {
@@ -548,35 +579,25 @@ public class ArgParser
         {
           if (linkedId == null)
           {
-            if (a.hasOption(Opt.OUTPUTFILE) && a.hasOption(Opt.ALLOWALL)
-                    && val.startsWith(MATCHALLLINKEDIDS))
+            if (a.hasOption(Opt.OUTPUTFILE) && a.hasOption(Opt.ALLOWMULTIID)
+                    && val.contains(MATCHALLLINKEDIDS))
             {
-              // --output=*.ext is shorthand for --all --output {basename}.ext
+              // --output=*.ext is shorthand for --output {basename}.ext
+              // --output=*/*.ext is shorthand for
+              // --output {dirname}/{basename}.ext
               // (or --image=*.ext)
-              allLinkedIds = true;
-              openedLinkedIds = false;
-              linkedId = MATCHALLLINKEDIDS;
-              val = LINKEDIDDIRNAME + File.separator + LINKEDIDBASENAME
-                      + val.substring(MATCHALLLINKEDIDS.length());
+              linkedId = allLinkedIds ? MATCHALLLINKEDIDS
+                      : MATCHOPENEDLINKEDIDS;
+              val = FileUtils.convertWildcardsToPath(val, MATCHALLLINKEDIDS,
+                      LINKEDIDDIRNAME, LINKEDIDBASENAME);
             }
-            else if (a.hasOption(Opt.OUTPUTFILE)
-                    && 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))
+            else if (allLinkedIds && a.hasOption(Opt.ALLOWMULTIID))
             {
               linkedId = MATCHALLLINKEDIDS;
             }
-            else if (openedLinkedIds && a.hasOption(Opt.ALLOWALL))
+            else if (a.hasOption(Opt.ALLOWMULTIID)
+                    && this.storedLinkedIds != null
+                    && this.storedLinkedIds.size() > 0)
             {
               linkedId = MATCHOPENEDLINKEDIDS;
             }
@@ -640,10 +661,9 @@ public class ArgParser
 
         // set allstructures to all non-primary structure options in this linked
         // id if --allstructures has been set
-        if (allStructures
-                && (a.getType() == Type.STRUCTURE
-                        || a.getType() == Type.STRUCTUREIMAGE)
-                && !a.hasOption(Opt.PRIMARY))
+        if (allStructures && (a.hasType(Type.STRUCTURE)
+        // || a.getType() == Type.STRUCTUREIMAGE)
+        ) && !a.hasOption(Opt.PRIMARY))
         {
           if (!subvals.has(Arg.ALLSTRUCTURES.getName()))
           // && !subvals.has("structureid"))
@@ -700,9 +720,8 @@ public class ArgParser
         // remove the '*' or 'open*' linkedId that should be empty if it was
         // created
         if ((MATCHALLLINKEDIDS.equals(linkedId)
+                || MATCHOPENEDLINKEDIDS.equals(linkedId))
                 && linkedArgs.containsKey(linkedId))
-                || (MATCHOPENEDLINKEDIDS.equals(linkedId)
-                        && linkedArgs.containsKey(linkedId)))
         {
           linkedArgs.remove(linkedId);
         }
@@ -749,6 +768,12 @@ public class ArgParser
 
   public String makeSubstitutions(String val, String linkedId)
   {
+    return makeSubstitutions(val, linkedId, false);
+  }
+
+  public String makeSubstitutions(String val, String linkedId,
+          boolean onthefly)
+  {
     if (!this.substitutions || val == null)
       return val;
 
@@ -768,14 +793,20 @@ public class ArgParser
       rest = val;
     }
     if (rest.contains(LINKEDIDAUTOCOUNTER))
+    {
       rest = rest.replace(LINKEDIDAUTOCOUNTER,
               String.valueOf(linkedIdAutoCounter));
+    }
     if (rest.contains(INCREMENTLINKEDIDAUTOCOUNTER))
+    {
       rest = rest.replace(INCREMENTLINKEDIDAUTOCOUNTER,
               String.valueOf(++linkedIdAutoCounter));
+    }
     if (rest.contains(DEFAULTLINKEDIDCOUNTER))
+    {
       rest = rest.replace(DEFAULTLINKEDIDCOUNTER,
               String.valueOf(defaultLinkedIdCounter));
+    }
     ArgValuesMap avm = linkedArgs.get(linkedId);
     if (avm != null)
     {
@@ -805,6 +836,32 @@ public class ArgParser
                 FileUtils.getDirname(new File(argFile)));
       }
     }
+    if (onthefly)
+    {
+      if (rest.contains(ONTHEFLYCOUNTER))
+      {
+        rest = rest.replace(ONTHEFLYCOUNTER,
+                String.valueOf(ontheflyCounter));
+      }
+      if (rest.contains(INCREMENTONTHEFLYCOUNTER))
+      {
+        rest = rest.replace(INCREMENTONTHEFLYCOUNTER,
+                String.valueOf(++ontheflyCounter));
+      }
+      if (currentStructureFilename != null)
+      {
+        if (rest.contains(STRUCTUREBASENAME))
+        {
+          rest = rest.replace(STRUCTUREBASENAME, FileUtils
+                  .getBasename(new File(currentStructureFilename)));
+        }
+        if (rest.contains(STRUCTUREDIRNAME))
+        {
+          rest = rest.replace(STRUCTUREDIRNAME,
+                  FileUtils.getDirname(new File(currentStructureFilename)));
+        }
+      }
+    }
 
     return new StringBuilder(subvals).append(rest).toString();
   }
@@ -993,161 +1050,6 @@ public class ArgParser
     return args;
   }
 
-  public static enum Position
-  {
-    FIRST, BEFORE, AFTER
-  }
-
-  /**
-   * get from following Arg of type a or subval of same name (lowercase)
-   */
-  public static String getValueFromSubValOrArg(ArgValuesMap avm,
-          ArgValue av, Arg a, SubVals sv)
-  {
-    return getFromSubValArgOrPref(avm, av, a, sv, null, null, null);
-  }
-
-  /**
-   * get from following Arg of type a or subval key or preference pref or
-   * default def
-   */
-  public static String getFromSubValArgOrPref(ArgValuesMap avm, ArgValue av,
-          Arg a, SubVals sv, String key, String pref, String def)
-  {
-    return getFromSubValArgOrPref(avm, a, Position.AFTER, av, sv, key, pref,
-            def);
-  }
-
-  /**
-   * get from following(AFTER), first occurence of (FIRST) or previous (BEFORE)
-   * Arg of type a or subval key or preference pref or default def
-   */
-  public static String getFromSubValArgOrPref(ArgValuesMap avm, Arg a,
-          Position pos, ArgValue av, SubVals sv, String key, String pref,
-          String def)
-  {
-    return getFromSubValArgOrPrefWithSubstitutions(null, avm, a, pos, av,
-            sv, key, pref, def);
-  }
-
-  public static String getFromSubValArgOrPrefWithSubstitutions(ArgParser ap,
-          ArgValuesMap avm, Arg a, Position pos, ArgValue av, SubVals sv,
-          String key, String pref, String def)
-  {
-    if (key == null)
-      key = a.getName();
-    String value = null;
-    if (sv != null && sv.has(key) && sv.get(key) != null)
-    {
-      value = ap == null ? sv.get(key)
-              : sv.getWithSubstitutions(ap, avm.getLinkedId(), key);
-    }
-    else if (avm != null && avm.containsArg(a))
-    {
-      if (pos == Position.FIRST && avm.getValue(a) != null)
-        value = avm.getValue(a);
-      else if (pos == Position.BEFORE
-              && avm.getClosestPreviousArgValueOfArg(av, a) != null)
-        value = avm.getClosestPreviousArgValueOfArg(av, a).getValue();
-      else if (pos == Position.AFTER
-              && avm.getClosestNextArgValueOfArg(av, a) != null)
-        value = avm.getClosestNextArgValueOfArg(av, a).getValue();
-
-      // look for allstructures subval for Type.STRUCTURE*
-      Arg arg = av.getArg();
-      if (value == null && arg.hasOption(Opt.PRIMARY)
-              && arg.getType() == Type.STRUCTURE
-              && !a.hasOption(Opt.PRIMARY) && (a.getType() == Type.STRUCTURE
-                      || a.getType() == Type.STRUCTUREIMAGE))
-      {
-        ArgValue av2 = avm.getArgValueOfArgWithSubValKey(a,
-                Arg.ALLSTRUCTURES.getName());
-        if (av2 != null)
-        {
-          value = av2.getValue();
-        }
-      }
-    }
-    if (value == null)
-    {
-      value = pref != null ? Cache.getDefault(pref, def) : def;
-    }
-    return value;
-  }
-
-  public static boolean getBoolFromSubValOrArg(ArgValuesMap avm, Arg a,
-          SubVals sv)
-  {
-    return getFromSubValArgOrPref(avm, a, sv, null, null, false);
-  }
-
-  public static boolean getFromSubValArgOrPref(ArgValuesMap avm, Arg a,
-          SubVals sv, String key, String pref, boolean def)
-  {
-    return getFromSubValArgOrPref(avm, a, sv, key, pref, def, false);
-  }
-
-  public static boolean getFromSubValArgOrPref(ArgValuesMap avm, Arg a,
-          SubVals sv, String key, String pref, boolean def,
-          boolean invertPref)
-  {
-    if ((key == null && a == null) || (sv == null && a == null))
-      return false;
-
-    boolean usingArgKey = false;
-    if (key == null)
-    {
-      key = a.getName();
-      usingArgKey = true;
-    }
-
-    String nokey = ArgParser.NEGATESTRING + key;
-
-    // look for key or nokey in subvals first (if using Arg check options)
-    if (sv != null)
-    {
-      // check for true boolean
-      if (sv.has(key) && sv.get(key) != null)
-      {
-        if (usingArgKey)
-        {
-          if (!(a.hasOption(Opt.BOOLEAN) || a.hasOption(Opt.UNARY)))
-          {
-            Console.debug(
-                    "Looking for boolean in subval from non-boolean/non-unary Arg "
-                            + a.getName());
-            return false;
-          }
-        }
-        return sv.get(key).toLowerCase(Locale.ROOT).equals("true");
-      }
-
-      // check for negative boolean (subval "no..." will be "true")
-      if (sv.has(nokey) && sv.get(nokey) != null)
-      {
-        if (usingArgKey)
-        {
-          if (!(a.hasOption(Opt.BOOLEAN)))
-          {
-            Console.debug(
-                    "Looking for negative boolean in subval from non-boolean Arg "
-                            + a.getName());
-            return false;
-          }
-        }
-        return !sv.get(nokey).toLowerCase(Locale.ROOT).equals("true");
-      }
-    }
-
-    // check argvalues
-    if (avm != null && avm.containsArg(a))
-      return avm.getBoolean(a);
-
-    // return preference or default
-    boolean prefVal = pref != null ? Cache.getDefault(pref, def) : false;
-    return pref != null ? (invertPref ? !prefVal : prefVal) : def;
-  }
-
   // the following methods look for the "*" linkedId and add the argvalue to all
   // linkedId ArgValues if it does.
   /**
@@ -1160,13 +1062,6 @@ public class ArgParser
             argIndex, doSubs);
   }
 
-  private void addValue(String linkedId, Type type, ArgValues avs, String v,
-          int argIndex, boolean doSubs)
-  {
-    this.argValueOperation(Op.ADDVALUE, linkedId, type, avs, null, v, false,
-            argIndex, doSubs);
-  }
-
   private void setBoolean(String linkedId, Type type, ArgValues avs,
           boolean b, int argIndex)
   {
@@ -1234,7 +1129,7 @@ public class ArgParser
     Arg a = avs.arg();
 
     List<String> wildcardLinkedIds = null;
-    if (a.hasOption(Opt.ALLOWALL))
+    if (a.hasOption(Opt.ALLOWMULTIID))
     {
       switch (linkedId)
       {
@@ -1265,7 +1160,9 @@ public class ArgParser
         // 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)
@@ -1387,4 +1284,10 @@ public class ArgParser
   {
     return mixedExamples;
   }
+
+  public void setStructureFilename(String s)
+  {
+    this.currentStructureFilename = s;
+  }
+
 }
\ No newline at end of file