Merge remote-tracking branch 'origin/bug/JAL-2282' into develop
authorkiramt <k.mourao@dundee.ac.uk>
Wed, 2 Nov 2016 16:19:54 +0000 (16:19 +0000)
committerkiramt <k.mourao@dundee.ac.uk>
Wed, 2 Nov 2016 16:19:54 +0000 (16:19 +0000)
15 files changed:
help/html/webServices/urllinks.html
resources/lang/Messages.properties
resources/lang/Messages_es.properties
src/jalview/appletgui/APopupMenu.java
src/jalview/appletgui/IdPanel.java
src/jalview/gui/Desktop.java
src/jalview/gui/IdPanel.java
src/jalview/gui/PopupMenu.java
src/jalview/gui/Preferences.java
src/jalview/io/SequenceAnnotationReport.java
src/jalview/util/DBRefUtils.java
src/jalview/util/UrlConstants.java
src/jalview/util/UrlLink.java
test/jalview/gui/PopupMenuTest.java
test/jalview/util/UrlLinkTest.java

index 0a4c650..1a1f0d0 100644 (file)
@@ -28,7 +28,7 @@
     and the desktop application are able to open URLs as 'popups' in
     your web browser. <br> Double-clicking on the ID of a sequence
     will open the first URL that can be generated from its sequence ID.
-    This is often the SRS site, but you can easily configure your own <a
+    This is by default the EMBL-EBI site, but you can easily configure your own <a
       href="#urllinks">sequence URL links</a>.
   </p>
   <p>
   <p>
     <strong><a name="urllinks">Configuring URL Links</a></strong> <br>URL
     links are defined in the &quot;Connections&quot; tab of the <a
-      href="../features/preferences.html">Jalview desktop
-      preferences</a>, or specified as <a
-      href="http://www.jalview.org/examples/appletParameters.html#parameters">applet
-      parameters</a>. <br> By default the item &quot;SRS&quot; is added
+    href="../features/preferences.html">Jalview desktop
+    preferences</a>, or specified as <a
+    href="http://www.jalview.org/examples/appletParameters.html#parameters">applet
+    parameters</a>. <br> By default the item &quot;EMBL-EBI Search&quot; is added
     to this link menu. This link will show a web page in your default
     browser with the selected sequence id as part of the URL.<br>
     In the preferences dialog box, click <strong>new</strong> to add a
@@ -51,9 +51,9 @@
     to remove it.<br> You can name the link, this will be displayed
     on a new menu item under the &quot;Link&quot; menu when you right
     click on a sequence id. <br> The URL string must contain a
-    token that can be replaced with a sequence ID. The simplest token is
+    token that can be replaced with a sequence ID or DB accession ID. The simplest token is
     &quot;$SEQUENCE_ID$&quot;, which will be replaced by the chosen
-    sequence id when you click on it.
+    sequence id when you click on it. 
   </p>
   <p>
     eg.<br> UniRef100 =
     Swissprot = http://www.expasy.org/uniprot/$SEQUENCE_ID$ <br> <br>
     Links will also be made for any database cross references associated
     with the sequence where the database name exactly matches a URL link
-    name. In this case, the $SEQUENCE_ID$ string will be replaced with
+    name. In this case, the $DB_ACCESSION$ string will be replaced with
     the accession string for the database cross-reference, rather than
-    the sequence ID for the sequence (<em>since Jalview 2.4</em>).
+    the sequence ID for the sequence (<em>since Jalview 2.10.1</em>).
   </p>
   <p>
     <strong>Regular Expression Substitution</strong><br> A url may
     contain a string of the form $SEQUENCE_ID=/<em>regular
-      expression</em>/=$. In this case, the regular expression will be
-    applied to the full sequence ID string and the resulting match will
+    expression</em>/=$ or $DB_ACCESSION=/<em>regular expression</em>/=$. 
+    In this case, the regular expression will be
+    applied to the full sequence ID or DB accession ID string and the resulting match will
     be inserted into the URL. Groups of parentheses can be used to
     specify which regions of the regular expression will be used to
     generate the URL:
index 864e34a..d8c9ad3 100644 (file)
@@ -787,9 +787,9 @@ label.hide_columns_containing = Hide columns containing
 label.hide_columns_not_containing = Hide columns that do not contain
 option.trim_retrieved_seqs = Trim retrieved sequences
 label.trim_retrieved_sequences = When the reference sequence is longer than the sequence that you are working with, only keep the relevant subsequences.
-label.use_sequence_id_1 = Use $SEQUENCE_ID$ or $SEQUENCE_ID=/<regex>/=$
-label.use_sequence_id_2 = to embed sequence id in URL
-label.use_sequence_id_3 = Use $SEQUENCE_NAME$ similarly to embed sequence name
+label.use_sequence_id_1 = Use $DB_ACCESSION$ or $DB_ACCESSION=/<regex>/=$
+label.use_sequence_id_2 = to embed accession id in URL
+label.use_sequence_id_3 = Use $SEQUENCE_ID$ similarly to embed sequence id
 label.use_sequence_id_4 = 
 label.ws_parameters_for = Parameters for {0}
 label.switch_server = Switch server
@@ -1268,3 +1268,7 @@ status.exporting_alignment_as_x_file = Exporting alignment as {0} file
 label.column = Column
 label.cant_map_cds = Unable to map CDS to protein\nCDS missing or incomplete
 label.operation_failed = Operation failed
+label.SEQUENCE_ID_no_longer_used = $SEQUENCE_ID$ is no longer used for DB accessions
+label.SEQUENCE_ID_for_DB_ACCESSION1 = Please review your URL links in the 'Connections' tab of the Preferences window:
+label.SEQUENCE_ID_for_DB_ACCESSION2 = URL links using '$SEQUENCE_ID$' for DB accessions now use '$DB_ACCESSION$'.
+label.do_not_display_again = Do not display this message again
index 754d94d..4f142b6 100644 (file)
@@ -720,10 +720,10 @@ label.select_columns_containing = Seleccione las columnas que contengan
 label.select_columns_not_containing = Seleccione las columnas que no contengan
 option.trim_retrieved_seqs = Ajustar las secuencias recuperadas
 label.trim_retrieved_sequences = Cuando la secuencia de referencia es más larga que la secuencia con la que está trabajando, sólo se mantienen las subsecuencias relevantes.
-label.use_sequence_id_1 = Utilice $SEQUENCE_ID$ o $SEQUENCE_ID=/<regex>/=$
-label.use_sequence_id_2 = para embeber el id de la secuencia en una URL
-label.use_sequence_id_3 = Utilice $SEQUENCE_NAME$ de manera similar para embeber
-label.use_sequence_id_4 = el nombre de la secuencia
+label.use_sequence_id_1 = Utilice $DB_ACCESSION$ o $DB_ACCESSION=/<regex>/=$
+label.use_sequence_id_2 = para embeber el ID de accesión en una URL
+label.use_sequence_id_3 = Utilice $SEQUENCE_ID$ de manera similar para embeber
+label.use_sequence_id_4 = el ID de la secuencia
 label.ws_parameters_for = Parámetros para {0}
 label.switch_server = Cambiar servidor
 label.open_jabaws_web_page = Abra el página principal del servidor JABAWS en un navegador web
@@ -1269,3 +1269,7 @@ status.exporting_alignment_as_x_file = Exportando alineamiento como fichero tipo
 label.column = Columna
 label.cant_map_cds = No se pudo mapear CDS a proteína\nDatos CDS faltantes o incompletos
 label.operation_failed = Operación fallada
+label.SEQUENCE_ID_no_longer_used = $SEQUENCE_ID$ no se utiliza más para accesiones DB
+label.SEQUENCE_ID_for_DB_ACCESSION1 = Por favor, revise sus URLs en la pestaña 'Conexiones' de la ventana de Preferencias:
+label.SEQUENCE_ID_for_DB_ACCESSION2 = URL enlaza usando '$SEQUENCE_ID$' para accesiones DB ahora usar '$DB_ACCESSION$'.
+label.do_not_display_again = No mostrar este mensaje de nuevo
\ No newline at end of file
index 7b0d4fb..d625f78 100644 (file)
@@ -24,12 +24,12 @@ import jalview.analysis.AAFrequency;
 import jalview.analysis.AlignmentAnnotationUtils;
 import jalview.analysis.AlignmentUtils;
 import jalview.analysis.Conservation;
+import jalview.bin.Cache;
 import jalview.commands.ChangeCaseCommand;
 import jalview.commands.EditCommand;
 import jalview.commands.EditCommand.Action;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
-import jalview.datamodel.DBRefEntry;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
@@ -59,6 +59,7 @@ import java.awt.event.ActionListener;
 import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -253,122 +254,9 @@ public class APopupMenu extends java.awt.PopupMenu implements
 
     if (links != null && links.size() > 0)
     {
-      Menu linkMenu = new Menu(MessageManager.getString("action.link"));
-      for (int i = 0; i < links.size(); i++)
-      {
-        String link = links.elementAt(i);
-        UrlLink urlLink = new UrlLink(link);
-        if (!urlLink.isValid())
-        {
-          System.err.println(urlLink.getInvalidMessage());
-          continue;
-        }
-        final String target = urlLink.getTarget(); // link.substring(0,
-        // link.indexOf("|"));
-        final String label = urlLink.getLabel();
-        if (seq != null && urlLink.isDynamic())
-        {
-
-          // collect matching db-refs
-          DBRefEntry[] dbr = jalview.util.DBRefUtils.selectRefs(
-                  seq.getDBRefs(), new String[] { target });
-          // collect id string too
-          String id = seq.getName();
-          String descr = seq.getDescription();
-          if (descr != null && descr.length() < 1)
-          {
-            descr = null;
-          }
-          if (dbr != null)
-          {
-            for (int r = 0; r < dbr.length; r++)
-            {
-              if (id != null && dbr[r].getAccessionId().equals(id))
-              {
-                // suppress duplicate link creation for the bare sequence ID
-                // string with this link
-                id = null;
-              }
-              // create Bare ID link for this RUL
-              String[] urls = urlLink.makeUrls(dbr[r].getAccessionId(),
-                      true);
-              if (urls != null)
-              {
-                for (int u = 0; u < urls.length; u += 2)
-                {
-                  addshowLink(linkMenu, label + "|" + urls[u], urls[u + 1]);
-                }
-              }
-            }
-          }
-          if (id != null)
-          {
-            // create Bare ID link for this RUL
-            String[] urls = urlLink.makeUrls(id, true);
-            if (urls != null)
-            {
-              for (int u = 0; u < urls.length; u += 2)
-              {
-                addshowLink(linkMenu, label, urls[u + 1]);
-              }
-            }
-            // addshowLink(linkMenu, target, url_pref + id + url_suff);
-          }
-          // Now construct URLs from description but only try to do it for regex
-          // URL links
-          if (descr != null && urlLink.getRegexReplace() != null)
-          {
-            // create link for this URL from description only if regex matches
-            String[] urls = urlLink.makeUrls(descr, true);
-            if (urls != null)
-            {
-              for (int u = 0; u < urls.length; u += 2)
-              {
-                addshowLink(linkMenu, label, urls[u + 1]);
-              }
-            }
-          }
-        }
-        else
-        {
-          addshowLink(linkMenu, target, urlLink.getUrl_prefix()); // link.substring(link.lastIndexOf("|")+1));
-        }
-        /*
-         * final String url;
-         * 
-         * if (link.indexOf("$SEQUENCE_ID$") > -1) { // Substitute SEQUENCE_ID
-         * string and any matching database reference accessions String url_pref
-         * = link.substring(link.indexOf("|") + 1,
-         * link.indexOf("$SEQUENCE_ID$"));
-         * 
-         * String url_suff = link.substring(link.indexOf("$SEQUENCE_ID$") + 13);
-         * // collect matching db-refs DBRefEntry[] dbr =
-         * jalview.util.DBRefUtils.selectRefs(seq.getDBRef(), new
-         * String[]{target}); // collect id string too String id =
-         * seq.getName(); if (id.indexOf("|") > -1) { id =
-         * id.substring(id.lastIndexOf("|") + 1); } if (dbr!=null) { for (int
-         * r=0;r<dbr.length; r++) { if (dbr[r].getAccessionId().equals(id)) { //
-         * suppress duplicate link creation for the bare sequence ID string with
-         * this link id = null; } addshowLink(linkMenu,
-         * dbr[r].getSource()+"|"+dbr[r].getAccessionId(), target,
-         * url_pref+dbr[r].getAccessionId()+url_suff); } } if (id!=null) { //
-         * create Bare ID link for this RUL addshowLink(linkMenu, target,
-         * url_pref + id + url_suff); } } else { addshowLink(linkMenu, target,
-         * link.substring(link.lastIndexOf("|")+1)); }
-         */
-      }
-      if (linkMenu.getItemCount() > 0)
-      {
-        if (seq != null)
-        {
-          seqMenu.add(linkMenu);
-        }
-        else
-        {
-          add(linkMenu);
-        }
-      }
+      addFeatureLinks(seq, links);
     }
+
     // TODO: add group link menu entry here
     if (seq != null)
     {
@@ -414,6 +302,62 @@ public class APopupMenu extends java.awt.PopupMenu implements
   }
 
   /**
+   * Adds a 'Link' menu item with a sub-menu item for each hyperlink provided.
+   * 
+   * @param seq
+   * @param links
+   */
+  void addFeatureLinks(final SequenceI seq, List<String> links)
+  {
+    Menu linkMenu = new Menu(MessageManager.getString("action.link"));
+    Map<String, List<String>> linkset = new LinkedHashMap<String, List<String>>();
+
+    for (String link : links)
+    {
+      UrlLink urlLink = null;
+      try
+      {
+        urlLink = new UrlLink(link);
+      } catch (Exception foo)
+      {
+        Cache.log.error("Exception for URLLink '" + link + "'", foo);
+        continue;
+      }
+
+      if (!urlLink.isValid())
+      {
+        Cache.log.error(urlLink.getInvalidMessage());
+        continue;
+      }
+
+      urlLink.createLinksFromSeq(seq, linkset);
+    }
+
+    addshowLinks(linkMenu, linkset.values());
+
+    if (linkMenu.getItemCount() > 0)
+    {
+      if (seq != null)
+      {
+        seqMenu.add(linkMenu);
+      }
+      else
+      {
+        add(linkMenu);
+      }
+    }
+  }
+
+  private void addshowLinks(Menu linkMenu, Collection<List<String>> linkset)
+  {
+    for (List<String> linkstrset : linkset)
+    {
+      // split linkstr into label and url
+      addshowLink(linkMenu, linkstrset.get(1), linkstrset.get(3));
+    }
+  }
+
+  /**
    * Build menus for annotation types that may be shown or hidden, and for
    * 'reference annotations' that may be added to the alignment.
    */
index 2cb3060..182f20e 100755 (executable)
@@ -246,7 +246,14 @@ public class IdPanel extends Panel implements MouseListener,
         url = null;
         continue;
       }
-      ;
+
+      if (urlLink.usesDBAccession())
+      {
+        // this URL requires an accession id, not the name of a sequence
+        url = null;
+        continue;
+      }
+
       if (!urlLink.isValid())
       {
         System.err.println(urlLink.getInvalidMessage());
index 3f457ea..b1b913b 100644 (file)
@@ -82,9 +82,12 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.Semaphore;
 
 import javax.swing.AbstractAction;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
 import javax.swing.DefaultDesktopManager;
 import javax.swing.DesktopManager;
 import javax.swing.JButton;
+import javax.swing.JCheckBox;
 import javax.swing.JComboBox;
 import javax.swing.JComponent;
 import javax.swing.JDesktopPane;
@@ -382,6 +385,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
 
     showNews.setVisible(false);
 
+    checkURLLinks();
+
     this.addWindowListener(new WindowAdapter()
     {
       @Override
@@ -2256,6 +2261,55 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     new Thread(jvq).start();
   }
 
+  public void checkURLLinks()
+  {
+    // Thread off the URL link checker
+    addDialogThread(new Runnable()
+    {
+      @Override
+      public void run()
+      {
+        if (Cache.getDefault("CHECKURLLINKS", true))
+        {
+          // check in case URL links use old style tokens ($SEQUENCE_ID$ for
+          // sequence id _or_ accession id)
+          JPanel msgPanel = new JPanel();
+          msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.PAGE_AXIS));
+          msgPanel.add(Box.createVerticalGlue());
+          JLabel msg = new JLabel(
+                  MessageManager
+                          .getString("label.SEQUENCE_ID_for_DB_ACCESSION1"));
+          JLabel msg2 = new JLabel(
+                  MessageManager
+                          .getString("label.SEQUENCE_ID_for_DB_ACCESSION2"));
+          msgPanel.add(msg);
+          msgPanel.add(msg2);
+
+          final JCheckBox jcb = new JCheckBox(
+                  MessageManager.getString("label.do_not_display_again"));
+          jcb.addActionListener(new ActionListener()
+          {
+
+            @Override
+            public void actionPerformed(ActionEvent e)
+            {
+              // update Cache settings if checkbox is selected
+              if (jcb.isSelected())
+              {
+                Cache.setProperty("CHECKURLLINKS", "false");
+              }
+            }
+          });
+          msgPanel.add(jcb);
+
+          JOptionPane.showMessageDialog(null, msgPanel, MessageManager
+                  .getString("label.SEQUENCE_ID_no_longer_used"),
+                  JOptionPane.WARNING_MESSAGE);
+        }
+      }
+    });
+    }
+
   /**
    * Proxy class for JDesktopPane which optionally displays the current memory
    * usage and highlights the desktop area with a red bar if free memory runs
index a65be7b..e321a74 100755 (executable)
@@ -225,7 +225,14 @@ public class IdPanel extends JPanel implements MouseListener,
         url = null;
         continue;
       }
-      ;
+
+      if (urlLink.usesDBAccession())
+      {
+        // this URL requires an accession id, not the name of a sequence
+        url = null;
+        continue;
+      }
+
       if (!urlLink.isValid())
       {
         jalview.bin.Cache.log.error(urlLink.getInvalidMessage());
index 7b70ff0..b342f86 100644 (file)
@@ -54,7 +54,6 @@ import jalview.schemes.TaylorColourScheme;
 import jalview.schemes.TurnColourScheme;
 import jalview.schemes.UserColourScheme;
 import jalview.schemes.ZappoColourScheme;
-import jalview.util.DBRefUtils;
 import jalview.util.GroupUrlLink;
 import jalview.util.GroupUrlLink.UrlStringTooLongException;
 import jalview.util.MessageManager;
@@ -63,8 +62,8 @@ import jalview.util.UrlLink;
 import java.awt.Color;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Hashtable;
 import java.util.LinkedHashMap;
@@ -617,7 +616,8 @@ public class PopupMenu extends JPopupMenu
   void addFeatureLinks(final SequenceI seq, List<String> links)
   {
     JMenu linkMenu = new JMenu(MessageManager.getString("action.link"));
-    List<String> linkset = new ArrayList<String>();
+    Map<String, List<String>> linkset = new LinkedHashMap<String, List<String>>();
+
     for (String link : links)
     {
       UrlLink urlLink = null;
@@ -629,80 +629,18 @@ public class PopupMenu extends JPopupMenu
         Cache.log.error("Exception for URLLink '" + link + "'", foo);
         continue;
       }
-      ;
+
       if (!urlLink.isValid())
       {
         Cache.log.error(urlLink.getInvalidMessage());
         continue;
       }
-      final String label = urlLink.getLabel();
-
-      // collect id string too
-      String id = seq.getName();
-      String descr = seq.getDescription();
-      if (descr != null && descr.length() < 1)
-      {
-        descr = null;
-      }
-
-      if (seq != null && urlLink.usesSeqId()) // link is ID
-      {
-        // collect matching db-refs
-        DBRefEntry[] dbr = DBRefUtils.selectRefs(seq.getDBRefs(),
-                new String[] { urlLink.getTarget() });
-
-        // if there are any dbrefs which match up with the link
-        if (dbr != null)
-        {
-          for (int r = 0; r < dbr.length; r++)
-          {
-            if (id != null && dbr[r].getAccessionId().equals(id))
-            {
-              // suppress duplicate link creation for the bare sequence ID
-              // string with this link
-              id = null;
-            }
-            // create Bare ID link for this URL
-            createBareURLLink(urlLink, dbr[r].getAccessionId(), linkset,
-                    linkMenu, label, true);
-          }
-        }
 
-        // Create urls from description but only for URL links which are regex
-        // links
-        if (descr != null && urlLink.getRegexReplace() != null)
-        {
-          // create link for this URL from description where regex matches
-          createBareURLLink(urlLink, descr, linkset, linkMenu, label, false);
-        }
+      urlLink.createLinksFromSeq(seq, linkset);
+    }
 
-      }
-      else if (seq != null && !urlLink.usesSeqId()) // link is name
-      {
-        if (id != null)
-        {
-          // create Bare ID link for this URL
-          createBareURLLink(urlLink, id, linkset, linkMenu, label, false);
-        }
-        // Create urls from description but only for URL links which are regex
-        // links
-        if (descr != null && urlLink.getRegexReplace() != null)
-        {
-          // create link for this URL from description where regex matches
-          createBareURLLink(urlLink, descr, linkset, linkMenu, label, false);
-        }
-      }
-      else
-      {
-        if (!linkset.contains(label + "|" + urlLink.getUrl_prefix()))
-        {
-          linkset.add(label + "|" + urlLink.getUrl_prefix());
-          // Add a non-dynamic link
-          addshowLink(linkMenu, label, urlLink.getUrl_prefix());
-        }
-      }
+    addshowLinks(linkMenu, linkset.values());
 
-    }
     if (sequence != null)
     {
       sequenceMenu.add(linkMenu);
@@ -713,33 +651,7 @@ public class PopupMenu extends JPopupMenu
     }
   }
 
-  /*
-   * Create a bare URL Link
-   */
-  private void createBareURLLink(UrlLink urlLink, String id,
-          List<String> linkset, JMenu linkMenu, String label,
-          Boolean addSepToLabel)
-  {
-    String[] urls = urlLink.makeUrls(id, true);
-    if (urls != null)
-    {
-      for (int u = 0; u < urls.length; u += 2)
-      {
-        if (!linkset.contains(urls[u] + "|" + urls[u + 1]))
-        {
-          linkset.add(urls[u] + "|" + urls[u + 1]);
-          if (addSepToLabel)
-          {
-            addshowLink(linkMenu, label + "|" + urls[u], urls[u + 1]);
-          }
-          else
-          {
-            addshowLink(linkMenu, label, urls[u + 1]);
-          }
-        }
-      }
-    }
-  }
+
 
   /**
    * Add annotation types to 'Show annotations' and/or 'Hide annotations' menus.
@@ -1015,6 +927,15 @@ public class PopupMenu extends JPopupMenu
     }
   }
 
+  private void addshowLinks(JMenu linkMenu, Collection<List<String>> linkset)
+  {
+    for (List<String> linkstrset : linkset)
+    {
+      // split linkstr into label and url
+      addshowLink(linkMenu, linkstrset.get(1), linkstrset.get(3));
+    }
+  }
+
   /**
    * add a show URL menu item to the given linkMenu
    * 
index b57b951..4f094e1 100755 (executable)
@@ -21,9 +21,8 @@
 package jalview.gui;
 
 import static jalview.util.UrlConstants.EMBLEBI_STRING;
-import static jalview.util.UrlConstants.OLD_EMBLEBI_STRING;
+import static jalview.util.UrlConstants.DB_ACCESSION;
 import static jalview.util.UrlConstants.SEQUENCE_ID;
-import static jalview.util.UrlConstants.SEQUENCE_NAME;
 import static jalview.util.UrlConstants.SRS_STRING;
 
 import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
@@ -127,10 +126,10 @@ public class Preferences extends GPreferences
         String name = st.nextToken();
         String url = st.nextToken();
         // check for '|' within a regex
-        int rxstart = url.indexOf("$" + SEQUENCE_ID + "$");
+        int rxstart = url.indexOf("$" + DB_ACCESSION + "$");
         if (rxstart == -1)
         {
-          rxstart = url.indexOf("$" + SEQUENCE_NAME + "$");
+          rxstart = url.indexOf("$" + SEQUENCE_ID + "$");
         }
         while (rxstart == -1 && url.indexOf("/=$") == -1)
         {
@@ -149,12 +148,6 @@ public class Preferences extends GPreferences
       {
         sequenceURLLinks.setElementAt(EMBLEBI_STRING, srsPos);
       }
-      // upgrade old EMBL-EBI link
-      int emblPos = sequenceURLLinks.indexOf(OLD_EMBLEBI_STRING);
-      if (emblPos > -1)
-      {
-        sequenceURLLinks.setElementAt(EMBLEBI_STRING, emblPos);
-      }
     }
 
     /**
index 07b88bf..89f1068 100644 (file)
@@ -24,10 +24,11 @@ import jalview.datamodel.DBRefEntry;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.io.gff.GffConstants;
-import jalview.util.DBRefUtils;
 import jalview.util.UrlLink;
 
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -206,16 +207,17 @@ public class SequenceAnnotationReport
         {
           try
           {
-            for (String[] urllink : createLinksFrom(null, urlstring))
+            for (List<String> urllink : createLinksFrom(null, urlstring))
             {
               sb.append("<br/> <a href=\""
-                      + urllink[3]
+                      + urllink.get(3)
                       + "\" target=\""
-                      + urllink[0]
+                      + urllink.get(0)
                       + "\">"
-                      + (urllink[0].toLowerCase().equals(
-                              urllink[1].toLowerCase()) ? urllink[0]
-                              : (urllink[0] + ":" + urllink[1]))
+                      + (urllink.get(0).toLowerCase()
+                              .equals(urllink.get(1).toLowerCase()) ? urllink
+                              .get(0) : (urllink.get(0) + ":" + urllink
+                              .get(1)))
                       + "</a></br>");
             }
           } catch (Exception x)
@@ -234,124 +236,22 @@ public class SequenceAnnotationReport
    * 
    * @param seq
    * @param link
-   * @return String[][] { String[] { link target, link label, dynamic component
-   *         inserted (if any), url }}
+   * @return Collection< List<String> > { List<String> { link target, link
+   *         label, dynamic component inserted (if any), url }}
    */
-  String[][] createLinksFrom(SequenceI seq, String link)
+  Collection<List<String>> createLinksFrom(SequenceI seq, String link)
   {
-    List<String[]> urlSets = new ArrayList<String[]>();
-    List<String> uniques = new ArrayList<String>();
+    Map<String, List<String>> urlSets = new LinkedHashMap<String, List<String>>();
     UrlLink urlLink = new UrlLink(link);
     if (!urlLink.isValid())
     {
       System.err.println(urlLink.getInvalidMessage());
       return null;
     }
-    if (seq != null && urlLink.isDynamic())
-    {
-      urlSets.addAll(createDynamicLinks(seq, urlLink, uniques));
-    }
-    else
-    {
-      String target = urlLink.getTarget();
-      String label = urlLink.getLabel();
-      String unq = label + "|" + urlLink.getUrl_prefix();
-      if (!uniques.contains(unq))
-      {
-        uniques.add(unq);
-        urlSets.add(new String[] { target, label, null,
-            urlLink.getUrl_prefix() });
-      }
-    }
-
-    return urlSets.toArray(new String[][] {});
-  }
 
-  /**
-   * Formats and returns a list of dynamic href links
-   * 
-   * @param seq
-   * @param urlLink
-   * @param uniques
-   */
-  List<String[]> createDynamicLinks(SequenceI seq, UrlLink urlLink,
-          List<String> uniques)
-  {
-    List<String[]> result = new ArrayList<String[]>();
-    final String target = urlLink.getTarget();
-    final String label = urlLink.getLabel();
+    urlLink.createLinksFromSeq(seq, urlSets);
 
-    // collect matching db-refs
-    DBRefEntry[] dbr = DBRefUtils.selectRefs(seq.getDBRefs(),
-            new String[] { target });
-    // collect id string too
-    String id = seq.getName();
-    String descr = seq.getDescription();
-    if (descr != null && descr.length() < 1)
-    {
-      descr = null;
-    }
-    if (dbr != null)
-    {
-      for (int r = 0; r < dbr.length; r++)
-      {
-        if (id != null && dbr[r].getAccessionId().equals(id))
-        {
-          // suppress duplicate link creation for the bare sequence ID
-          // string with this link
-          id = null;
-        }
-        // create Bare ID link for this URL
-        String[] urls = urlLink.makeUrls(dbr[r].getAccessionId(), true);
-        if (urls != null)
-        {
-          for (int u = 0; u < urls.length; u += 2)
-          {
-            String unq = urls[u] + "|" + urls[u + 1];
-            if (!uniques.contains(unq))
-            {
-              result.add(new String[] { target, label, urls[u], urls[u + 1] });
-              uniques.add(unq);
-            }
-          }
-        }
-      }
-    }
-    if (id != null)
-    {
-      // create Bare ID link for this URL
-      String[] urls = urlLink.makeUrls(id, true);
-      if (urls != null)
-      {
-        for (int u = 0; u < urls.length; u += 2)
-        {
-          String unq = urls[u] + "|" + urls[u + 1];
-          if (!uniques.contains(unq))
-          {
-            result.add(new String[] { target, label, urls[u], urls[u + 1] });
-            uniques.add(unq);
-          }
-        }
-      }
-    }
-    if (descr != null && urlLink.getRegexReplace() != null)
-    {
-      // create link for this URL from description only if regex matches
-      String[] urls = urlLink.makeUrls(descr, true);
-      if (urls != null)
-      {
-        for (int u = 0; u < urls.length; u += 2)
-        {
-          String unq = urls[u] + "|" + urls[u + 1];
-          if (!uniques.contains(unq))
-          {
-            result.add(new String[] { target, label, urls[u], urls[u + 1] });
-            uniques.add(unq);
-          }
-        }
-      }
-    }
-    return result;
+    return urlSets.values();
   }
 
   public void createSequenceAnnotationReport(final StringBuffer tip,
index e6aa472..04cb75e 100755 (executable)
@@ -100,14 +100,14 @@ public class DBRefUtils
     HashSet<String> srcs = new HashSet<String>();
     for (String src : sources)
     {
-      srcs.add(src);
+      srcs.add(src.toUpperCase());
     }
 
     List<DBRefEntry> res = new ArrayList<DBRefEntry>();
     for (DBRefEntry dbr : dbrefs)
     {
       String source = getCanonicalName(dbr.getSource());
-      if (srcs.contains(source))
+      if (srcs.contains(source.toUpperCase()))
       {
         res.add(dbr);
       }
index ce6d980..1910bff 100644 (file)
@@ -29,22 +29,17 @@ public class UrlConstants
   /*
    * Sequence ID string
    */
-  public static final String SEQUENCE_ID = "SEQUENCE_ID";
+  public static final String DB_ACCESSION = "DB_ACCESSION";
 
   /*
    * Sequence Name string
    */
-  public static final String SEQUENCE_NAME = "SEQUENCE_NAME";
-
-  /*
-   * Default sequence URL link string for EMBL-EBI search
-   */
-  public static final String EMBLEBI_STRING = "EMBL-EBI Search|http://www.ebi.ac.uk/ebisearch/search.ebi?db=allebi&query=$SEQUENCE_NAME$";
+  public static final String SEQUENCE_ID = "SEQUENCE_ID";
 
   /*
    * Default sequence URL link string for EMBL-EBI search
    */
-  public static final String OLD_EMBLEBI_STRING = "EMBL-EBI Search|http://www.ebi.ac.uk/ebisearch/search.ebi?db=allebi&query=$SEQUENCE_ID$";
+  public static final String EMBLEBI_STRING = "EMBL-EBI Search|http://www.ebi.ac.uk/ebisearch/search.ebi?db=allebi&query=$SEQUENCE_ID$";
 
   /*
    * Default sequence URL link string for SRS 
index 872f432..3ee6432 100644 (file)
  */
 package jalview.util;
 
+import static jalview.util.UrlConstants.DB_ACCESSION;
 import static jalview.util.UrlConstants.SEQUENCE_ID;
-import static jalview.util.UrlConstants.SEQUENCE_NAME;
 
+import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.SequenceI;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
 import java.util.Vector;
 
 public class UrlLink
@@ -33,19 +39,33 @@ public class UrlLink
    * 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 susbstituted. Usage
+   * text following the first pipe symbol will be substituted. Usage
    * documentation todo.
    */
-  private String url_suffix, url_prefix, target, label, regexReplace;
+
+  // Internal constants
+  private static final String SEP = "|";
+
+  private static final String DELIM = "$";
+
+  private String urlSuffix;
+
+  private String urlPrefix;
+
+  private String target;
+
+  private String label;
+
+  private String regexReplace;
 
   private boolean dynamic = false;
 
-  private boolean uses_seq_id = false;
+  private boolean usesDBaccession = false;
 
   private String invalidMessage = null;
 
   /**
-   * parse the given linkString of the form '<label>|<url>' into parts url may
+   * parse the given linkString of the form '<label>SEP<url>' into parts url may
    * contain a string $SEQUENCE_ID<=optional regex=>$ where <=optional regex=>
    * must be of the form =/<perl style regex>/=$
    * 
@@ -53,40 +73,37 @@ public class UrlLink
    */
   public UrlLink(String link)
   {
-    int sep = link.indexOf("|");
-    int psqid = link.indexOf("$" + SEQUENCE_ID);
-    int nsqid = link.indexOf("$" + SEQUENCE_NAME);
+    int sep = link.indexOf(SEP);
+    int psqid = link.indexOf(DELIM + DB_ACCESSION);
+    int nsqid = link.indexOf(DELIM + SEQUENCE_ID);
     if (psqid > -1)
     {
       dynamic = true;
-      uses_seq_id = true;
+      usesDBaccession = true;
 
       sep = parseTargetAndLabel(sep, psqid, link);
 
-      parseUrl(link, SEQUENCE_ID, psqid, sep);
+      parseUrl(link, DB_ACCESSION, psqid, sep);
     }
     else if (nsqid > -1)
     {
       dynamic = true;
       sep = parseTargetAndLabel(sep, nsqid, link);
 
-      parseUrl(link, SEQUENCE_NAME, nsqid, sep);
+      parseUrl(link, SEQUENCE_ID, nsqid, sep);
     }
     else
     {
       target = link.substring(0, sep);
-      sep = link.lastIndexOf("|");
+      sep = link.lastIndexOf(SEP);
       label = link.substring(0, sep);
-      url_prefix = link.substring(sep + 1);
+      urlPrefix = link.substring(sep + 1).trim();
       regexReplace = null; // implies we trim any prefix if necessary //
-      // regexReplace=".*\\|?(.*)";
-      url_suffix = null;
+      urlSuffix = null;
     }
 
     label = label.trim();
     target = target.trim();
-    target = target.toUpperCase(); // DBRefEntry uppercases DB names
-    // NB getCanonicalName might be better but does not currently change case
   }
 
   /**
@@ -94,7 +111,7 @@ public class UrlLink
    */
   public String getUrl_suffix()
   {
-    return url_suffix;
+    return urlSuffix;
   }
 
   /**
@@ -102,7 +119,7 @@ public class UrlLink
    */
   public String getUrl_prefix()
   {
-    return url_prefix;
+    return urlPrefix;
   }
 
   /**
@@ -149,6 +166,34 @@ public class UrlLink
   }
 
   /**
+   * 
+   * @return whether link is dynamic
+   */
+  public boolean isDynamic()
+  {
+    return dynamic;
+  }
+
+  /**
+   * 
+   * @return whether link uses DB Accession id
+   */
+  public boolean usesDBAccession()
+  {
+    return usesDBaccession;
+  }
+
+  /**
+   * Set the label
+   * 
+   * @param newlabel
+   */
+  public void setLabel(String newlabel)
+  {
+    this.label = newlabel;
+  }
+
+  /**
    * return one or more URL strings by applying regex to the given idstring
    * 
    * @param idstring
@@ -173,7 +218,7 @@ public class UrlLink
           {
             // take whole regex
             return new String[] { rg.stringMatched(),
-                url_prefix + rg.stringMatched() + url_suffix };
+                urlPrefix + rg.stringMatched() + urlSuffix };
           } /*
              * else if (ns==1) { // take only subgroup match return new String[]
              * { rg.stringMatched(1), url_prefix+rg.stringMatched(1)+url_suffix
@@ -214,7 +259,7 @@ public class UrlLink
                 if (mtch.length() > 0)
                 {
                   subs.addElement(mtch);
-                  subs.addElement(url_prefix + mtch + url_suffix);
+                  subs.addElement(urlPrefix + mtch + urlSuffix);
                 }
                 s = r;
               }
@@ -223,8 +268,8 @@ public class UrlLink
                 if (rg.matchedFrom(s) > -1)
                 {
                   subs.addElement(rg.stringMatched(s));
-                  subs.addElement(url_prefix + rg.stringMatched(s)
-                          + url_suffix);
+                  subs.addElement(urlPrefix + rg.stringMatched(s)
+                          + urlSuffix);
                 }
                 s++;
               }
@@ -245,31 +290,31 @@ public class UrlLink
         }
       }
       /* Otherwise - trim off any 'prefix' - pre 2.4 Jalview behaviour */
-      if (idstring.indexOf("|") > -1)
+      if (idstring.indexOf(SEP) > -1)
       {
-        idstring = idstring.substring(idstring.lastIndexOf("|") + 1);
+        idstring = idstring.substring(idstring.lastIndexOf(SEP) + 1);
       }
 
       // just return simple url substitution.
-      return new String[] { idstring, url_prefix + idstring + url_suffix };
+      return new String[] { idstring, urlPrefix + idstring + urlSuffix };
     }
     else
     {
-      return new String[] { "", url_prefix };
+      return new String[] { "", urlPrefix };
     }
   }
 
   @Override
   public String toString()
   {
-    String var = (uses_seq_id ? SEQUENCE_ID : SEQUENCE_NAME);
+    String var = (usesDBaccession ? DB_ACCESSION : SEQUENCE_ID);
 
     return label
-            + "|"
-            + url_prefix
-            + (dynamic ? ("$" + var + ((regexReplace != null) ? "="
-                    + regexReplace + "=$" : "$")) : "")
-            + ((url_suffix == null) ? "" : url_suffix);
+            + SEP
+            + urlPrefix
+            + (dynamic ? (DELIM + var + ((regexReplace != null) ? "="
+                    + regexReplace + "=" + DELIM : DELIM)) : "")
+            + ((urlSuffix == null) ? "" : urlSuffix);
   }
 
   /**
@@ -289,15 +334,15 @@ public class UrlLink
     do
     {
       sep = p;
-      p = link.indexOf("|", sep + 1);
+      p = link.indexOf(SEP, sep + 1);
     } while (p > sep && p < psqid);
-    // Assuming that the URL itself does not contain any '|' symbols
+    // Assuming that the URL itself does not contain any SEP symbols
     // sep now contains last pipe symbol position prior to any regex symbols
     label = link.substring(0, sep);
-    if (label.indexOf("|") > -1)
+    if (label.indexOf(SEP) > -1)
     {
-      // | terminated database name / www target at start of Label
-      target = label.substring(0, label.indexOf("|"));
+      // SEP terminated database name / www target at start of Label
+      target = label.substring(0, label.indexOf(SEP));
     }
     else if (label.indexOf(" ") > 2)
     {
@@ -325,13 +370,13 @@ public class UrlLink
    */
   protected void parseUrl(String link, String varName, int sqidPos, int sep)
   {
-    url_prefix = link.substring(sep + 1, sqidPos);
+    urlPrefix = link.substring(sep + 1, sqidPos).trim();
 
     // delimiter at start of regex: e.g. $SEQUENCE_ID=/
-    String startDelimiter = "$" + varName + "=/";
+    String startDelimiter = DELIM + varName + "=/";
 
     // delimiter at end of regex: /=$
-    String endDelimiter = "/=$";
+    String endDelimiter = "/=" + DELIM;
 
     int startLength = startDelimiter.length();
 
@@ -342,7 +387,7 @@ public class UrlLink
             && (p > sqidPos + startLength))
     {
       // Extract Regex and suffix
-      url_suffix = link.substring(p + endDelimiter.length());
+      urlSuffix = link.substring(p + endDelimiter.length());
       regexReplace = link.substring(sqidPos + startLength, p);
       try
       {
@@ -364,9 +409,9 @@ public class UrlLink
       // no regex
       regexReplace = null;
       // verify format is really correct.
-      if (link.indexOf("$" + varName + "$") == sqidPos)
+      if (link.indexOf(DELIM + varName + DELIM) == sqidPos)
       {
-        url_suffix = link.substring(sqidPos + startLength - 1);
+        urlSuffix = link.substring(sqidPos + startLength - 1);
         regexReplace = null;
       }
       else
@@ -377,6 +422,124 @@ public class UrlLink
     }
   }
 
+  /**
+   * Create a set of URL links for a sequence
+   * 
+   * @param seq
+   *          The sequence to create links for
+   * @param linkset
+   *          Map of links: key = id + SEP + link, value = [target, label, id,
+   *          link]
+   */
+  public void createLinksFromSeq(final SequenceI seq,
+          Map<String, List<String>> linkset)
+  {
+    if (seq != null && dynamic)
+    {
+      createDynamicLinks(seq, linkset);
+    }
+    else
+    {
+      createStaticLink(linkset);
+    }
+  }
+
+  /**
+   * Create a static URL link
+   * 
+   * @param linkset
+   *          Map of links: key = id + SEP + link, value = [target, label, id,
+   *          link]
+   */
+  protected void createStaticLink(Map<String, List<String>> linkset)
+  {
+    if (!linkset.containsKey(label + SEP + getUrl_prefix()))
+    {
+      // Add a non-dynamic link
+      linkset.put(label + SEP + getUrl_prefix(),
+              Arrays.asList(target, label, null, getUrl_prefix()));
+    }
+  }
+
+  /**
+   * Create dynamic URL links
+   * 
+   * @param seq
+   *          The sequence to create links for
+   * @param linkset
+   *          Map of links: key = id + SEP + link, value = [target, label, id,
+   *          link]
+   */
+  protected void createDynamicLinks(final SequenceI seq,
+          Map<String, List<String>> linkset)
+  {
+    // collect id string too
+    String id = seq.getName();
+    String descr = seq.getDescription();
+    if (descr != null && descr.length() < 1)
+    {
+      descr = null;
+    }
+
+    if (usesDBAccession()) // link is ID
+    {
+      // collect matching db-refs
+      DBRefEntry[] dbr = DBRefUtils.selectRefs(seq.getDBRefs(),
+              new String[] { target });
+
+      // if there are any dbrefs which match up with the link
+      if (dbr != null)
+      {
+        for (int r = 0; r < dbr.length; r++)
+        {
+          // create Bare ID link for this URL
+          createBareURLLink(dbr[r].getAccessionId(), true, linkset);
+        }
+      }
+    }
+    else if (!usesDBAccession() && id != null) // link is name
+    {
+      // create Bare ID link for this URL
+      createBareURLLink(id, false, linkset);
+    }
+
+    // Create urls from description but only for URL links which are regex
+    // links
+    if (descr != null && getRegexReplace() != null)
+    {
+      // create link for this URL from description where regex matches
+      createBareURLLink(descr, false, linkset);
+    }
+  }
+
+  /*
+   * Create a bare URL Link
+   * Returns map where key = id + SEP + link, and value = [target, label, id, link]
+   */
+  protected void createBareURLLink(String id, Boolean combineLabel,
+          Map<String, List<String>> linkset)
+  {
+    String[] urls = makeUrls(id, true);
+    if (urls != null)
+    {
+      for (int u = 0; u < urls.length; u += 2)
+      {
+        if (!linkset.containsKey(urls[u] + SEP + urls[u + 1]))
+        {
+          String thisLabel = label;
+          if (combineLabel)
+          {
+            // incorporate label with idstring
+            thisLabel = label + SEP + urls[u];
+          }
+
+          linkset.put(urls[u] + SEP + urls[u + 1],
+                  Arrays.asList(target, thisLabel, urls[u], urls[u + 1]));
+        }
+      }
+    }
+  }
+
   private static void testUrls(UrlLink ul, String idstring, String[] urls)
   {
 
@@ -412,7 +575,7 @@ public class UrlLink
      * "PF3|http://us.expasy.org/cgi-bin/niceprot.pl?$SEQUENCE_ID=/PFAM:(.+)/=$"
      * , "NOTFER|http://notfer.org/$SEQUENCE_ID=/(?<!\\s)(.+)/=$",
      */
-    "NESTED|http://nested/$" + SEQUENCE_ID
+    "NESTED|http://nested/$" + DB_ACCESSION
             + "=/^(?:Label:)?(?:(?:gi\\|(\\d+))|([^:]+))/=$/nested" };
     String[] idstrings = new String[] {
     /*
@@ -454,20 +617,4 @@ public class UrlLink
       }
     }
   }
-
-  public boolean isDynamic()
-  {
-    // TODO Auto-generated method stub
-    return dynamic;
-  }
-
-  public boolean usesSeqId()
-  {
-    return uses_seq_id;
-  }
-
-  public void setLabel(String newlabel)
-  {
-    this.label = newlabel;
-  }
 }
index b4e8629..7b1eac1 100644 (file)
@@ -20,6 +20,8 @@
  */
 package jalview.gui;
 
+import static jalview.util.UrlConstants.DB_ACCESSION;
+import static jalview.util.UrlConstants.SEQUENCE_ID;
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertFalse;
 import static org.testng.AssertJUnit.assertTrue;
@@ -458,11 +460,15 @@ public class PopupMenuTest
     List<DBRefEntry> refs = new ArrayList<DBRefEntry>();
 
     // links as might be added into Preferences | Connections dialog
-    links.add("EMBL-EBI Search | http://www.ebi.ac.uk/ebisearch/search.ebi?db=allebi&query=$SEQUENCE_NAME$");
-    links.add("UNIPROT | http://www.uniprot.org/uniprot/$SEQUENCE_ID$");
-    links.add("INTERPRO | http://www.ebi.ac.uk/interpro/entry/$SEQUENCE_ID$");
+    links.add("EMBL-EBI Search | http://www.ebi.ac.uk/ebisearch/search.ebi?db=allebi&query=$"
+            + SEQUENCE_ID + "$");
+    links.add("UNIPROT | http://www.uniprot.org/uniprot/$" + DB_ACCESSION
+            + "$");
+    links.add("INTERPRO | http://www.ebi.ac.uk/interpro/entry/$"
+            + DB_ACCESSION + "$");
     // Gene3D entry tests for case (in)sensitivity
-    links.add("Gene3D | http://gene3d.biochem.ucl.ac.uk/Gene3D/search?sterm=$SEQUENCE_ID$&mode=protein");
+    links.add("Gene3D | http://gene3d.biochem.ucl.ac.uk/Gene3D/search?sterm=$"
+            + DB_ACCESSION + "$&mode=protein");
 
     // make seq0 dbrefs
     refs.add(new DBRefEntry(DBRefSource.UNIPROT, "1", "P83527"));
index 45ef6af..c98d8ce 100644 (file)
  */
 package jalview.util;
 
+import static jalview.util.UrlConstants.DB_ACCESSION;
 import static jalview.util.UrlConstants.SEQUENCE_ID;
-import static jalview.util.UrlConstants.SEQUENCE_NAME;
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertFalse;
 import static org.testng.AssertJUnit.assertNull;
 import static org.testng.AssertJUnit.assertTrue;
 
+import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.DBRefSource;
+import jalview.datamodel.Sequence;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
 import org.testng.annotations.Test;
 
 public class UrlLinkTest
@@ -52,28 +61,28 @@ public class UrlLinkTest
   @Test(groups = { "Functional" })
   public void testUrlLinkCreationNoRegex()
   {
-    // SEQUENCE_NAME
-    UrlLink ul = new UrlLink(DB + SEP + URL_PREFIX + DELIM + SEQUENCE_NAME
+    // SEQUENCE_ID
+    UrlLink ul = new UrlLink(DB + SEP + URL_PREFIX + DELIM + SEQUENCE_ID
             + DELIM + URL_SUFFIX);
     assertEquals(DB.toUpperCase(), ul.getTarget());
     assertEquals(DB, ul.getLabel());
     assertEquals(URL_PREFIX, ul.getUrl_prefix());
     assertEquals(URL_SUFFIX, ul.getUrl_suffix());
     assertTrue(ul.isDynamic());
-    assertFalse(ul.usesSeqId());
+    assertFalse(ul.usesDBAccession());
     assertNull(ul.getRegexReplace());
     assertTrue(ul.isValid());
     assertNull(ul.getInvalidMessage());
 
-    // SEQUENCE_ID
-    ul = new UrlLink(DB + SEP + URL_PREFIX + DELIM + SEQUENCE_ID + DELIM
+    // DB_ACCESSION
+    ul = new UrlLink(DB + SEP + URL_PREFIX + DELIM + DB_ACCESSION + DELIM
             + URL_SUFFIX);
     assertEquals(DB.toUpperCase(), ul.getTarget());
     assertEquals(DB, ul.getLabel());
     assertEquals(URL_PREFIX, ul.getUrl_prefix());
     assertEquals(URL_SUFFIX, ul.getUrl_suffix());
     assertTrue(ul.isDynamic());
-    assertTrue(ul.usesSeqId());
+    assertTrue(ul.usesDBAccession());
     assertNull(ul.getRegexReplace());
     assertTrue(ul.isValid());
     assertNull(ul.getInvalidMessage());
@@ -84,7 +93,7 @@ public class UrlLinkTest
     assertEquals(DB, ul.getLabel());
     assertEquals(URL_PREFIX + URL_SUFFIX.substring(1), ul.getUrl_prefix());
     assertFalse(ul.isDynamic());
-    assertFalse(ul.usesSeqId());
+    assertFalse(ul.usesDBAccession());
     assertNull(ul.getRegexReplace());
     assertTrue(ul.isValid());
     assertNull(ul.getInvalidMessage());
@@ -96,43 +105,43 @@ public class UrlLinkTest
   @Test(groups = { "Functional" })
   public void testUrlLinkCreationWithRegex()
   {
-    // SEQUENCE_NAME
-    UrlLink ul = new UrlLink(DB + SEP + URL_PREFIX + DELIM + SEQUENCE_NAME
+    // SEQUENCE_ID
+    UrlLink ul = new UrlLink(DB + SEP + URL_PREFIX + DELIM + SEQUENCE_ID
             + REGEX_NESTED + DELIM + URL_SUFFIX);
     assertEquals(DB.toUpperCase(), ul.getTarget());
     assertEquals(DB, ul.getLabel());
     assertEquals(URL_PREFIX, ul.getUrl_prefix());
     assertEquals(URL_SUFFIX, ul.getUrl_suffix());
     assertTrue(ul.isDynamic());
-    assertFalse(ul.usesSeqId());
+    assertFalse(ul.usesDBAccession());
     assertEquals(REGEX_NESTED.substring(2, REGEX_NESTED.length() - 2),
             ul.getRegexReplace());
     assertTrue(ul.isValid());
     assertNull(ul.getInvalidMessage());
 
-    // SEQUENCE_ID
-    ul = new UrlLink(DB + SEP + URL_PREFIX + DELIM + SEQUENCE_ID
+    // DB_ACCESSION
+    ul = new UrlLink(DB + SEP + URL_PREFIX + DELIM + DB_ACCESSION
             + REGEX_NESTED + DELIM + URL_SUFFIX);
     assertEquals(DB.toUpperCase(), ul.getTarget());
     assertEquals(DB, ul.getLabel());
     assertEquals(URL_PREFIX, ul.getUrl_prefix());
     assertEquals(URL_SUFFIX, ul.getUrl_suffix());
     assertTrue(ul.isDynamic());
-    assertTrue(ul.usesSeqId());
+    assertTrue(ul.usesDBAccession());
     assertEquals(REGEX_NESTED.substring(2, REGEX_NESTED.length() - 2),
             ul.getRegexReplace());
     assertTrue(ul.isValid());
     assertNull(ul.getInvalidMessage());
 
     // invalid regex
-    ul = new UrlLink(DB + SEP + URL_PREFIX + DELIM + SEQUENCE_ID
+    ul = new UrlLink(DB + SEP + URL_PREFIX + DELIM + DB_ACCESSION
             + REGEX_RUBBISH + DELIM + URL_SUFFIX);
     assertEquals(DB.toUpperCase(), ul.getTarget());
     assertEquals(DB, ul.getLabel());
     assertEquals(URL_PREFIX, ul.getUrl_prefix());
     assertEquals(URL_SUFFIX, ul.getUrl_suffix());
     assertTrue(ul.isDynamic());
-    assertTrue(ul.usesSeqId());
+    assertTrue(ul.usesDBAccession());
     assertEquals(REGEX_RUBBISH.substring(2, REGEX_RUBBISH.length() - 2),
             ul.getRegexReplace());
     assertFalse(ul.isValid());
@@ -150,7 +159,7 @@ public class UrlLinkTest
   public void testMakeUrlNoRegex()
   {
     // Single non-regex
-    UrlLink ul = new UrlLink(DB + SEP + URL_PREFIX + DELIM + SEQUENCE_NAME
+    UrlLink ul = new UrlLink(DB + SEP + URL_PREFIX + DELIM + SEQUENCE_ID
             + DELIM + URL_SUFFIX);
     String idstring = "FER_CAPAA";
     String[] urls = ul.makeUrls(idstring, true);
@@ -167,13 +176,14 @@ public class UrlLinkTest
   }
 
   /**
-   * Test construction of link by substituting sequence id or name
+   * Test construction of link by substituting sequence id or name using regular
+   * expression
    */
   @Test(groups = { "Functional" })
   public void testMakeUrlWithRegex()
   {
     // Unused regex
-    UrlLink ul = new UrlLink(DB + SEP + URL_PREFIX + DELIM + SEQUENCE_ID
+    UrlLink ul = new UrlLink(DB + SEP + URL_PREFIX + DELIM + DB_ACCESSION
             + REGEX_NESTED + DELIM + URL_SUFFIX);
     String idstring = "FER_CAPAA";
     String[] urls = ul.makeUrls(idstring, true);
@@ -243,4 +253,150 @@ public class UrlLinkTest
     assertNull(ul.getInvalidMessage());
   }
 
+  /**
+   * Test creating links with null sequence
+   */
+  @Test(groups = { "Functional" })
+  public void testCreateLinksFromNullSequence()
+  {
+    UrlLink ul = new UrlLink(DB + SEP + URL_PREFIX + DELIM + SEQUENCE_ID
+            + DELIM + URL_SUFFIX);
+
+    Map<String, List<String>> linkset = new LinkedHashMap<String, List<String>>();
+    ul.createLinksFromSeq(null, linkset);
+
+    String key = DB + SEP + URL_PREFIX;
+    assertEquals(1, linkset.size());
+    assertTrue(linkset.containsKey(key));
+    assertEquals(linkset.get(key).get(0), DB.toUpperCase());
+    assertEquals(linkset.get(key).get(1), DB);
+    assertEquals(linkset.get(key).get(2), null);
+    assertEquals(linkset.get(key).get(3), URL_PREFIX);
+  }
+
+  /**
+   * Test creating links with non-dynamic urlLink
+   */
+  @Test(groups = { "Functional" })
+  public void testCreateLinksForNonDynamic()
+  {
+    UrlLink ul = new UrlLink(DB + SEP + URL_PREFIX + URL_SUFFIX);
+
+    Map<String, List<String>> linkset = new LinkedHashMap<String, List<String>>();
+    ul.createLinksFromSeq(null, linkset);
+
+    String key = DB + SEP + URL_PREFIX + URL_SUFFIX;
+    assertEquals(1, linkset.size());
+    assertTrue(linkset.containsKey(key));
+    assertEquals(linkset.get(key).get(0), DB.toUpperCase());
+    assertEquals(linkset.get(key).get(1), DB);
+    assertEquals(linkset.get(key).get(2), null);
+    assertEquals(linkset.get(key).get(3), URL_PREFIX + URL_SUFFIX);
+  }
+
+  /**
+   * Test creating links
+   */
+  @Test(groups = { "Functional" })
+  public void testCreateLinksFromSequence()
+  {
+
+    // create list of links and list of DBRefs
+    List<String> links = new ArrayList<String>();
+    List<DBRefEntry> refs = new ArrayList<DBRefEntry>();
+
+    // links as might be added into Preferences | Connections dialog
+    links.add("EMBL-EBI Search | http://www.ebi.ac.uk/ebisearch/search.ebi?db=allebi&query=$"
+            + SEQUENCE_ID + "$");
+    links.add("UNIPROT | http://www.uniprot.org/uniprot/$" + DB_ACCESSION
+            + "$");
+    links.add("INTERPRO | http://www.ebi.ac.uk/interpro/entry/$"
+            + DB_ACCESSION + "$");
+
+    // make seq0 dbrefs
+    refs.add(new DBRefEntry(DBRefSource.UNIPROT, "1", "P83527"));
+    refs.add(new DBRefEntry("INTERPRO", "1", "IPR001041"));
+    refs.add(new DBRefEntry("INTERPRO", "1", "IPR006058"));
+    refs.add(new DBRefEntry("INTERPRO", "1", "IPR012675"));
+
+    Sequence seq0 = new Sequence("FER1", "AKPNGVL");
+
+    // add all the dbrefs to the sequence
+    seq0.addDBRef(refs.get(0));
+    seq0.addDBRef(refs.get(1));
+    seq0.addDBRef(refs.get(2));
+    seq0.addDBRef(refs.get(3));
+    seq0.createDatasetSequence();
+
+    // Test where link takes a sequence id as replacement
+    UrlLink ul = new UrlLink(DB + SEP + URL_PREFIX + DELIM + SEQUENCE_ID
+            + DELIM + URL_SUFFIX);
+
+    Map<String, List<String>> linkset = new LinkedHashMap<String, List<String>>();
+    ul.createLinksFromSeq(seq0, linkset);
+
+    String key = seq0.getName() + SEP + URL_PREFIX + seq0.getName()
+            + URL_SUFFIX;
+    assertEquals(1, linkset.size());
+    assertTrue(linkset.containsKey(key));
+    assertEquals(linkset.get(key).get(0), DB.toUpperCase());
+    assertEquals(linkset.get(key).get(1), DB);
+    assertEquals(linkset.get(key).get(2), seq0.getName());
+    assertEquals(linkset.get(key).get(3), URL_PREFIX + seq0.getName()
+            + URL_SUFFIX);
+
+    // Test where link takes a db annotation id and only has one dbref
+    ul = new UrlLink(links.get(1));
+    linkset = new LinkedHashMap<String, List<String>>();
+    ul.createLinksFromSeq(seq0, linkset);
+
+    key = "P83527|http://www.uniprot.org/uniprot/P83527";
+    assertEquals(1, linkset.size());
+    assertTrue(linkset.containsKey(key));
+    assertEquals(linkset.get(key).get(0), DBRefSource.UNIPROT);
+    assertEquals(linkset.get(key).get(1), DBRefSource.UNIPROT + SEP
+            + "P83527");
+    assertEquals(linkset.get(key).get(2), "P83527");
+    assertEquals(linkset.get(key).get(3),
+            "http://www.uniprot.org/uniprot/P83527");
+
+    // Test where link takes a db annotation id and has multiple dbrefs
+    ul = new UrlLink(links.get(2));
+    linkset = new LinkedHashMap<String, List<String>>();
+    ul.createLinksFromSeq(seq0, linkset);
+    assertEquals(3, linkset.size());
+
+    // check each link made it in correctly
+    key = "IPR001041|http://www.ebi.ac.uk/interpro/entry/IPR001041";
+    assertTrue(linkset.containsKey(key));
+    assertEquals(linkset.get(key).get(0), "INTERPRO");
+    assertEquals(linkset.get(key).get(1), "INTERPRO" + SEP + "IPR001041");
+    assertEquals(linkset.get(key).get(2), "IPR001041");
+    assertEquals(linkset.get(key).get(3),
+            "http://www.ebi.ac.uk/interpro/entry/IPR001041");
+
+    key = "IPR006058|http://www.ebi.ac.uk/interpro/entry/IPR006058";
+    assertTrue(linkset.containsKey(key));
+    assertEquals(linkset.get(key).get(0), "INTERPRO");
+    assertEquals(linkset.get(key).get(1), "INTERPRO" + SEP + "IPR006058");
+    assertEquals(linkset.get(key).get(2), "IPR006058");
+    assertEquals(linkset.get(key).get(3),
+            "http://www.ebi.ac.uk/interpro/entry/IPR006058");
+
+    key = "IPR012675|http://www.ebi.ac.uk/interpro/entry/IPR012675";
+    assertTrue(linkset.containsKey(key));
+    assertEquals(linkset.get(key).get(0), "INTERPRO");
+    assertEquals(linkset.get(key).get(1), "INTERPRO" + SEP + "IPR012675");
+    assertEquals(linkset.get(key).get(2), "IPR012675");
+    assertEquals(linkset.get(key).get(3),
+            "http://www.ebi.ac.uk/interpro/entry/IPR012675");
+
+    // Test where there are no matching dbrefs for the link
+    ul = new UrlLink(DB + SEP + URL_PREFIX + DELIM + DB_ACCESSION + DELIM
+            + URL_SUFFIX);
+    linkset = new LinkedHashMap<String, List<String>>();
+    ul.createLinksFromSeq(seq0, linkset);
+    assertTrue(linkset.isEmpty());
+  }
+
 }