Merge branch 'develop' into merged_2_11_2_0_to_2_12
[jalview.git] / src / jalview / io / SequenceAnnotationReport.java
index bf3cd45..a287cb8 100644 (file)
  */
 package jalview.io;
 
-import java.util.Arrays;
+import java.util.ArrayList;
+
 import java.util.Collection;
 import java.util.Comparator;
 import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 
 import jalview.api.FeatureColourI;
@@ -59,9 +61,7 @@ public class SequenceAnnotationReport
 
   private static String linkImageURL;
 
-  private static final String[][] PRIMARY_SOURCES = new String[][] {
-      DBRefSource.CODINGDBS, DBRefSource.DNACODINGDBS,
-      DBRefSource.PROTEINDBS };
+ // public static final String[][] PRIMARY_SOURCES  moved to DBRefSource.java
 
   /*
    * Comparator to order DBRefEntry by Source + accession id (case-insensitive),
@@ -83,8 +83,8 @@ public class SequenceAnnotationReport
       }
       String s1 = ref1.getSource();
       String s2 = ref2.getSource();
-      boolean s1Primary = isPrimarySource(s1);
-      boolean s2Primary = isPrimarySource(s2);
+      boolean s1Primary = DBRefSource.isPrimarySource(s1);
+      boolean s2Primary = DBRefSource.isPrimarySource(s2);
       if (s1Primary && !s2Primary)
       {
         return -1;
@@ -105,20 +105,20 @@ public class SequenceAnnotationReport
       return comp;
     }
 
-    private boolean isPrimarySource(String source)
-    {
-      for (String[] primary : PRIMARY_SOURCES)
-      {
-        for (String s : primary)
-        {
-          if (source.equals(s))
-          {
-            return true;
-          }
-        }
-      }
-      return false;
-    }
+//    private boolean isPrimarySource(String source)
+//    {
+//      for (String[] primary : DBRefSource.PRIMARY_SOURCES)
+//      {
+//        for (String s : primary)
+//        {
+//          if (source.equals(s))
+//          {
+//            return true;
+//          }
+//        }
+//      }
+//      return false;
+//    }
   };
 
   private boolean forTooltip;
@@ -211,12 +211,27 @@ public class SequenceAnnotationReport
      * if this is a virtual features, convert begin/end to the
      * coordinates of the sequence it is mapped to
      */
-    int[] beginRange = null;
-    int[] endRange = null;
+    int[] beginRange = null; // feature start in local coordinates
+    int[] endRange = null; // feature end in local coordinates
     if (mf != null)
     {
-      beginRange = mf.getMappedPositions(begin, begin);
-      endRange = mf.getMappedPositions(end, end);
+      if (feature.isContactFeature())
+      {
+        /*
+         * map start and end points individually
+         */
+        beginRange = mf.getMappedPositions(begin, begin);
+        endRange = begin == end ? beginRange
+                : mf.getMappedPositions(end, end);
+      }
+      else
+      {
+        /*
+         * map the feature extent
+         */
+        beginRange = mf.getMappedPositions(begin, end);
+        endRange = beginRange;
+      }
       if (beginRange == null || endRange == null)
       {
         // something went wrong
@@ -277,10 +292,12 @@ public class SequenceAnnotationReport
          * truncate overlong descriptions unless they contain an href
          * before the truncation point (as truncation could leave corrupted html)
          */
-        int linkindex = description.toLowerCase().indexOf("<a ");
+        int linkindex = description.toLowerCase(Locale.ROOT).indexOf("<a ");
         boolean hasLink = linkindex > -1
                 && linkindex < MAX_DESCRIPTION_LENGTH;
-        if (description.length() > MAX_DESCRIPTION_LENGTH && !hasLink)
+        if (
+                // BH suggestion maxlength == 0 && 
+                description.length() > MAX_DESCRIPTION_LENGTH && !hasLink)
         {
           description = description.substring(0, MAX_DESCRIPTION_LENGTH)
                   + ELLIPSIS;
@@ -399,16 +416,16 @@ public class SequenceAnnotationReport
           {
             for (List<String> urllink : createLinksFrom(null, urlstring))
             {
-              sb.append("<br/> <a href=\""
+              sb.append("<br> <a href=\""
                       + urllink.get(3)
                       + "\" target=\""
                       + urllink.get(0)
                       + "\">"
-                      + (urllink.get(0).toLowerCase()
-                              .equals(urllink.get(1).toLowerCase()) ? urllink
+                      + (urllink.get(0).toLowerCase(Locale.ROOT)
+                              .equals(urllink.get(1).toLowerCase(Locale.ROOT)) ? urllink
                               .get(0) : (urllink.get(0) + ":" + urllink
                                               .get(1)))
-                      + "</a><br/>");
+                      + "</a><br>");
             }
           } catch (Exception x)
           {
@@ -482,7 +499,7 @@ public class SequenceAnnotationReport
       sb.append(tmp);
       maxWidth = Math.max(maxWidth, tmp.length());
     }
-
+    sb.append("\n");
     SequenceI ds = sequence;
     while (ds.getDatasetSequence() != null)
     {
@@ -502,11 +519,11 @@ public class SequenceAnnotationReport
                 .append(aa.getScore());
       }
     }
-
     if (showDbRefs)
     {
       maxWidth = Math.max(maxWidth, appendDbRefs(sb, ds, summary));
     }
+    sb.append("\n");
 
     /*
      * add non-positional features if wanted
@@ -522,8 +539,6 @@ public class SequenceAnnotationReport
         maxWidth = Math.max(maxWidth, sz);
       }
     }
-
-
     if (sequence.getAnnotation("Search Scores") != null)
     {
       sb.append("<br>");
@@ -539,7 +554,6 @@ public class SequenceAnnotationReport
     }
     sb.append("<br>");
     sb.append("</i>");
-
     return maxWidth;
   }
 
@@ -555,14 +569,20 @@ public class SequenceAnnotationReport
   protected int appendDbRefs(final StringBuilder sb, SequenceI ds,
           boolean summary)
   {
-    DBRefEntry[] dbrefs = ds.getDBRefs();
-    if (dbrefs == null)
+    List<DBRefEntry> dbrefs, dbrefset = ds.getDBRefs();
+
+    if (dbrefset == null)
     {
       return 0;
     }
 
+    // PATCH for JAL-3980 defensive copy
+
+    dbrefs = new ArrayList<DBRefEntry>();
+
+    dbrefs.addAll(dbrefset);
     // note this sorts the refs held on the sequence!
-    Arrays.sort(dbrefs, comparator);
+    dbrefs.sort(comparator);
     boolean ellipsis = false;
     String source = null;
     String lastSource = null;
@@ -597,7 +617,7 @@ public class SequenceAnnotationReport
       countForSource++;
       if (countForSource == 1 || !summary)
       {
-        sb.append("<br/>");
+        sb.append("<br/>\n");
       }
       if (countForSource <= MAX_REFS_PER_SOURCE || !summary)
       {
@@ -605,7 +625,7 @@ public class SequenceAnnotationReport
         lineLength += accessionId.length() + 1;
         if (countForSource > 1 && summary)
         {
-          sb.append(", ").append(accessionId);
+          sb.append(",\n ").append(accessionId);
           lineLength++;
         }
         else
@@ -623,11 +643,11 @@ public class SequenceAnnotationReport
     }
     if (moreSources)
     {
-      sb.append("<br/>").append(source).append(COMMA).append(ELLIPSIS);
+      sb.append("<br/>\n").append(source).append(COMMA).append(ELLIPSIS);
     }
     if (ellipsis)
     {
-      sb.append("<br/>(");
+      sb.append("<br/>\n(");
       sb.append(MessageManager.getString("label.output_seq_details"));
       sb.append(")");
     }