formatting
[jalview.git] / src / jalview / io / SequenceAnnotationReport.java
1 package jalview.io;
2
3 import java.util.ArrayList;
4 import java.util.Hashtable;
5 import java.util.Vector;
6
7 import jalview.datamodel.DBRefEntry;
8 import jalview.datamodel.SequenceFeature;
9 import jalview.datamodel.SequenceI;
10 import jalview.util.UrlLink;
11
12 /**
13  * generate HTML reports for a sequence
14  * 
15  * @author jimp
16  */
17 public class SequenceAnnotationReport
18 {
19   final String linkImageURL;
20
21   public SequenceAnnotationReport(String linkImageURL)
22   {
23     this.linkImageURL = linkImageURL;
24   }
25
26   /**
27    * appends the features at rpos to the given stringbuffer ready for display in
28    * a tooltip
29    * 
30    * @param tooltipText2
31    * @param linkImageURL
32    * @param rpos
33    * @param features
34    *          TODO refactor to Jalview 'utilities' somehow.
35    */
36   public void appendFeatures(final StringBuffer tooltipText2, int rpos,
37           SequenceFeature[] features)
38   {
39     appendFeatures(tooltipText2, rpos, features, null);
40   }
41
42   public void appendFeatures(final StringBuffer tooltipText2, int rpos,
43           SequenceFeature[] features, Hashtable minmax)
44   {
45     String tmpString;
46     if (features != null)
47     {
48       for (int i = 0; i < features.length; i++)
49       {
50         if (features[i].getType().equals("disulfide bond"))
51         {
52           if (features[i].getBegin() == rpos
53                   || features[i].getEnd() == rpos)
54           {
55             if (tooltipText2.length() > 6)
56             {
57               tooltipText2.append("<br>");
58             }
59             tooltipText2.append("disulfide bond " + features[i].getBegin()
60                     + ":" + features[i].getEnd());
61           }
62         }
63         else
64         {
65           if (tooltipText2.length() > 6)
66           {
67             tooltipText2.append("<br>");
68           }
69           // TODO: remove this hack to display link only features
70           boolean linkOnly = features[i].getValue("linkonly") != null;
71           if (!linkOnly)
72           {
73             tooltipText2.append(features[i].getType() + " ");
74             if (rpos != 0)
75             {
76               // we are marking a positional feature
77               tooltipText2.append(features[i].begin);
78             }
79             if (features[i].begin != features[i].end)
80             {
81               tooltipText2.append(" " + features[i].end);
82             }
83
84             if (features[i].getDescription() != null
85                     && !features[i].description.equals(features[i]
86                             .getType()))
87             {
88               tmpString = features[i].getDescription();
89               String tmp2up = tmpString.toUpperCase();
90               int startTag = tmp2up.indexOf("<HTML>");
91               if (startTag > -1)
92               {
93                 tmpString = tmpString.substring(startTag + 6);
94                 tmp2up = tmp2up.substring(startTag + 6);
95               }
96               int endTag = tmp2up.indexOf("</BODY>");
97               if (endTag > -1)
98               {
99                 tmpString = tmpString.substring(0, endTag);
100                 tmp2up = tmp2up.substring(0, endTag);
101               }
102               endTag = tmp2up.indexOf("</HTML>");
103               if (endTag > -1)
104               {
105                 tmpString = tmpString.substring(0, endTag);
106               }
107
108               if (startTag > -1)
109               {
110                 tooltipText2.append("; " + tmpString);
111               }
112               else
113               {
114                 if (tmpString.indexOf("<") > -1
115                         || tmpString.indexOf(">") > -1)
116                 {
117                   // The description does not specify html is to
118                   // be used, so we must remove < > symbols
119                   tmpString = tmpString.replaceAll("<", "&lt;");
120                   tmpString = tmpString.replaceAll(">", "&gt;");
121
122                   tooltipText2.append("; ");
123                   tooltipText2.append(tmpString);
124
125                 }
126                 else
127                 {
128                   tooltipText2.append("; " + tmpString);
129                 }
130               }
131             }
132             // check score should be shown
133             if (features[i].getScore() != Float.NaN)
134             {
135               float[][] rng = (minmax == null) ? null : ((float[][]) minmax
136                       .get(features[i].getType()));
137               if (rng != null && rng[0] != null && rng[0][0] != rng[0][1])
138               {
139                 tooltipText2.append(" Score=" + features[i].getScore());
140               }
141             }
142             if (features[i].getValue("status") != null)
143             {
144               String status = features[i].getValue("status").toString();
145               if (status.length() > 0)
146               {
147                 tooltipText2.append("; (" + features[i].getValue("status")
148                         + ")");
149               }
150             }
151           }
152         }
153         if (features[i].links != null)
154         {
155           if (linkImageURL != null)
156           {
157             tooltipText2.append(" <img src=\"" + linkImageURL + "\">");
158           }
159           else
160           {
161             for (String urlstring : (Vector<String>) features[i].links)
162             {
163               try
164               {
165                 for (String[] urllink : createLinksFrom(null, urlstring))
166                 {
167                   tooltipText2.append("<br/> <a href=\""
168                           + urllink[3]
169                           + "\" target=\""
170                           + urllink[0]
171                           + "\">"
172                           + (urllink[0].toLowerCase().equals(
173                                   urllink[1].toLowerCase()) ? urllink[0]
174                                   : (urllink[0] + ":" + urllink[1]))
175                           + "</a></br>");
176                 }
177               } catch (Exception x)
178               {
179                 System.err.println("problem when creating links from "
180                         + urlstring);
181                 x.printStackTrace();
182               }
183             }
184           }
185
186         }
187       }
188     }
189   }
190
191   /**
192    * 
193    * @param seq
194    * @param link
195    * @return String[][] { String[] { link target, link label, dynamic component
196    *         inserted (if any), url }}
197    */
198   public String[][] createLinksFrom(SequenceI seq, String link)
199   {
200     ArrayList<String[]> urlSets = new ArrayList<String[]>();
201     ArrayList<String> uniques = new ArrayList<String>();
202     UrlLink urlLink = new UrlLink(link);
203     if (!urlLink.isValid())
204     {
205       System.err.println(urlLink.getInvalidMessage());
206       return null;
207     }
208     final String target = urlLink.getTarget(); // link.substring(0,
209     // link.indexOf("|"));
210     final String label = urlLink.getLabel();
211     if (seq != null && urlLink.isDynamic())
212     {
213
214       // collect matching db-refs
215       DBRefEntry[] dbr = jalview.util.DBRefUtils.selectRefs(seq.getDBRef(),
216               new String[]
217               { target });
218       // collect id string too
219       String id = seq.getName();
220       String descr = seq.getDescription();
221       if (descr != null && descr.length() < 1)
222       {
223         descr = null;
224       }
225       if (dbr != null)
226       {
227         for (int r = 0; r < dbr.length; r++)
228         {
229           if (id != null && dbr[r].getAccessionId().equals(id))
230           {
231             // suppress duplicate link creation for the bare sequence ID
232             // string with this link
233             id = null;
234           }
235           // create Bare ID link for this RUL
236           String[] urls = urlLink.makeUrls(dbr[r].getAccessionId(), true);
237           if (urls != null)
238           {
239             for (int u = 0; u < urls.length; u += 2)
240             {
241               String unq = urls[u] + "|" + urls[u + 1];
242               if (!uniques.contains(unq))
243               {
244                 urlSets.add(new String[]
245                 { target, label, urls[u], urls[u + 1] });
246                 uniques.add(unq);
247               }
248             }
249           }
250         }
251       }
252       if (id != null)
253       {
254         // create Bare ID link for this RUL
255         String[] urls = urlLink.makeUrls(id, true);
256         if (urls != null)
257         {
258           for (int u = 0; u < urls.length; u += 2)
259           {
260             String unq = urls[u] + "|" + urls[u + 1];
261             if (!uniques.contains(unq))
262             {
263               urlSets.add(new String[]
264               { target, label, urls[u], urls[u + 1] });
265               uniques.add(unq);
266             }
267           }
268         }
269       }
270       if (descr != null && urlLink.getRegexReplace() != null)
271       {
272         // create link for this URL from description only if regex matches
273         String[] urls = urlLink.makeUrls(descr, true);
274         if (urls != null)
275         {
276           for (int u = 0; u < urls.length; u += 2)
277           {
278             String unq = urls[u] + "|" + urls[u + 1];
279             if (!uniques.contains(unq))
280             {
281               urlSets.add(new String[]
282               { target, label, urls[u], urls[u + 1] });
283               uniques.add(unq);
284             }
285           }
286         }
287       }
288
289     }
290     else
291     {
292       String unq = label + "|" + urlLink.getUrl_prefix();
293       if (!uniques.contains(unq))
294       {
295         uniques.add(unq);
296         // Add a non-dynamic link
297         urlSets.add(new String[]
298         { target, label, null, urlLink.getUrl_prefix() });
299       }
300     }
301
302     return urlSets.toArray(new String[][]
303     {});
304   }
305
306   public void createSequenceAnnotationReport(final StringBuffer tip,
307           SequenceI sequence, boolean showDbRefs, boolean showNpFeats,
308           Hashtable minmax)
309   {
310     createSequenceAnnotationReport(tip, sequence, showDbRefs, showNpFeats,
311             true, minmax);
312   }
313
314   public void createSequenceAnnotationReport(final StringBuffer tip,
315           SequenceI sequence, boolean showDbRefs, boolean showNpFeats,
316           boolean tableWrap, Hashtable minmax)
317   {
318     String tmp;
319     tip.append("<i>");
320
321     int maxWidth = 0;
322     if (sequence.getDescription() != null)
323     {
324       tmp = sequence.getDescription();
325       tip.append("<br>" + tmp);
326       maxWidth = Math.max(maxWidth, tmp.length());
327     }
328     SequenceI ds = sequence;
329     while (ds.getDatasetSequence() != null)
330     {
331       ds = ds.getDatasetSequence();
332     }
333     DBRefEntry[] dbrefs = ds.getDBRef();
334     if (showDbRefs && dbrefs != null)
335     {
336       for (int i = 0; i < dbrefs.length; i++)
337       {
338         tip.append("<br>");
339         tmp = dbrefs[i].getSource() + " " + dbrefs[i].getAccessionId();
340         tip.append(tmp);
341         maxWidth = Math.max(maxWidth, tmp.length());
342       }
343     }
344
345     // ADD NON POSITIONAL SEQUENCE INFO
346     SequenceFeature[] features = ds.getSequenceFeatures();
347     SequenceFeature[] tfeat = new SequenceFeature[1];
348     if (showNpFeats && features != null)
349     {
350       for (int i = 0; i < features.length; i++)
351       {
352         if (features[i].begin == 0 && features[i].end == 0)
353         {
354           int sz = -tip.length();
355           tfeat[0] = features[i];
356           appendFeatures(tip, 0, tfeat, minmax);
357           sz += tip.length();
358           maxWidth = Math.max(maxWidth, sz);
359         }
360       }
361     }
362
363     if (tableWrap && maxWidth > 60)
364     {
365       tip.insert(0, "<table width=350 border=0><tr><td><i>");
366       tip.append("</i></td></tr></table>");
367     }
368
369   }
370 }