JAL-2907 read/write underscore for annotation at gap positions
[jalview.git] / src / jalview / io / StockholmFile.java
index f5b5177..0388fda 100644 (file)
@@ -46,6 +46,7 @@ import java.util.Hashtable;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Vector;
 
 import com.stevesoft.pat.Regex;
@@ -74,11 +75,13 @@ import fr.orsay.lri.varna.models.rna.RNA;
  */
 public class StockholmFile extends AlignFile
 {
-  private static final String ANNOTATION = "annotation";
+  private static final char UNDERSCORE = '_';
 
-  private static final Regex OPEN_PAREN = new Regex("(<|\\[)", "(");
+  private static final String ANNOTATION = "annotation";
 
-  private static final Regex CLOSE_PAREN = new Regex("(>|\\])", ")");
+  // private static final Regex OPEN_PAREN = new Regex("(<|\\[)", "(");
+  //
+  // private static final Regex CLOSE_PAREN = new Regex("(>|\\])", ")");
 
   public static final Regex DETECT_BRACKETS = new Regex(
           "(<|>|\\[|\\]|\\(|\\)|\\{|\\})");
@@ -197,7 +200,7 @@ public class StockholmFile extends AlignFile
     String version;
     // String id;
     Hashtable seqAnn = new Hashtable(); // Sequence related annotations
-    LinkedHashMap<String, String> seqs = new LinkedHashMap<String, String>();
+    LinkedHashMap<String, String> seqs = new LinkedHashMap<>();
     Regex p, r, rend, s, x;
     // Temporary line for processing RNA annotation
     // String RNAannot = "";
@@ -658,7 +661,7 @@ public class StockholmFile extends AlignFile
               strucAnn = new Hashtable();
             }
 
-            Vector<AlignmentAnnotation> newStruc = new Vector<AlignmentAnnotation>();
+            Vector<AlignmentAnnotation> newStruc = new Vector<>();
             parseAnnotationRow(newStruc, type, ns);
             for (AlignmentAnnotation alan : newStruc)
             {
@@ -710,7 +713,7 @@ public class StockholmFile extends AlignFile
   private void guessDatabaseFor(Sequence seqO, String dbr, String dbsource)
   {
     DBRefEntry dbrf = null;
-    List<DBRefEntry> dbrs = new ArrayList<DBRefEntry>();
+    List<DBRefEntry> dbrs = new ArrayList<>();
     String seqdb = "Unknown", sdbac = "" + dbr;
     int st = -1, en = -1, p;
     if ((st = sdbac.indexOf("/")) > -1)
@@ -837,6 +840,10 @@ public class StockholmFile extends AlignFile
     for (int i = 0; i < annots.length(); i++)
     {
       String pos = annots.substring(i, i + 1);
+      if (UNDERSCORE == pos.charAt(0))
+      {
+        pos = " ";
+      }
       Annotation ann;
       ann = new Annotation(pos, "", ' ', 0f); // 0f is 'valid' null - will not
       // be written out
@@ -985,7 +992,6 @@ public class StockholmFile extends AlignFile
                 .form("#=GS " + idd.toString() + " "));
         if (type.contains("PFAM") || type.contains("RFAM"))
         {
-
           out.append(" AC " + type.substring(type.indexOf(";") + 1));
         }
         else
@@ -1028,7 +1034,7 @@ public class StockholmFile extends AlignFile
           String seq = "";
           for (int k = 0; k < ann.length; k++)
           {
-            seq += outputCharacter(key, k, isrna, ann, s[i]);
+            seq += outputCharacter(key, k, ann, s[i]);
           }
           out.append(seq);
           out.append(newline);
@@ -1080,10 +1086,9 @@ public class StockholmFile extends AlignFile
 
         out.append(
                 new Format("%-" + maxid + "s").form("#=GC " + label + " "));
-        boolean isrna = aa.isValidStruc();
         for (int j = 0; j < aa.annotations.length; j++)
         {
-          seq += outputCharacter(key, j, isrna, aa.annotations, null);
+          seq += outputCharacter(key, j, aa.annotations, null);
         }
         out.append(seq);
         out.append(newline);
@@ -1101,26 +1106,25 @@ public class StockholmFile extends AlignFile
    * 
    * @param seq
    * @param key
-   * @param k
-   * @param isrna
+   * @param column
    * @param ann
    * @param sequenceI
    */
-  private char outputCharacter(String key, int k, boolean isrna,
-          Annotation[] ann, SequenceI sequenceI)
+  static char outputCharacter(String key, int column, Annotation[] ann,
+          SequenceI sequenceI)
   {
-    char seq = ' ';
-    Annotation annot = ann[k];
+    Annotation annot = column >= ann.length ? null : ann[column];
     String ch = (annot == null)
             ? ((sequenceI == null) ? "-"
-                    : Character.toString(sequenceI.getCharAt(k)))
+                    : Character.toString(sequenceI.getCharAt(column)))
             : annot.displayCharacter;
-    if (key != null && key.equals("SS"))
+
+    if ("SS".equals(key))
     {
       if (annot == null)
       {
-        // sensible gap character
-        return ' ';
+        // whitespace not allowed in annotation
+        return UNDERSCORE;
       }
       else
       {
@@ -1132,6 +1136,7 @@ public class StockholmFile extends AlignFile
       }
     }
 
+    char seq = '0';
     if (ch.length() == 0)
     {
       seq = '.';
@@ -1140,7 +1145,7 @@ public class StockholmFile extends AlignFile
     {
       seq = ch.charAt(0);
     }
-    else if (ch.length() > 1)
+    else
     {
       seq = ch.charAt(1);
     }
@@ -1159,13 +1164,13 @@ public class StockholmFile extends AlignFile
     return out.toString();
   }
 
-  private static Hashtable typeIds = null;
+  private static Map<String, String> typeIds = null;
 
   static
   {
     if (typeIds == null)
     {
-      typeIds = new Hashtable();
+      typeIds = new Hashtable<>();
       typeIds.put("SS", "Secondary Structure");
       typeIds.put("SA", "Surface Accessibility");
       typeIds.put("TM", "transmembrane");
@@ -1181,7 +1186,6 @@ public class StockholmFile extends AlignFile
       typeIds.put("DR", "reference");
       typeIds.put("LO", "look");
       typeIds.put("RF", "Reference Positions");
-
     }
   }
 
@@ -1189,7 +1193,7 @@ public class StockholmFile extends AlignFile
   {
     if (typeIds.containsKey(id))
     {
-      return (String) typeIds.get(id);
+      return typeIds.get(id);
     }
     System.err.println(
             "Warning : Unknown Stockholm annotation type code " + id);
@@ -1199,20 +1203,13 @@ public class StockholmFile extends AlignFile
   protected static String type2id(String type)
   {
     String key = null;
-    Enumeration e = typeIds.keys();
-    while (e.hasMoreElements())
+    for (Entry<String, String> entry : typeIds.entrySet())
     {
-      Object ll = e.nextElement();
-      if (typeIds.get(ll).toString().equalsIgnoreCase(type))
+      if (entry.getValue().equalsIgnoreCase(type))
       {
-        key = (String) ll;
-        break;
+        return entry.getKey();
       }
     }
-    if (key != null)
-    {
-      return key;
-    }
     System.err.println(
             "Warning : Unknown Stockholm annotation type: " + type);
     return key;