Merge branch 'bug/JAL-4353_cannot_output_multiple_different_structure_images_for_one_...
[jalview.git] / src / jalview / bin / argparser / ArgValuesMap.java
index fc1e090..219983f 100644 (file)
@@ -22,8 +22,10 @@ package jalview.bin.argparser;
 
 import java.io.File;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -77,9 +79,13 @@ public class ArgValuesMap
   private void newArg(Arg a)
   {
     if (m == null)
+    {
       newMap();
+    }
     if (!containsArg(a))
-      m.put(a, new ArgValues(a));
+    {
+      m.put(a, new ArgValues(a, this));
+    }
   }
 
   public ArgValues getArgValues(Arg a)
@@ -101,6 +107,112 @@ public class ArgValuesMap
     return avs == null ? new ArrayList<>() : avs.getArgValueList();
   }
 
+  public List<ArgValue> getArgValueListFromSubValOrArg(ArgValue av, Arg a,
+          SubVals sv)
+  {
+    return getArgValueListFromSubValArgOrPrefWithSubstitutionsWithinTypes(
+            null, a, Position.AFTER, av, sv, null, null, null, true, null);
+  }
+
+  public List<ArgValue> getArgValueListFromSubValArgOrPrefWithSubstitutionsWithinTypes(
+          ArgParser ap, Arg a, ArgValuesMap.Position pos, ArgValue av,
+          SubVals sv, String key, String pref, String def,
+          boolean withinTypes, Type type)
+  {
+    if (key == null)
+    {
+      key = a.getName();
+    }
+    Set<Type> types = new HashSet<>();
+    if (type == null)
+    {
+      types.addAll(Arrays.asList(av.getArg().getTypes()));
+    }
+    else
+    {
+      types.add(type);
+    }
+    List<ArgValue> avList = new ArrayList<>();
+    if (sv != null && sv.has(key) && sv.get(key) != null)
+    {
+      String value = ap == null ? sv.get(key)
+              : sv.getWithSubstitutions(ap, getLinkedId(), key);
+      // protected ArgValue(Arg a, SubVals sv, Type type, String content, int
+      // argIndex)
+
+      ArgValue svav = new ArgValue(a, null, null, value, av.getArgIndex(),
+              false, null, this.getLinkedId());
+      avList.add(svav);
+    }
+    else if (containsArg(a))
+    {
+      if (pos == ArgValuesMap.Position.FIRST && getValue(a) != null)
+        avList.add(getArgValue(a));
+      else if (pos == ArgValuesMap.Position.BEFORE
+              && getClosestPreviousArgValueOfArg(av, a) != null)
+      {
+        for (ArgValue tmpAv : getArgValues(a).getArgValueList())
+        {
+          if (tmpAv.getArgIndex() >= av.getArgIndex())
+          {
+            continue;
+          }
+          avList.add(tmpAv);
+        }
+      }
+      else if (pos == ArgValuesMap.Position.AFTER
+              && getClosestNextArgValueOfArg(av, a, withinTypes) != null)
+      {
+        for (ArgValue tmpAv : getArgValues(a).getArgValueList())
+        {
+          if (tmpAv.getArgIndex() <= av.getArgIndex())
+          {
+            continue;
+          }
+          avList.add(tmpAv);
+        }
+      }
+    }
+
+    // check if withinType the avs don't belong to the next primary arg
+    // of this type. Checking for *any* shared type.
+    if (withinTypes && !avList.isEmpty())
+    {
+      int nextPrimaryArgOfSameTypeIndex = Integer.MAX_VALUE;
+      // run through every Arg used in this ArgValuesMap
+      for (Arg tmpA : this.getArgKeys())
+      {
+        // only interested in looking up to next Opt.PRIMARY args of the same
+        // type as av (or provided type)
+        if (tmpA.hasType(types) && tmpA.hasOption(Opt.PRIMARY))
+        {
+          for (ArgValue tmpAv : getArgValueList(tmpA))
+          {
+            int tmpArgIndex = tmpAv.getArgIndex();
+            if (tmpArgIndex > av.getArgIndex()
+                    && tmpArgIndex < nextPrimaryArgOfSameTypeIndex)
+            {
+              nextPrimaryArgOfSameTypeIndex = tmpArgIndex;
+            }
+          }
+        }
+      }
+      List<ArgValue> tmpList = new ArrayList<>();
+      for (ArgValue tmpAv : avList)
+      {
+        int tmpAvIndex = tmpAv.getArgIndex();
+        if (av.getArgIndex() < tmpAvIndex
+                && tmpAvIndex < nextPrimaryArgOfSameTypeIndex)
+        {
+          tmpList.add(tmpAv);
+        }
+      }
+      avList = tmpList;
+    }
+
+    return avList;
+  }
+
   public ArgValue getArgValue(Arg a)
   {
     List<ArgValue> vals = getArgValueList(a);
@@ -113,6 +225,25 @@ public class ArgValuesMap
     return av == null ? null : av.getValue();
   }
 
+  public List<String> getValues(Arg a)
+  {
+    return toValues(getArgValueList(a));
+  }
+
+  public static List<String> toValues(List<ArgValue> avl)
+  {
+    if (avl == null)
+    {
+      return null;
+    }
+    List<String> vl = new ArrayList<>();
+    for (ArgValue av : avl)
+    {
+      vl.add(av.getValue());
+    }
+    return vl;
+  }
+
   public boolean containsArg(Arg a)
   {
     if (m == null || !m.containsKey(a))
@@ -193,7 +324,7 @@ public class ArgValuesMap
   }
 
   public ArgValue getClosestNextArgValueOfArg(ArgValue thisAv, Arg a,
-          boolean withinType)
+          boolean withinTypes)
   {
     // this looks for the *next* arg that *might* be referring back to
     // a thisAv. Such an arg would have no subValues (if it does it should
@@ -215,14 +346,14 @@ public class ArgValuesMap
     }
 
     // check if withinType this closestAv doesn't belong to the next primary arg
-    // of this type
-    if (withinType && closestAv != null)
+    // of this type. Checking for *any* shared type.
+    if (withinTypes && closestAv != null)
     {
       int nextPrimaryArgOfSameTypeIndex = Integer.MAX_VALUE;
       for (Arg tmpA : this.getArgKeys())
       {
         // interested in Opt.PRIMARY args of the same type
-        if (tmpA.getType() == a.getType() && tmpA.hasOption(Opt.PRIMARY))
+        if (tmpA.sharesType(a) && tmpA.hasOption(Opt.PRIMARY))
         {
           for (ArgValue tmpAv : getArgValueList(tmpA))
           {
@@ -237,7 +368,7 @@ public class ArgValuesMap
       }
       if (nextPrimaryArgOfSameTypeIndex < closestAv.getArgIndex())
       {
-        // looks licke closestAv actually belongs to a different primary Arg
+        // looks like closestAv actually belongs to a different primary Arg
         return null;
       }
     }
@@ -370,33 +501,32 @@ public class ArgValuesMap
   public String getFromSubValArgOrPref(ArgValue av, Arg a, SubVals sv,
           String key, String pref, String def)
   {
-    return getFromSubValArgOrPref(a, ArgValuesMap.Position.AFTER, av, sv,
-            key, pref, def);
+    return getFromSubValArgOrPref(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 String getFromSubValArgOrPref(Arg a, ArgValuesMap.Position pos,
-          ArgValue av, SubVals sv, String key, String pref, String def)
+  public String getFromSubValArgOrPref(Arg a, Position pos, ArgValue av,
+          SubVals sv, String key, String pref, String def)
   {
     return getFromSubValArgOrPrefWithSubstitutions(null, a, pos, av, sv,
             key, pref, def);
   }
 
   public String getFromSubValArgOrPrefWithSubstitutions(ArgParser ap, Arg a,
-          ArgValuesMap.Position pos, ArgValue av, SubVals sv, String key,
-          String pref, String def)
+          Position pos, ArgValue av, SubVals sv, String key, String pref,
+          String def)
   {
-    return getFromSubValArgOrPrefWithSubstitutionsWithinType(ap, a, pos, av,
-            sv, key, pref, def, true);
+    return getFromSubValArgOrPrefWithSubstitutionsWithinTypes(ap, a, pos,
+            av, sv, key, pref, def, true);
   }
 
-  public String getFromSubValArgOrPrefWithSubstitutionsWithinType(
-          ArgParser ap, Arg a, ArgValuesMap.Position pos, ArgValue av,
-          SubVals sv, String key, String pref, String def,
-          boolean withinType)
+  public String getFromSubValArgOrPrefWithSubstitutionsWithinTypes(
+          ArgParser ap, Arg a, Position pos, ArgValue av, SubVals sv,
+          String key, String pref, String def, boolean withinTypes)
   {
     if (key == null)
       key = a.getName();
@@ -414,14 +544,14 @@ public class ArgValuesMap
               && getClosestPreviousArgValueOfArg(av, a) != null)
         value = getClosestPreviousArgValueOfArg(av, a).getValue();
       else if (pos == ArgValuesMap.Position.AFTER
-              && getClosestNextArgValueOfArg(av, a, withinType) != null)
-        value = getClosestNextArgValueOfArg(av, a, withinType).getValue();
+              && getClosestNextArgValueOfArg(av, a, withinTypes) != null)
+        value = getClosestNextArgValueOfArg(av, a, withinTypes).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
+              && arg.hasType(Type.STRUCTURE) && !a.hasOption(Opt.PRIMARY)
+              && (a.getFirstType() == Type.STRUCTURE
               // || a.getType() == Type.STRUCTUREIMAGE))
               ))
       {
@@ -432,6 +562,18 @@ public class ArgValuesMap
           value = av2.getValue();
         }
       }
+
+      if (value == null)
+      {
+        // look for --all --a occurrences
+        for (ArgValue tmpAv : this.getArgValueList(a))
+        {
+          if (tmpAv.setByWildcardLinkedId())
+          {
+            value = tmpAv.getValue();
+          }
+        }
+      }
     }
     if (value == null)
     {