JAL-1015 refactor tooltip html generation code to jalview.io.SequenceAnnotationReport
authorjprocter <jprocter@compbio.dundee.ac.uk>
Fri, 31 Aug 2012 10:22:23 +0000 (11:22 +0100)
committerjprocter <jprocter@compbio.dundee.ac.uk>
Fri, 31 Aug 2012 10:22:23 +0000 (11:22 +0100)
src/jalview/gui/IdPanel.java
src/jalview/gui/SeqPanel.java
src/jalview/io/SequenceAnnotationReport.java [new file with mode: 0644]

index 0480ffa..3b9d385 100755 (executable)
@@ -25,6 +25,7 @@ import java.util.Vector;
 import javax.swing.*;
 
 import jalview.datamodel.*;
+import jalview.io.SequenceAnnotationReport;
 import jalview.util.UrlLink;
 
 /**
@@ -52,6 +53,7 @@ public class IdPanel extends JPanel implements MouseListener,
   int lastid = -1;
 
   boolean mouseDragging = false;
+  private final SequenceAnnotationReport seqAnnotReport;
 
   /**
    * Creates a new IdPanel object.
@@ -67,6 +69,7 @@ public class IdPanel extends JPanel implements MouseListener,
     alignPanel = parent;
     idCanvas = new IdCanvas(av);
     linkImageURL = getClass().getResource("/images/link.gif").toString();
+    seqAnnotReport = new SequenceAnnotationReport(linkImageURL);
     setLayout(new BorderLayout());
     add(idCanvas, BorderLayout.CENTER);
     addMouseListener(this);
@@ -74,7 +77,6 @@ public class IdPanel extends JPanel implements MouseListener,
     addMouseWheelListener(this);
     ToolTipManager.sharedInstance().registerComponent(this);
   }
-
   /**
    * DOCUMENT ME!
    *
@@ -86,63 +88,15 @@ public class IdPanel extends JPanel implements MouseListener,
   {
     SeqPanel sp = alignPanel.seqPanel;
     int seq = Math.max(0, sp.findSeq(e));
-    String tmp;
     if (seq > -1 && seq < av.getAlignment().getHeight())
     {
       SequenceI sequence = av.getAlignment().getSequenceAt(seq);
       StringBuffer tip = new StringBuffer();
-      tip.append("<i>");
-
-      int maxWidth = 0;
-      if (sequence.getDescription() != null)
-      {
-        tmp = sequence.getDescription();
-        tip.append("<br>" + tmp);
-        maxWidth = Math.max(maxWidth, tmp.length());
-      }
-
-      DBRefEntry[] dbrefs = sequence.getDatasetSequence().getDBRef();
-      if (av.isShowDbRefs() && dbrefs != null)
-      {
-        for (int i = 0; i < dbrefs.length; i++)
-        {
-          tip.append("<br>");
-          tmp = dbrefs[i].getSource() + " " + dbrefs[i].getAccessionId();
-          tip.append(tmp);
-          maxWidth = Math.max(maxWidth, tmp.length());
-        }
-      }
-
-      // ADD NON POSITIONAL SEQUENCE INFO
-      SequenceFeature[] features = sequence.getDatasetSequence()
-              .getSequenceFeatures();
-      SequenceFeature[] tfeat = new SequenceFeature[1];
-      if (av.isShowNpFeats() && features != null)
-      {
-        for (int i = 0; i < features.length; i++)
-        {
-          if (features[i].begin == 0 && features[i].end == 0)
-          {
-            int sz = -tip.length();
-            tfeat[0] = features[i];
-            sp.appendFeatures(tip, linkImageURL, 0, tfeat,
-                    sp.seqCanvas.fr.minmax);
-            sz += tip.length();
-            maxWidth = Math.max(maxWidth, sz);
-          }
-        }
-      }
-
-      if (maxWidth > 60)
-      {
-        tip.insert(0, "<table width=350 border=0><tr><td><i>");
-        tip.append("</i></td></tr></table>");
-      }
-
-      tip.append("</html>");
-
+      seqAnnotReport.createSequenceAnnotationReport(tip, sequence,
+              av.isShowDbRefs(), av.isShowNpFeats(),
+              sp.seqCanvas.fr.minmax);
       setToolTipText("<html>" + sequence.getDisplayId(true) + " "
-              + tip.toString());
+              + tip.toString()+"</html>");
     }
   }
 
index cdaa5b9..648c3a2 100644 (file)
@@ -27,6 +27,7 @@ import javax.swing.*;
 
 import jalview.commands.*;
 import jalview.datamodel.*;
+import jalview.io.SequenceAnnotationReport;
 import jalview.schemes.*;
 import jalview.structure.*;
 
@@ -87,7 +88,7 @@ public class SeqPanel extends JPanel implements MouseListener,
   StringBuffer keyboardNo2;
 
   java.net.URL linkImageURL;
-
+  private final SequenceAnnotationReport seqARep;
   StringBuffer tooltipText = new StringBuffer("<html>");
 
   String tmpString;
@@ -107,6 +108,7 @@ public class SeqPanel extends JPanel implements MouseListener,
   public SeqPanel(AlignViewport av, AlignmentPanel ap)
   {
     linkImageURL = getClass().getResource("/images/link.gif");
+    seqARep=new SequenceAnnotationReport(linkImageURL.toString());
     ToolTipManager.sharedInstance().registerComponent(this);
     ToolTipManager.sharedInstance().setInitialDelay(0);
     ToolTipManager.sharedInstance().setDismissDelay(10000);
@@ -713,7 +715,7 @@ public class SeqPanel extends JPanel implements MouseListener,
       SequenceFeature[] features = findFeaturesAtRes(
               sequence.getDatasetSequence(),
               rpos = sequence.findPosition(res));
-      appendFeatures(tooltipText, linkImageURL.toString(), rpos, features,
+      seqARep.appendFeatures(tooltipText,  rpos, features,
               this.ap.seqPanel.seqCanvas.fr.minmax);
     }
     if (tooltipText.length() == 6) // <html></html>
@@ -759,145 +761,6 @@ public class SeqPanel extends JPanel implements MouseListener,
     return lastp = p;
   }
 
-  /**
-   * appends the features at rpos to the given stringbuffer ready for display in
-   * a tooltip
-   *
-   * @param tooltipText2
-   * @param linkImageURL
-   * @param rpos
-   * @param features
-   *          TODO refactor to Jalview 'utilities' somehow.
-   */
-  public void appendFeatures(StringBuffer tooltipText2,
-          String linkImageURL, int rpos, SequenceFeature[] features)
-  {
-    appendFeatures(tooltipText2, linkImageURL, rpos, features, null);
-  }
-
-  public void appendFeatures(StringBuffer tooltipText2, String string,
-          int rpos, SequenceFeature[] features, Hashtable minmax)
-  {
-    String tmpString;
-    if (features != null)
-    {
-      for (int i = 0; i < features.length; i++)
-      {
-        if (features[i].getType().equals("disulfide bond"))
-        {
-          if (features[i].getBegin() == rpos
-                  || features[i].getEnd() == rpos)
-          {
-            if (tooltipText2.length() > 6)
-            {
-              tooltipText2.append("<br>");
-            }
-            tooltipText2.append("disulfide bond " + features[i].getBegin()
-                    + ":" + features[i].getEnd());
-            if (features[i].links != null)
-            {
-              tooltipText2.append(" <img src=\"" + linkImageURL + "\">");
-            }
-          }
-        }
-        else
-        {
-          if (tooltipText2.length() > 6)
-          {
-            tooltipText2.append("<br>");
-          }
-          // TODO: remove this hack to display link only features
-          boolean linkOnly = features[i].getValue("linkonly") != null;
-          if (!linkOnly)
-          {
-            tooltipText2.append(features[i].getType() + " ");
-            if (rpos != 0)
-            {
-              // we are marking a positional feature
-              tooltipText2.append(features[i].begin);
-            }
-            if (features[i].begin != features[i].end)
-            {
-              tooltipText2.append(" " + features[i].end);
-            }
-
-            if (features[i].getDescription() != null
-                    && !features[i].description.equals(features[i]
-                            .getType()))
-            {
-              tmpString = features[i].getDescription();
-              String tmp2up=tmpString.toUpperCase();
-              int startTag = tmp2up.indexOf("<HTML>");
-              if (startTag > -1)
-              {
-                tmpString = tmpString.substring(startTag + 6);
-                tmp2up = tmp2up.substring(startTag+6);
-              }
-              int endTag = tmp2up.indexOf("</BODY>");
-              if (endTag > -1)
-              {
-                tmpString = tmpString.substring(0, endTag);
-                tmp2up = tmp2up.substring(0, endTag);
-              }
-              endTag = tmp2up.indexOf("</HTML>");
-              if (endTag > -1)
-              {
-                tmpString = tmpString.substring(0, endTag);
-              }
-
-              if (startTag > -1)
-              {
-                tooltipText2.append("; " + tmpString);
-              }
-              else
-              {
-                if (tmpString.indexOf("<") > -1
-                        || tmpString.indexOf(">") > -1)
-                {
-                  // The description does not specify html is to
-                  // be used, so we must remove < > symbols
-                  tmpString = tmpString.replaceAll("<", "&lt;");
-                  tmpString = tmpString.replaceAll(">", "&gt;");
-
-                  tooltipText2.append("; ");
-                  tooltipText2.append(tmpString);
-
-                }
-                else
-                {
-                  tooltipText2.append("; " + tmpString);
-                }
-              }
-            }
-            // check score should be shown
-            if (features[i].getScore() != Float.NaN)
-            {
-              float[][] rng = (minmax == null) ? null : ((float[][]) minmax
-                      .get(features[i].getType()));
-              if (rng != null && rng[0] != null && rng[0][0] != rng[0][1])
-              {
-                tooltipText2.append(" Score=" + features[i].getScore());
-              }
-            }
-            if (features[i].getValue("status") != null)
-            {
-              String status = features[i].getValue("status").toString();
-              if (status.length() > 0)
-              {
-                tooltipText2.append("; (" + features[i].getValue("status")
-                        + ")");
-              }
-            }
-          }
-          if (features[i].links != null)
-          {
-            tooltipText2.append(" <img src=\"" + linkImageURL + "\">");
-          }
-
-        }
-      }
-    }
-  }
 
   String lastTooltip;
 
diff --git a/src/jalview/io/SequenceAnnotationReport.java b/src/jalview/io/SequenceAnnotationReport.java
new file mode 100644 (file)
index 0000000..8642446
--- /dev/null
@@ -0,0 +1,357 @@
+package jalview.io;
+
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceI;
+import jalview.util.UrlLink;
+
+/**
+ * generate HTML reports for a sequence
+ * 
+ * @author jimp
+ */
+public class SequenceAnnotationReport
+{
+  final String linkImageURL;
+
+  public SequenceAnnotationReport(String linkImageURL)
+  {
+    this.linkImageURL = linkImageURL;
+  }
+
+  /**
+   * appends the features at rpos to the given stringbuffer ready for display in
+   * a tooltip
+   * 
+   * @param tooltipText2
+   * @param linkImageURL
+   * @param rpos
+   * @param features
+   *          TODO refactor to Jalview 'utilities' somehow.
+   */
+  public void appendFeatures(final StringBuffer tooltipText2, int rpos,
+          SequenceFeature[] features)
+  {
+    appendFeatures(tooltipText2, rpos, features, null);
+  }
+
+  public void appendFeatures(final StringBuffer tooltipText2, int rpos,
+          SequenceFeature[] features, Hashtable minmax)
+  {
+    String tmpString;
+    if (features != null)
+    {
+      for (int i = 0; i < features.length; i++)
+      {
+        if (features[i].getType().equals("disulfide bond"))
+        {
+          if (features[i].getBegin() == rpos
+                  || features[i].getEnd() == rpos)
+          {
+            if (tooltipText2.length() > 6)
+            {
+              tooltipText2.append("<br>");
+            }
+            tooltipText2.append("disulfide bond " + features[i].getBegin()
+                    + ":" + features[i].getEnd());
+          }
+        }
+        else
+        {
+          if (tooltipText2.length() > 6)
+          {
+            tooltipText2.append("<br>");
+          }
+          // TODO: remove this hack to display link only features
+          boolean linkOnly = features[i].getValue("linkonly") != null;
+          if (!linkOnly)
+          {
+            tooltipText2.append(features[i].getType() + " ");
+            if (rpos != 0)
+            {
+              // we are marking a positional feature
+              tooltipText2.append(features[i].begin);
+            }
+            if (features[i].begin != features[i].end)
+            {
+              tooltipText2.append(" " + features[i].end);
+            }
+
+            if (features[i].getDescription() != null
+                    && !features[i].description.equals(features[i]
+                            .getType()))
+            {
+              tmpString = features[i].getDescription();
+              String tmp2up = tmpString.toUpperCase();
+              int startTag = tmp2up.indexOf("<HTML>");
+              if (startTag > -1)
+              {
+                tmpString = tmpString.substring(startTag + 6);
+                tmp2up = tmp2up.substring(startTag + 6);
+              }
+              int endTag = tmp2up.indexOf("</BODY>");
+              if (endTag > -1)
+              {
+                tmpString = tmpString.substring(0, endTag);
+                tmp2up = tmp2up.substring(0, endTag);
+              }
+              endTag = tmp2up.indexOf("</HTML>");
+              if (endTag > -1)
+              {
+                tmpString = tmpString.substring(0, endTag);
+              }
+
+              if (startTag > -1)
+              {
+                tooltipText2.append("; " + tmpString);
+              }
+              else
+              {
+                if (tmpString.indexOf("<") > -1
+                        || tmpString.indexOf(">") > -1)
+                {
+                  // The description does not specify html is to
+                  // be used, so we must remove < > symbols
+                  tmpString = tmpString.replaceAll("<", "&lt;");
+                  tmpString = tmpString.replaceAll(">", "&gt;");
+
+                  tooltipText2.append("; ");
+                  tooltipText2.append(tmpString);
+
+                }
+                else
+                {
+                  tooltipText2.append("; " + tmpString);
+                }
+              }
+            }
+            // check score should be shown
+            if (features[i].getScore() != Float.NaN)
+            {
+              float[][] rng = (minmax == null) ? null : ((float[][]) minmax
+                      .get(features[i].getType()));
+              if (rng != null && rng[0] != null && rng[0][0] != rng[0][1])
+              {
+                tooltipText2.append(" Score=" + features[i].getScore());
+              }
+            }
+            if (features[i].getValue("status") != null)
+            {
+              String status = features[i].getValue("status").toString();
+              if (status.length() > 0)
+              {
+                tooltipText2.append("; (" + features[i].getValue("status")
+                        + ")");
+              }
+            }
+          }
+        }
+        if (features[i].links != null)
+        {
+          if (linkImageURL != null)
+          {
+            tooltipText2.append(" <img src=\"" + linkImageURL + "\">");
+          }
+          else
+          {
+            for (String urlstring : (Vector<String>) features[i].links)
+            {
+              try
+              {
+                for (String[] urllink : createLinksFrom(null, urlstring))
+                {
+                  tooltipText2.append("<br/> <a href=\"" + urllink[3]
+                          + "\" target=\"" + urllink[0] + "\">"
+                          + (urllink[0].toLowerCase().equals(urllink[1].toLowerCase()) ? urllink[0] : (urllink[0]+ ":" + urllink[1])) + "</a></br>");
+                }
+              } catch (Exception x)
+              {
+                System.err.println("problem when creating links from "
+                        + urlstring);
+                x.printStackTrace();
+              }
+            }
+          }
+
+        }
+      }
+    }
+  }
+
+  /**
+   * 
+   * @param seq
+   * @param link
+   * @return String[][] { String[] { link target, link label, dynamic component
+   *         inserted (if any), url }}
+   */
+  public String[][] createLinksFrom(SequenceI seq, String link)
+  {
+    ArrayList<String[]> urlSets = new ArrayList<String[]>();
+    ArrayList<String> uniques=new ArrayList<String>();
+    UrlLink urlLink = new UrlLink(link);
+    if (!urlLink.isValid())
+    {
+      System.err.println(urlLink.getInvalidMessage());
+      return null;
+    }
+    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.getDBRef(),
+              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)
+            {
+              String unq=urls[u]+"|"+urls[u+1];
+              if (!uniques.contains(unq))
+              {
+                urlSets.add(new String[]
+                        { target, label, urls[u], urls[u + 1] });
+                uniques.add(unq);
+              }
+            }
+          }
+        }
+      }
+      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)
+          {
+            String unq=urls[u]+"|"+urls[u+1];
+            if (!uniques.contains(unq))
+            {
+              urlSets.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))
+            {
+              urlSets.add(new String[]
+            { target, label, urls[u], urls[u + 1] });
+              uniques.add(unq);
+            }
+          }
+        }
+      }
+
+    } else {
+      String unq=label + "|" + urlLink.getUrl_prefix();
+      if (!uniques.contains(unq)){
+        uniques.add(unq);
+        // Add a non-dynamic link
+        urlSets.add(new String[] {target, label, null, urlLink.getUrl_prefix()});
+      }
+    }
+
+    return urlSets.toArray(new String[][]
+    {});
+  }
+
+
+  public void createSequenceAnnotationReport(final StringBuffer tip,
+          SequenceI sequence, boolean showDbRefs, boolean showNpFeats,
+          Hashtable minmax)
+  {
+    createSequenceAnnotationReport(tip, sequence, showDbRefs, showNpFeats, true, minmax);
+  }
+
+  public void createSequenceAnnotationReport(final StringBuffer tip,
+          SequenceI sequence, boolean showDbRefs, boolean showNpFeats, boolean tableWrap,
+          Hashtable minmax)
+  {
+    String tmp;
+    tip.append("<i>");
+
+    int maxWidth = 0;
+    if (sequence.getDescription() != null)
+    {
+      tmp = sequence.getDescription();
+      tip.append("<br>" + tmp);
+      maxWidth = Math.max(maxWidth, tmp.length());
+    }
+
+    DBRefEntry[] dbrefs = sequence.getDatasetSequence().getDBRef();
+    if (showDbRefs && dbrefs != null)
+    {
+      for (int i = 0; i < dbrefs.length; i++)
+      {
+        tip.append("<br>");
+        tmp = dbrefs[i].getSource() + " " + dbrefs[i].getAccessionId();
+        tip.append(tmp);
+        maxWidth = Math.max(maxWidth, tmp.length());
+      }
+    }
+
+    // ADD NON POSITIONAL SEQUENCE INFO
+    SequenceFeature[] features = sequence.getDatasetSequence()
+            .getSequenceFeatures();
+    SequenceFeature[] tfeat = new SequenceFeature[1];
+    if (showNpFeats && features != null)
+    {
+      for (int i = 0; i < features.length; i++)
+      {
+        if (features[i].begin == 0 && features[i].end == 0)
+        {
+          int sz = -tip.length();
+          tfeat[0] = features[i];
+          appendFeatures(tip, 0, tfeat, minmax);
+          sz += tip.length();
+          maxWidth = Math.max(maxWidth, sz);
+        }
+      }
+    }
+
+    if (tableWrap && maxWidth > 60)
+    {
+      tip.insert(0, "<table width=350 border=0><tr><td><i>");
+      tip.append("</i></td></tr></table>");
+    }
+
+  }
+}