JAL-4353 Preserve the user given 'linkedId' with ArgValue, to help with deciding...
[jalview.git] / src / jalview / bin / argparser / ArgParser.java
index fd42bb2..12e1b1d 100644 (file)
@@ -119,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;
@@ -278,9 +318,13 @@ public class ArgParser
     }
 
     if (bsa != null)
+    {
       this.bootstrapArgs = bsa;
+    }
     else
+    {
       this.bootstrapArgs = BootstrapArgs.getBootstrapArgs(args);
+    }
     parse(args, initsubstitutions, allowPrivate);
   }
 
@@ -321,6 +365,8 @@ public class ArgParser
         List<String> globVals = null; // for Opt.GLOB only
         SubVals globSubVals = null; // also for use by Opt.GLOB only
         String linkedId = null;
+        String givenLinkedId = null; // this is preserved to add to each
+                                     // "ArgValue"
         Type type = null;
 
         // look for equals e.g. --arg=value
@@ -341,6 +387,7 @@ public class ArgParser
         if (idOpen > -1 && idClose == argName.length() - 1)
         {
           linkedId = argName.substring(idOpen + 1, idClose);
+          givenLinkedId = linkedId;
           argName = argName.substring(0, idOpen);
         }
 
@@ -551,6 +598,12 @@ public class ArgParser
             {
               linkedId = MATCHALLLINKEDIDS;
             }
+            if (allLinkedIds)
+            {
+              // user has made conscious decision for these args to apply to
+              // all, so set givenLinkedId too
+              givenLinkedId = linkedId;
+            }
             else if (a.hasOption(Opt.ALLOWMULTIID)
                     && this.storedLinkedIds != null
                     && this.storedLinkedIds.size() > 0)
@@ -617,7 +670,7 @@ 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
+        if (allStructures && (a.hasType(Type.STRUCTURE)
         // || a.getType() == Type.STRUCTUREIMAGE)
         ) && !a.hasOption(Opt.PRIMARY))
         {
@@ -642,7 +695,8 @@ public class ArgParser
             {
               String v = gve.nextElement();
               SubVals vsv = new SubVals(globSubVals, v);
-              addValue(linkedId, type, avs, vsv, v, argIndex++, true);
+              addValue(linkedId, givenLinkedId, type, avs, vsv, v,
+                      argIndex++, true);
               // if we're using defaultLinkedId and the arg increments the
               // counter:
               if (gve.hasMoreElements() && usingDefaultLinkedId
@@ -659,18 +713,19 @@ public class ArgParser
           else
           {
             // addValue(linkedId, type, avs, val, argIndex, true);
-            addValue(linkedId, type, avs, addNewSubVals ? subvals : null,
-                    val, argIndex, true);
+            addValue(linkedId, givenLinkedId, type, avs,
+                    addNewSubVals ? subvals : null, val, argIndex, true);
           }
         }
         else if (a.hasOption(Opt.BOOLEAN))
         {
-          setBoolean(linkedId, type, avs, !negated, argIndex);
+          setBoolean(linkedId, givenLinkedId, type, avs, !negated,
+                  argIndex);
           setNegated(linkedId, avs, negated);
         }
         else if (a.hasOption(Opt.UNARY))
         {
-          setBoolean(linkedId, type, avs, true, argIndex);
+          setBoolean(linkedId, givenLinkedId, type, avs, true, argIndex);
         }
 
         // remove the '*' or 'open*' linkedId that should be empty if it was
@@ -724,6 +779,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;
 
@@ -743,14 +804,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)
     {
@@ -780,6 +847,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();
   }
@@ -973,30 +1066,30 @@ public class ArgParser
   /**
    * This version inserts the subvals sv into all created values
    */
-  private void addValue(String linkedId, Type type, ArgValues avs,
-          SubVals sv, String v, int argIndex, boolean doSubs)
+  private void addValue(String linkedId, String givenLinkedId, Type type,
+          ArgValues avs, SubVals sv, String v, int argIndex, boolean doSubs)
   {
-    this.argValueOperation(Op.ADDVALUE, linkedId, type, avs, sv, v, false,
-            argIndex, doSubs);
+    this.argValueOperation(Op.ADDVALUE, linkedId, givenLinkedId, type, avs,
+            sv, v, false, argIndex, doSubs);
   }
 
-  private void setBoolean(String linkedId, Type type, ArgValues avs,
-          boolean b, int argIndex)
+  private void setBoolean(String linkedId, String givenLinkedId, Type type,
+          ArgValues avs, boolean b, int argIndex)
   {
-    this.argValueOperation(Op.SETBOOLEAN, linkedId, type, avs, null, null,
-            b, argIndex, false);
+    this.argValueOperation(Op.SETBOOLEAN, linkedId, givenLinkedId, type,
+            avs, null, null, b, argIndex, false);
   }
 
   private void setNegated(String linkedId, ArgValues avs, boolean b)
   {
-    this.argValueOperation(Op.SETNEGATED, linkedId, null, avs, null, null,
-            b, 0, false);
+    this.argValueOperation(Op.SETNEGATED, linkedId, null, null, avs, null,
+            null, b, 0, false);
   }
 
   private void incrementCount(String linkedId, ArgValues avs)
   {
-    this.argValueOperation(Op.INCREMENTCOUNT, linkedId, null, avs, null,
-            null, false, 0, false);
+    this.argValueOperation(Op.INCREMENTCOUNT, linkedId, null, null, avs,
+            null, null, false, 0, false);
   }
 
   private enum Op
@@ -1004,13 +1097,13 @@ public class ArgParser
     ADDVALUE, SETBOOLEAN, SETNEGATED, INCREMENTCOUNT
   }
 
-  private void argValueOperation(Op op, String linkedId, Type type,
-          ArgValues avs, SubVals sv, String v, boolean b, int argIndex,
-          boolean doSubs)
+  private void argValueOperation(Op op, String linkedId,
+          String givenLinkedId, Type type, ArgValues avs, SubVals sv,
+          String v, boolean b, int argIndex, boolean doSubs)
   {
     // default to merge subvals if subvals are provided
-    argValueOperation(op, linkedId, type, avs, sv, true, v, b, argIndex,
-            doSubs);
+    argValueOperation(op, linkedId, givenLinkedId, type, avs, sv, true, v,
+            b, argIndex, doSubs);
   }
 
   /**
@@ -1040,9 +1133,9 @@ public class ArgParser
    * @param doSubs
    *          Whether to perform substitutions on the subvals and value.
    */
-  private void argValueOperation(Op op, String linkedId, Type type,
-          ArgValues avs, SubVals sv, boolean merge, String v, boolean b,
-          int argIndex, boolean doSubs)
+  private void argValueOperation(Op op, String linkedId,
+          String givenLinkedId, Type type, ArgValues avs, SubVals sv,
+          boolean merge, String v, boolean b, int argIndex, boolean doSubs)
   {
     Arg a = avs.arg();
 
@@ -1073,15 +1166,16 @@ public class ArgParser
     // linkedIds
     if (wildcardLinkedIds != null)
     {
-      for (String id : wildcardLinkedIds)
+      for (String matchedLinkedId : wildcardLinkedIds)
       {
         // skip incorrectly stored wildcard ids!
-        if (id == null || MATCHALLLINKEDIDS.equals(id)
-                || MATCHOPENEDLINKEDIDS.equals(id))
+        if (matchedLinkedId == null
+                || MATCHALLLINKEDIDS.equals(matchedLinkedId)
+                || MATCHOPENEDLINKEDIDS.equals(matchedLinkedId))
         {
           continue;
         }
-        ArgValuesMap avm = linkedArgs.get(id);
+        ArgValuesMap avm = linkedArgs.get(matchedLinkedId);
         // don't set an output if there isn't an input
         if (a.hasOption(Opt.REQUIREINPUT)
                 && !avm.hasArgWithOption(Opt.INPUT))
@@ -1098,24 +1192,24 @@ public class ArgParser
             if (doSubs)
             {
               sv = new SubVals(sv, val, merge);
-              val = makeSubstitutions(sv.getContent(), id);
+              val = makeSubstitutions(sv.getContent(), matchedLinkedId);
             }
-            tavs.addValue(sv, type, val, argIndex, true);
+            tavs.addValue(sv, type, val, argIndex, true, givenLinkedId);
           }
           else
           {
             if (doSubs)
             {
-              val = makeSubstitutions(v, id);
+              val = makeSubstitutions(v, matchedLinkedId);
             }
-            tavs.addValue(type, val, argIndex, true);
+            tavs.addValue(type, val, argIndex, true, givenLinkedId);
           }
-          finaliseStoringArgValue(id, tavs);
+          finaliseStoringArgValue(matchedLinkedId, tavs);
           break;
 
         case SETBOOLEAN:
-          tavs.setBoolean(type, b, argIndex, true);
-          finaliseStoringArgValue(id, tavs);
+          tavs.setBoolean(type, b, argIndex, true, givenLinkedId);
+          finaliseStoringArgValue(matchedLinkedId, tavs);
           break;
 
         case SETNEGATED:
@@ -1146,7 +1240,7 @@ public class ArgParser
             val = makeSubstitutions(v, linkedId);
             sv = new SubVals(sv, val);
           }
-          avs.addValue(sv, type, val, argIndex, false);
+          avs.addValue(sv, type, val, argIndex, false, givenLinkedId);
         }
         else
         {
@@ -1154,13 +1248,13 @@ public class ArgParser
           {
             val = makeSubstitutions(v, linkedId);
           }
-          avs.addValue(type, val, argIndex, false);
+          avs.addValue(type, val, argIndex, false, givenLinkedId);
         }
         finaliseStoringArgValue(linkedId, avs);
         break;
 
       case SETBOOLEAN:
-        avs.setBoolean(type, b, argIndex, false);
+        avs.setBoolean(type, b, argIndex, false, givenLinkedId);
         finaliseStoringArgValue(linkedId, avs);
         break;
 
@@ -1203,4 +1297,9 @@ public class ArgParser
     return mixedExamples;
   }
 
+  public void setStructureFilename(String s)
+  {
+    this.currentStructureFilename = s;
+  }
+
 }
\ No newline at end of file