Merge branch 'develop' into bug/JAL-2323disulfideOverview
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 21 Nov 2016 11:02:04 +0000 (11:02 +0000)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 21 Nov 2016 11:02:04 +0000 (11:02 +0000)
Conflicts:
src/jalview/io/SequenceAnnotationReport.java

1  2 
src/jalview/io/SequenceAnnotationReport.java

  package jalview.io;
  
  import jalview.datamodel.DBRefEntry;
+ import jalview.datamodel.DBRefSource;
  import jalview.datamodel.SequenceFeature;
  import jalview.datamodel.SequenceI;
  import jalview.io.gff.GffConstants;
+ import jalview.util.MessageManager;
  import jalview.util.UrlLink;
  
- import java.util.ArrayList;
+ import java.util.Arrays;
  import java.util.Collection;
+ import java.util.Comparator;
  import java.util.LinkedHashMap;
  import java.util.List;
  import java.util.Map;
   */
  public class SequenceAnnotationReport
  {
+   private static final String COMMA = ",";
+   private static final String ELLIPSIS = "...";
+   private static final int MAX_REFS_PER_SOURCE = 4;
+   private static final int MAX_SOURCES = 40;
+   private static final String[][] PRIMARY_SOURCES = new String[][] {
+       DBRefSource.CODINGDBS, DBRefSource.DNACODINGDBS,
+       DBRefSource.PROTEINDBS };
    final String linkImageURL;
  
+   /*
+    * Comparator to order DBRefEntry by Source + accession id (case-insensitive)
+    */
+   private static Comparator<DBRefEntry> comparator = new Comparator<DBRefEntry>()
+   {
+     @Override
+     public int compare(DBRefEntry ref1, DBRefEntry ref2)
+     {
+       String s1 = ref1.getSource();
+       String s2 = ref2.getSource();
+       boolean s1Primary = isPrimarySource(s1);
+       boolean s2Primary = isPrimarySource(s2);
+       if (s1Primary && !s2Primary)
+       {
+         return -1;
+       }
+       if (!s1Primary && s2Primary)
+       {
+         return 1;
+       }
+       int comp = s1 == null ? -1 : (s2 == null ? 1 : s1
+               .compareToIgnoreCase(s2));
+       if (comp == 0)
+       {
+         String a1 = ref1.getAccessionId();
+         String a2 = ref2.getAccessionId();
+         comp = a1 == null ? -1 : (a2 == null ? 1 : a1
+                 .compareToIgnoreCase(a2));
+       }
+       return comp;
+     }
+     private boolean isPrimarySource(String source)
+     {
+       for (String[] primary : PRIMARY_SOURCES)
+       {
+         for (String s : primary)
+         {
+           if (source.equals(s))
+           {
+             return true;
+           }
+         }
+       }
+       return false;
+     }
+   };
    public SequenceAnnotationReport(String linkImageURL)
    {
      this.linkImageURL = linkImageURL;
    /**
     * Append text for the list of features to the tooltip
     * 
-    * @param tooltipText2
+    * @param sb
     * @param rpos
     * @param features
     * @param minmax
     */
-   public void appendFeatures(final StringBuffer tooltipText2, int rpos,
+   public void appendFeatures(final StringBuilder sb, int rpos,
            List<SequenceFeature> features, Map<String, float[][]> minmax)
    {
      if (features != null)
      {
        for (SequenceFeature feature : features)
        {
-         appendFeature(tooltipText2, rpos, minmax, feature);
+         appendFeature(sb, rpos, minmax, feature);
        }
      }
    }
  
    /**
-    * Appends text for one sequence feature to the string buffer
+    * Appends the feature at rpos to the given buffer
     * 
     * @param sb
     * @param rpos
     * @param minmax
-    *          {{min, max}, {min, max}} positional and non-positional feature
-    *          scores for this type
     * @param feature
     */
-   void appendFeature(final StringBuffer sb, int rpos,
+   void appendFeature(final StringBuilder sb, int rpos,
            Map<String, float[][]> minmax, SequenceFeature feature)
    {
 -    String tmpString;
 -    if (feature.getType().equals("disulfide bond"))
 +    if (feature.isContactFeature())
      {
        if (feature.getBegin() == rpos || feature.getEnd() == rpos)
        {
          {
            sb.append("<br>");
          }
 -        sb.append("disulfide bond ").append(feature.getBegin()).append(":")
 +        sb.append(feature.getType()).append(" ").append(feature.getBegin())
 +                .append(":")
                  .append(feature.getEnd());
        }
      }
          }
          if (feature.begin != feature.end)
          {
-           sb.append(" " + feature.end);
+           sb.append(" ").append(feature.end);
          }
  
          if (feature.getDescription() != null
                  && !feature.description.equals(feature.getType()))
          {
 -          tmpString = feature.getDescription();
 +          String tmpString = feature.getDescription();
            String tmp2up = tmpString.toUpperCase();
-           final int startTag = tmp2up.indexOf("<HTML>");
+           int startTag = tmp2up.indexOf("<HTML>");
            if (startTag > -1)
            {
              tmpString = tmpString.substring(startTag + 6);
              tmp2up = tmp2up.substring(startTag + 6);
            }
-           // TODO strips off </body> but not <body> - is that intended?
            int endTag = tmp2up.indexOf("</BODY>");
            if (endTag > -1)
            {
                // be used, so we must remove < > symbols
                tmpString = tmpString.replaceAll("<", "&lt;");
                tmpString = tmpString.replaceAll(">", "&gt;");
-               sb.append("; ").append(tmpString);
+               sb.append("; ");
+               sb.append(tmpString);
              }
              else
              {
              }
            }
          }
-         /*
-          * score should be shown if there is one, and min != max
-          * for this feature type (e.g. not all 0)
-          */
+         // check score should be shown
          if (!Float.isNaN(feature.getScore()))
          {
 -          float[][] rng = (minmax == null) ? null : ((float[][]) minmax
 -                  .get(feature.getType()));
 +          float[][] rng = (minmax == null) ? null : minmax.get(feature
 +                  .getType());
            if (rng != null && rng[0] != null && rng[0][0] != rng[0][1])
            {
 -            sb.append(" Score=" + feature.getScore());
 +            sb.append(" Score=").append(String.valueOf(feature.getScore()));
            }
          }
          String status = (String) feature.getValue("status");
          }
        }
      }
-     appendLinks(sb, feature);
    }
  
    /**
      return urlSets.values();
    }
  
-   public void createSequenceAnnotationReport(final StringBuffer tip,
+   public void createSequenceAnnotationReport(final StringBuilder tip,
            SequenceI sequence, boolean showDbRefs, boolean showNpFeats,
            Map<String, float[][]> minmax)
    {
      createSequenceAnnotationReport(tip, sequence, showDbRefs, showNpFeats,
-             true, minmax);
+             minmax, false);
    }
  
-   public void createSequenceAnnotationReport(final StringBuffer tip,
+   /**
+    * Builds an html formatted report of sequence details and appends it to the
+    * provided buffer.
+    * 
+    * @param sb
+    *          buffer to append report to
+    * @param sequence
+    *          the sequence the report is for
+    * @param showDbRefs
+    *          whether to include database references for the sequence
+    * @param showNpFeats
+    *          whether to include non-positional sequence features
+    * @param minmax
+    * @param summary
+    * @return
+    */
+   int createSequenceAnnotationReport(final StringBuilder sb,
            SequenceI sequence, boolean showDbRefs, boolean showNpFeats,
-           boolean tableWrap, Map<String, float[][]> minmax)
+           Map<String, float[][]> minmax, boolean summary)
    {
      String tmp;
-     tip.append("<i>");
+     sb.append("<i>");
  
      int maxWidth = 0;
      if (sequence.getDescription() != null)
      {
        tmp = sequence.getDescription();
-       tip.append("<br>" + tmp);
+       sb.append("<br>").append(tmp);
        maxWidth = Math.max(maxWidth, tmp.length());
      }
      SequenceI ds = sequence;
      DBRefEntry[] dbrefs = ds.getDBRefs();
      if (showDbRefs && dbrefs != null)
      {
-       for (int i = 0; i < dbrefs.length; i++)
+       // note this sorts the refs held on the sequence!
+       Arrays.sort(dbrefs, comparator);
+       boolean ellipsis = false;
+       String source = null;
+       String lastSource = null;
+       int countForSource = 0;
+       int sourceCount = 0;
+       boolean moreSources = false;
+       int lineLength = 0;
+       for (DBRefEntry ref : dbrefs)
+       {
+         source = ref.getSource();
+         if (source == null)
+         {
+           // shouldn't happen
+           continue;
+         }
+         boolean sourceChanged = !source.equals(lastSource);
+         if (sourceChanged)
+         {
+           lineLength = 0;
+           countForSource = 0;
+           sourceCount++;
+         }
+         if (sourceCount > MAX_SOURCES && summary)
+         {
+           ellipsis = true;
+           moreSources = true;
+           break;
+         }
+         lastSource = source;
+         countForSource++;
+         if (countForSource == 1 || !summary)
+         {
+           sb.append("<br>");
+         }
+         if (countForSource <= MAX_REFS_PER_SOURCE || !summary)
+         {
+           String accessionId = ref.getAccessionId();
+           lineLength += accessionId.length() + 1;
+           if (countForSource > 1 && summary)
+           {
+             sb.append(", ").append(accessionId);
+             lineLength++;
+           }
+           else
+           {
+             sb.append(source).append(" ").append(accessionId);
+             lineLength += source.length();
+           }
+           maxWidth = Math.max(maxWidth, lineLength);
+         }
+         if (countForSource == MAX_REFS_PER_SOURCE && summary)
+         {
+           sb.append(COMMA).append(ELLIPSIS);
+           ellipsis = true;
+         }
+       }
+       if (moreSources)
        {
-         tip.append("<br>");
-         tmp = dbrefs[i].getSource() + " " + dbrefs[i].getAccessionId();
-         tip.append(tmp);
-         maxWidth = Math.max(maxWidth, tmp.length());
+         sb.append("<br>").append(ELLIPSIS).append(COMMA).append(source)
+                 .append(COMMA).append(ELLIPSIS);
+       }
+       if (ellipsis)
+       {
+         sb.append("<br>(");
+         sb.append(MessageManager.getString("label.output_seq_details"));
+         sb.append(")");
        }
      }
  
-     // ADD NON POSITIONAL SEQUENCE INFO
+     /*
+      * add non-positional features if wanted
+      */
      SequenceFeature[] features = sequence.getSequenceFeatures();
      if (showNpFeats && features != null)
      {
        {
          if (features[i].begin == 0 && features[i].end == 0)
          {
-           int sz = -tip.length();
-           List<SequenceFeature> tfeat = new ArrayList<SequenceFeature>();
-           tfeat.add(features[i]);
-           appendFeatures(tip, 0, tfeat, minmax);
-           sz += tip.length();
+           int sz = -sb.length();
+           appendFeature(sb, 0, minmax, features[i]);
+           sz += sb.length();
            maxWidth = Math.max(maxWidth, sz);
          }
        }
      }
+     sb.append("</i>");
+     return maxWidth;
+   }
+   public void createTooltipAnnotationReport(final StringBuilder tip,
+           SequenceI sequence, boolean showDbRefs, boolean showNpFeats,
+           Map<String, float[][]> minmax)
+   {
+     int maxWidth = createSequenceAnnotationReport(tip, sequence,
+             showDbRefs, showNpFeats, minmax, true);
  
-     if (tableWrap && maxWidth > 60)
+     if (maxWidth > 60)
      {
-       tip.insert(0, "<table width=350 border=0><tr><td><i>");
-       tip.append("</i></td></tr></table>");
+       // ? not sure this serves any useful purpose
+       // tip.insert(0, "<table width=350 border=0><tr><td>");
+       // tip.append("</td></tr></table>");
      }
    }
  }