JAL-3181 order link menu items
[jalview.git] / src / jalview / util / UrlLink.java
index 007da86..dda9e0e 100644 (file)
@@ -29,21 +29,63 @@ import jalview.datamodel.DBRefEntry;
 import jalview.datamodel.SequenceI;
 
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 import java.util.Vector;
 
+/**
+ * A helper class to parse URL Link strings taken from applet parameters or
+ * jalview properties file using the com.stevesoft.pat.Regex implementation.
+ * Jalview 2.4 extension allows regular expressions to be used to parse ID
+ * strings and replace the result in the URL. Regex's operate on the whole ID
+ * string given to the matchURL method, if no regex is supplied, then only text
+ * following the first pipe symbol will be substituted. Usage documentation
+ * todo.
+ */
 public class UrlLink
 {
   /**
-   * helper class to parse URL Link strings taken from applet parameters or
-   * jalview properties file using the com.stevesoft.pat.Regex implementation.
-   * Jalview 2.4 extension allows regular expressions to be used to parse ID
-   * strings and replace the result in the URL. Regex's operate on the whole ID
-   * string given to the matchURL method, if no regex is supplied, then only
-   * text following the first pipe symbol will be substituted. Usage
-   * documentation todo.
+   * A comparator that puts SEQUENCE_ID template links before DB_ACCESSION
+   * links, and otherwise orders by link name (not case sensitive). It expects
+   * to compare strings formatted as "Name|URLTemplate" where the template may
+   * include $SEQUENCE_ID$ or $DB_ACCESSION$ or neither.
    */
+  public static final Comparator<String> LINK_COMPARATOR = new Comparator<String>()
+  {
+    @Override
+    public int compare(String link1, String link2)
+    {
+      if (link1 == null || link2 == null)
+      {
+        return 0; // for failsafe only
+      }
+      String[] tokens1 = link1.split("\\|");
+      String[] tokens2 = link2.split("\\|");
+      if (tokens1.length < 2 || tokens2.length < 2)
+      {
+        // for failsafe only
+        return String.CASE_INSENSITIVE_ORDER.compare(link1, link2);
+      }
+      String name1 = tokens1[0];
+      String name2 = tokens2[0];
+      String pattern1 = tokens1[1];
+      String pattern2 = tokens2[1];
+      if (pattern1.contains(UrlConstants.SEQUENCE_ID)
+              && pattern2.contains(UrlConstants.DB_ACCESSION))
+      {
+        return -1;
+      }
+      if (pattern2.contains(UrlConstants.SEQUENCE_ID)
+              && pattern1.contains(UrlConstants.DB_ACCESSION))
+      {
+        return 1;
+      }
+      return String.CASE_INSENSITIVE_ORDER.compare(name1, name2);
+
+    }
+  };
 
   private static final String EQUALS = "=";
 
@@ -291,7 +333,7 @@ public class UrlLink
                       + rg.stringMatched(s) + "'");
             }
             // try to collate subgroup matches
-            Vector<String> subs = new Vector<String>();
+            Vector<String> subs = new Vector<>();
             // have to loop through submatches, collating them at top level
             // match
             int s = 0; // 1;
@@ -632,4 +674,20 @@ public class UrlLink
       }
     }
   }
+
+  /**
+   * Sorts links (formatted as LinkName|LinkPattern) suitable for display in a
+   * menu
+   * <ul>
+   * <li>SEQUENCE_ID links precede DB_ACCESSION links (i.e. canonical lookup
+   * before cross-references)</li>
+   * <li>otherwise by Link name (case insensitive)</li>
+   * </ul>
+   * 
+   * @param nlinks
+   */
+  public static void sort(List<String> nlinks)
+  {
+    Collections.sort(nlinks, LINK_COMPARATOR);
+  }
 }