JAL-3081 compiler warnings and formatting improvements
[jalview.git] / src / jalview / io / AnnotationFile.java
index 34fdabe..3d8096b 100755 (executable)
@@ -27,13 +27,15 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Annotation;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.GraphLine;
+import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.HiddenSequences;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.schemes.ColourSchemeI;
 import jalview.schemes.ColourSchemeProperty;
-import jalview.schemes.UserColourScheme;
+import jalview.util.ColorUtils;
 
+import java.awt.Color;
 import java.io.BufferedReader;
 import java.io.FileReader;
 import java.io.InputStreamReader;
@@ -42,9 +44,13 @@ import java.net.URL;
 import java.util.ArrayList;
 import java.util.BitSet;
 import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Hashtable;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.StringTokenizer;
 import java.util.Vector;
 
@@ -98,7 +104,8 @@ public class AnnotationFile
   public String printAnnotations(AlignmentAnnotation[] annotations,
           List<SequenceGroup> list, Hashtable properties)
   {
-    return printAnnotations(annotations, list, properties, null, null, null);
+    return printAnnotations(annotations, list, properties, null, null,
+            null);
 
   }
 
@@ -108,23 +115,22 @@ public class AnnotationFile
    */
   public class ViewDef
   {
-    public String viewname;
+    // TODO this class is not used - remove?
+    public final String viewname;
 
-    public HiddenSequences hidseqs;
+    public final HiddenSequences hidseqs;
 
-    public ColumnSelection hiddencols;
+    public final HiddenColumns hiddencols;
 
-    public Vector visibleGroups;
+    public final Hashtable hiddenRepSeqs;
 
-    public Hashtable hiddenRepSeqs;
-
-    public ViewDef(String viewname, HiddenSequences hidseqs,
-            ColumnSelection hiddencols, Hashtable hiddenRepSeqs)
+    public ViewDef(String vname, HiddenSequences hseqs, HiddenColumns hcols,
+            Hashtable hRepSeqs)
     {
-      this.viewname = viewname;
-      this.hidseqs = hidseqs;
-      this.hiddencols = hiddencols;
-      this.hiddenRepSeqs = hiddenRepSeqs;
+      this.viewname = vname;
+      this.hidseqs = hseqs;
+      this.hiddencols = hcols;
+      this.hiddenRepSeqs = hRepSeqs;
     }
   }
 
@@ -139,8 +145,8 @@ public class AnnotationFile
    * @return annotation file
    */
   public String printAnnotations(AlignmentAnnotation[] annotations,
-          List<SequenceGroup> list, Hashtable properties,
-          ColumnSelection cs, AlignmentI al, ViewDef view)
+          List<SequenceGroup> list, Hashtable properties, HiddenColumns cs,
+          AlignmentI al, ViewDef view)
   {
     if (view != null)
     {
@@ -150,7 +156,7 @@ public class AnnotationFile
       }
       if (list == null)
       {
-        list = view.visibleGroups;
+        // list = view.visibleGroups;
       }
       if (cs == null)
       {
@@ -169,22 +175,9 @@ public class AnnotationFile
     if (cs != null && cs.hasHiddenColumns())
     {
       text.append("VIEW_HIDECOLS\t");
-      List<int[]> hc = cs.getHiddenColumns();
-      boolean comma = false;
-      for (int[] r : hc)
-      {
-        if (!comma)
-        {
-          comma = true;
-        }
-        else
-        {
-          text.append(",");
-        }
-        text.append(r[0]);
-        text.append("-");
-        text.append(r[1]);
-      }
+
+      String regions = cs.regionsToString(",", "-");
+      text.append(regions);
       text.append("\n");
     }
     // TODO: allow efficient recovery of annotation data shown in several
@@ -200,8 +193,8 @@ public class AnnotationFile
       StringBuffer colours = new StringBuffer();
       StringBuffer graphLine = new StringBuffer();
       StringBuffer rowprops = new StringBuffer();
-      Hashtable<Integer, String> graphGroup = new Hashtable<Integer, String>();
-      Hashtable<Integer, Object[]> graphGroup_refs = new Hashtable<Integer, Object[]>();
+      Hashtable<Integer, String> graphGroup = new Hashtable<>();
+      Hashtable<Integer, Object[]> graphGroup_refs = new Hashtable<>();
       BitSet graphGroupSeen = new BitSet();
 
       java.awt.Color color;
@@ -210,10 +203,8 @@ public class AnnotationFile
       {
         row = annotations[i];
 
-        if (!row.visible
-                && !row.hasScore()
-                && !(row.graphGroup > -1 && graphGroupSeen
-                        .get(row.graphGroup)))
+        if (!row.visible && !row.hasScore() && !(row.graphGroup > -1
+                && graphGroupSeen.get(row.graphGroup)))
         {
           continue;
         }
@@ -228,7 +219,8 @@ public class AnnotationFile
         writeGroup_Ref(refGroup, row.groupRef);
         refGroup = row.groupRef;
 
-        boolean hasGlyphs = row.hasIcons, hasLabels = row.hasText, hasValues = row.hasScore, hasText = false;
+        boolean hasGlyphs = row.hasIcons, hasLabels = row.hasText,
+                hasValues = row.hasScore, hasText = false;
         // lookahead to check what the annotation row object actually contains.
         for (int j = 0; row.annotations != null
                 && j < row.annotations.length
@@ -237,14 +229,15 @@ public class AnnotationFile
           if (row.annotations[j] != null)
           {
             hasLabels |= (row.annotations[j].displayCharacter != null
-                    && row.annotations[j].displayCharacter.length() > 0 && !row.annotations[j].displayCharacter
-                    .equals(" "));
-            hasGlyphs |= (row.annotations[j].secondaryStructure != 0 && row.annotations[j].secondaryStructure != ' ');
+                    && row.annotations[j].displayCharacter.length() > 0
+                    && !row.annotations[j].displayCharacter.equals(" "));
+            hasGlyphs |= (row.annotations[j].secondaryStructure != 0
+                    && row.annotations[j].secondaryStructure != ' ');
             hasValues |= (!Float.isNaN(row.annotations[j].value)); // NaNs can't
             // be
             // rendered..
-            hasText |= (row.annotations[j].description != null && row.annotations[j].description
-                    .length() > 0);
+            hasText |= (row.annotations[j].description != null
+                    && row.annotations[j].description.length() > 0);
           }
         }
 
@@ -277,8 +270,8 @@ public class AnnotationFile
             graphLine.append("\t");
             graphLine.append(row.getThreshold().label);
             graphLine.append("\t");
-            graphLine.append(jalview.util.Format.getHexString(row
-                    .getThreshold().colour));
+            graphLine.append(jalview.util.Format
+                    .getHexString(row.getThreshold().colour));
             graphLine.append(newline);
           }
 
@@ -373,11 +366,8 @@ public class AnnotationFile
             if (row.annotations[j].colour != null
                     && row.annotations[j].colour != java.awt.Color.black)
             {
-              text.append(comma
-                      + "["
-                      + jalview.util.Format
-                              .getHexString(row.annotations[j].colour)
-                      + "]");
+              text.append(comma + "[" + jalview.util.Format
+                      .getHexString(row.annotations[j].colour) + "]");
               comma = ",";
             }
           }
@@ -429,8 +419,8 @@ public class AnnotationFile
         for (Map.Entry<Integer, String> combine_statement : graphGroup
                 .entrySet())
         {
-          Object[] seqRefAndGroup = graphGroup_refs.get(combine_statement
-                  .getKey());
+          Object[] seqRefAndGroup = graphGroup_refs
+                  .get(combine_statement.getKey());
 
           writeSequence_Ref(refSeq, (SequenceI) seqRefAndGroup[0]);
           refSeq = (SequenceI) seqRefAndGroup[0];
@@ -535,7 +525,7 @@ public class AnnotationFile
     return false;
   }
 
-  public void printGroups(List<SequenceGroup> list)
+  protected void printGroups(List<SequenceGroup> list)
   {
     SequenceI seqrep = null;
     for (SequenceGroup sg : list)
@@ -581,7 +571,8 @@ public class AnnotationFile
       if (sg.cs != null)
       {
         text.append("colour=");
-        text.append(ColourSchemeProperty.getColourName(sg.cs));
+        text.append(ColourSchemeProperty
+                .getColourName(sg.cs.getColourScheme()));
         text.append("\t");
         if (sg.cs.getThreshold() != 0)
         {
@@ -659,50 +650,56 @@ public class AnnotationFile
 
   String refSeqId = null;
 
-  public boolean annotateAlignmentView(AlignViewportI viewport,
-          String file, String protocol)
+  public boolean annotateAlignmentView(AlignViewportI viewport, String file,
+          DataSourceType protocol)
   {
     ColumnSelection colSel = viewport.getColumnSelection();
+    HiddenColumns hidden = viewport.getAlignment().getHiddenColumns();
     if (colSel == null)
     {
       colSel = new ColumnSelection();
     }
-    boolean rslt = readAnnotationFile(viewport.getAlignment(), colSel,
-            file, protocol);
-    if (rslt && (colSel.hasSelectedColumns() || colSel.hasHiddenColumns()))
+    if (hidden == null)
+    {
+      hidden = new HiddenColumns();
+    }
+    boolean rslt = readAnnotationFile(viewport.getAlignment(), hidden, file,
+            protocol);
+    if (rslt && (colSel.hasSelectedColumns() || hidden.hasHiddenColumns()))
     {
       viewport.setColumnSelection(colSel);
+      viewport.getAlignment().setHiddenColumns(hidden);
     }
 
     return rslt;
   }
 
   public boolean readAnnotationFile(AlignmentI al, String file,
-          String protocol)
+          DataSourceType sourceType)
   {
-    return readAnnotationFile(al, null, file, protocol);
+    return readAnnotationFile(al, null, file, sourceType);
   }
 
-  public boolean readAnnotationFile(AlignmentI al, ColumnSelection colSel,
-          String file, String protocol)
+  public boolean readAnnotationFile(AlignmentI al, HiddenColumns hidden,
+          String file, DataSourceType sourceType)
   {
     BufferedReader in = null;
     try
     {
-      if (protocol.equals(AppletFormatAdapter.FILE))
+      if (sourceType == DataSourceType.FILE)
       {
         in = new BufferedReader(new FileReader(file));
       }
-      else if (protocol.equals(AppletFormatAdapter.URL))
+      else if (sourceType == DataSourceType.URL)
       {
         URL url = new URL(file);
         in = new BufferedReader(new InputStreamReader(url.openStream()));
       }
-      else if (protocol.equals(AppletFormatAdapter.PASTE))
+      else if (sourceType == DataSourceType.PASTE)
       {
         in = new BufferedReader(new StringReader(file));
       }
-      else if (protocol.equals(AppletFormatAdapter.CLASSLOADER))
+      else if (sourceType == DataSourceType.CLASSLOADER)
       {
         java.io.InputStream is = getClass().getResourceAsStream("/" + file);
         if (is != null)
@@ -712,7 +709,7 @@ public class AnnotationFile
       }
       if (in != null)
       {
-        return parseAnnotationFrom(al, colSel, in);
+        return parseAnnotationFrom(al, hidden, in);
       }
 
     } catch (Exception ex)
@@ -721,8 +718,8 @@ public class AnnotationFile
       System.out.println("Problem reading annotation file: " + ex);
       if (nlinesread > 0)
       {
-        System.out.println("Last read line " + nlinesread + ": '"
-                + lastread + "' (first 80 chars) ...");
+        System.out.println("Last read line " + nlinesread + ": '" + lastread
+                + "' (first 80 chars) ...");
       }
       return false;
     }
@@ -735,451 +732,445 @@ public class AnnotationFile
 
   private static String GRAPHLINE = "GRAPHLINE", COMBINE = "COMBINE";
 
-  public boolean parseAnnotationFrom(AlignmentI al, ColumnSelection colSel,
+  public boolean parseAnnotationFrom(AlignmentI al, HiddenColumns hidden,
           BufferedReader in) throws Exception
   {
     nlinesread = 0;
-    ArrayList<Object[]> combineAnnotation_calls = new ArrayList<Object[]>();
-    ArrayList<Object[]> deferredAnnotation_calls = new ArrayList<Object[]>();
+    List<Object[]> combineAnnotation_calls = new ArrayList<>();
+    List<Object[]> deferredAnnotation_calls = new ArrayList<>();
     boolean modified = false;
     String groupRef = null;
-    Hashtable groupRefRows = new Hashtable();
-
-    Hashtable autoAnnots = new Hashtable();
+    Map<String, Vector<AlignmentAnnotation>> groupRefRows = new HashMap<>();
+
+    Set<String> autoAnnots = new HashSet<>();
+    String line, label, description, token;
+    int graphStyle, index;
+    int refSeqIndex = 1;
+    int existingAnnotationCount = 0;
+    // when true - will add new rows regardless of whether they are duplicate
+    // auto-annotation like consensus or conservation graphs
+    boolean overrideAutoAnnot = false;
+    if (al.getAlignmentAnnotation() != null)
     {
-      String line, label, description, token;
-      int graphStyle, index;
-      int refSeqIndex = 1;
-      int existingAnnotations = 0;
-      // when true - will add new rows regardless of whether they are duplicate
-      // auto-annotation like consensus or conservation graphs
-      boolean overrideAutoAnnot = false;
-      if (al.getAlignmentAnnotation() != null)
-      {
-        existingAnnotations = al.getAlignmentAnnotation().length;
-        if (existingAnnotations > 0)
-        {
-          AlignmentAnnotation[] aa = al.getAlignmentAnnotation();
-          for (int aai = 0; aai < aa.length; aai++)
+      existingAnnotationCount = al.getAlignmentAnnotation().length;
+      if (existingAnnotationCount > 0)
+      {
+        AlignmentAnnotation[] aa = al.getAlignmentAnnotation();
+        for (int aai = 0; aai < aa.length; aai++)
+        {
+          if (aa[aai].autoCalculated)
           {
-            if (aa[aai].autoCalculated)
-            {
-              // make a note of the name and description
-              autoAnnots.put(
-                      autoAnnotsKey(aa[aai], aa[aai].sequenceRef,
-                              (aa[aai].groupRef == null ? null
-                                      : aa[aai].groupRef.getName())),
-                      new Integer(1));
-            }
+            // make a note of the name and description
+            autoAnnots.add(autoAnnotsKey(aa[aai], aa[aai].sequenceRef,
+                    (aa[aai].groupRef == null ? null
+                            : aa[aai].groupRef.getName())));
           }
         }
       }
+    }
 
-      int alWidth = al.getWidth();
+    int alWidth = al.getWidth();
 
-      StringTokenizer st;
-      Annotation[] annotations;
-      AlignmentAnnotation annotation = null;
+    StringTokenizer st;
+    Annotation[] annotations;
+    AlignmentAnnotation annotation = null;
 
-      // First confirm this is an Annotation file
-      boolean jvAnnotationFile = false;
-      while ((line = in.readLine()) != null)
+    // First confirm this is an Annotation file
+    boolean jvAnnotationFile = false;
+    while ((line = in.readLine()) != null)
+    {
+      nlinesread++;
+      lastread = new String(line);
+      if (line.indexOf("#") == 0)
       {
-        nlinesread++;
-        lastread = new String(line);
-        if (line.indexOf("#") == 0)
-        {
-          continue;
-        }
-
-        if (line.indexOf("JALVIEW_ANNOTATION") > -1)
-        {
-          jvAnnotationFile = true;
-          break;
-        }
+        continue;
       }
 
-      if (!jvAnnotationFile)
+      if (line.indexOf("JALVIEW_ANNOTATION") > -1)
       {
-        in.close();
-        return false;
+        jvAnnotationFile = true;
+        break;
       }
+    }
 
-      while ((line = in.readLine()) != null)
+    if (!jvAnnotationFile)
+    {
+      in.close();
+      return false;
+    }
+
+    while ((line = in.readLine()) != null)
+    {
+      nlinesread++;
+      lastread = new String(line);
+      if (line.indexOf("#") == 0 || line.indexOf("JALVIEW_ANNOTATION") > -1
+              || line.length() == 0)
       {
-        nlinesread++;
-        lastread = new String(line);
-        if (line.indexOf("#") == 0
-                || line.indexOf("JALVIEW_ANNOTATION") > -1
-                || line.length() == 0)
-        {
-          continue;
-        }
+        continue;
+      }
 
-        st = new StringTokenizer(line, "\t");
-        token = st.nextToken();
-        if (token.equalsIgnoreCase("COLOUR"))
-        {
-          // TODO: use graduated colour def'n here too
-          colourAnnotations(al, st.nextToken(), st.nextToken());
-          modified = true;
-          continue;
-        }
+      st = new StringTokenizer(line, "\t");
+      token = st.nextToken();
+      if (token.equalsIgnoreCase("COLOUR"))
+      {
+        // TODO: use graduated colour def'n here too
+        colourAnnotations(al, st.nextToken(), st.nextToken());
+        modified = true;
+        continue;
+      }
 
-        else if (token.equalsIgnoreCase(COMBINE))
-        {
-          // keep a record of current state and resolve groupRef at end
-          combineAnnotation_calls
-                  .add(new Object[] { st, refSeq, groupRef });
-          modified = true;
-          continue;
-        }
-        else if (token.equalsIgnoreCase("ROWPROPERTIES"))
-        {
-          addRowProperties(al, st);
-          modified = true;
-          continue;
-        }
-        else if (token.equalsIgnoreCase(GRAPHLINE))
-        {
-          // resolve at end
-          deferredAnnotation_calls.add(new Object[] { GRAPHLINE, st,
-              refSeq, groupRef });
-          modified = true;
-          continue;
-        }
+      else if (token.equalsIgnoreCase(COMBINE))
+      {
+        // keep a record of current state and resolve groupRef at end
+        combineAnnotation_calls.add(new Object[] { st, refSeq, groupRef });
+        modified = true;
+        continue;
+      }
+      else if (token.equalsIgnoreCase("ROWPROPERTIES"))
+      {
+        addRowProperties(al, st);
+        modified = true;
+        continue;
+      }
+      else if (token.equalsIgnoreCase(GRAPHLINE))
+      {
+        // resolve at end
+        deferredAnnotation_calls
+                .add(new Object[]
+                { GRAPHLINE, st, refSeq, groupRef });
+        modified = true;
+        continue;
+      }
 
-        else if (token.equalsIgnoreCase("SEQUENCE_REF"))
+      else if (token.equalsIgnoreCase("SEQUENCE_REF"))
+      {
+        if (st.hasMoreTokens())
         {
-          if (st.hasMoreTokens())
+          refSeq = al.findName(refSeqId = st.nextToken());
+          if (refSeq == null)
           {
-            refSeq = al.findName(refSeqId = st.nextToken());
-            if (refSeq == null)
-            {
-              refSeqId = null;
-            }
-            try
-            {
-              refSeqIndex = Integer.parseInt(st.nextToken());
-              if (refSeqIndex < 1)
-              {
-                refSeqIndex = 1;
-                System.out
-                        .println("WARNING: SEQUENCE_REF index must be > 0 in AnnotationFile");
-              }
-            } catch (Exception ex)
+            refSeqId = null;
+          }
+          try
+          {
+            refSeqIndex = Integer.parseInt(st.nextToken());
+            if (refSeqIndex < 1)
             {
               refSeqIndex = 1;
+              System.out.println(
+                      "WARNING: SEQUENCE_REF index must be > 0 in AnnotationFile");
             }
-          }
-          else
+          } catch (Exception ex)
           {
-            refSeq = null;
-            refSeqId = null;
+            refSeqIndex = 1;
           }
-          continue;
         }
-        else if (token.equalsIgnoreCase("GROUP_REF"))
+        else
         {
-          // Group references could be forward or backwards, so they are
-          // resolved after the whole file is read in
-          groupRef = null;
-          if (st.hasMoreTokens())
+          refSeq = null;
+          refSeqId = null;
+        }
+        continue;
+      }
+      else if (token.equalsIgnoreCase("GROUP_REF"))
+      {
+        // Group references could be forward or backwards, so they are
+        // resolved after the whole file is read in
+        groupRef = null;
+        if (st.hasMoreTokens())
+        {
+          groupRef = st.nextToken();
+          if (groupRef.length() < 1)
+          {
+            groupRef = null; // empty string
+          }
+          else
           {
-            groupRef = st.nextToken();
-            if (groupRef.length() < 1)
+            if (groupRefRows.get(groupRef) == null)
             {
-              groupRef = null; // empty string
-            }
-            else
-            {
-              if (groupRefRows.get(groupRef) == null)
-              {
-                groupRefRows.put(groupRef, new Vector());
-              }
+              groupRefRows.put(groupRef, new Vector<>());
             }
           }
-          continue;
-        }
-        else if (token.equalsIgnoreCase("SEQUENCE_GROUP"))
-        {
-          addGroup(al, st);
-          modified = true;
-          continue;
         }
+        continue;
+      }
+      else if (token.equalsIgnoreCase("SEQUENCE_GROUP"))
+      {
+        addGroup(al, st);
+        modified = true;
+        continue;
+      }
 
-        else if (token.equalsIgnoreCase("PROPERTIES"))
-        {
-          addProperties(al, st);
-          modified = true;
-          continue;
-        }
+      else if (token.equalsIgnoreCase("PROPERTIES"))
+      {
+        addProperties(al, st);
+        modified = true;
+        continue;
+      }
 
-        else if (token.equalsIgnoreCase("BELOW_ALIGNMENT"))
+      else if (token.equalsIgnoreCase("BELOW_ALIGNMENT"))
+      {
+        setBelowAlignment(al, st);
+        modified = true;
+        continue;
+      }
+      else if (token.equalsIgnoreCase("ALIGNMENT"))
+      {
+        addAlignmentDetails(al, st);
+        modified = true;
+        continue;
+      }
+      // else if (token.equalsIgnoreCase("VIEW_DEF"))
+      // {
+      // addOrSetView(al,st);
+      // modified = true;
+      // continue;
+      // }
+      else if (token.equalsIgnoreCase("VIEW_SETREF"))
+      {
+        if (refSeq != null)
         {
-          setBelowAlignment(al, st);
-          modified = true;
-          continue;
+          al.setSeqrep(refSeq);
         }
-        else if (token.equalsIgnoreCase("ALIGNMENT"))
+        modified = true;
+        continue;
+      }
+      else if (token.equalsIgnoreCase("VIEW_HIDECOLS"))
+      {
+        if (st.hasMoreTokens())
         {
-          addAlignmentDetails(al, st);
-          modified = true;
-          continue;
-        }
-        // else if (token.equalsIgnoreCase("VIEW_DEF"))
-        // {
-        // addOrSetView(al,st);
-        // modified = true;
-        // continue;
-        // }
-        else if (token.equalsIgnoreCase("VIEW_SETREF"))
-        {
-          if (refSeq != null)
+          if (hidden == null)
           {
-            al.setSeqrep(refSeq);
+            hidden = new HiddenColumns();
           }
-          modified = true;
-          continue;
+          parseHideCols(hidden, st.nextToken());
         }
-        else if (token.equalsIgnoreCase("VIEW_HIDECOLS"))
+        modified = true;
+        continue;
+      }
+      else if (token.equalsIgnoreCase("HIDE_INSERTIONS"))
+      {
+        SequenceI sr = refSeq == null ? al.getSeqrep() : refSeq;
+        if (sr == null)
         {
-          if (st.hasMoreTokens())
-          {
-            if (colSel == null)
-            {
-              colSel = new ColumnSelection();
-            }
-            parseHideCols(colSel, st.nextToken());
-          }
-          modified = true;
-          continue;
+          sr = al.getSequenceAt(0);
         }
-        else if (token.equalsIgnoreCase("HIDE_INSERTIONS"))
+        if (sr != null)
         {
-          SequenceI sr = refSeq == null ? al.getSeqrep() : refSeq;
-          if (sr == null)
+          if (hidden == null)
           {
-            sr = al.getSequenceAt(0);
+            System.err.println(
+                    "Cannot process HIDE_INSERTIONS without an alignment view: Ignoring line: "
+                            + line);
           }
-          if (sr != null)
+          else
           {
-            if (colSel == null)
-            {
-              System.err
-                      .println("Cannot process HIDE_INSERTIONS without an alignment view: Ignoring line: "
-                              + line);
-            }
-            else
-            {
-              // consider deferring this till after the file has been parsed ?
-              colSel.hideInsertionsFor(sr);
-            }
+            // consider deferring this till after the file has been parsed ?
+            hidden.hideList(sr.getInsertions());
           }
-          modified = true;
-          continue;
         }
+        modified = true;
+        continue;
+      }
 
-        // Parse out the annotation row
-        graphStyle = AlignmentAnnotation.getGraphValueFromString(token);
-        label = st.nextToken();
-
-        index = 0;
-        annotations = new Annotation[alWidth];
-        description = null;
-        float score = Float.NaN;
+      // Parse out the annotation row
+      graphStyle = AlignmentAnnotation.getGraphValueFromString(token);
+      label = st.nextToken();
 
-        if (st.hasMoreTokens())
-        {
-          line = st.nextToken();
+      index = 0;
+      annotations = new Annotation[alWidth];
+      description = null;
+      float score = Float.NaN;
 
-          if (line.indexOf("|") == -1)
-          {
-            description = line;
-            if (st.hasMoreTokens())
-            {
-              line = st.nextToken();
-            }
-          }
+      if (st.hasMoreTokens())
+      {
+        line = st.nextToken();
 
+        if (line.indexOf("|") == -1)
+        {
+          description = line;
           if (st.hasMoreTokens())
           {
-            // This must be the score
-            score = Float.valueOf(st.nextToken()).floatValue();
+            line = st.nextToken();
           }
+        }
 
-          st = new StringTokenizer(line, "|", true);
+        if (st.hasMoreTokens())
+        {
+          // This must be the score
+          score = Float.valueOf(st.nextToken()).floatValue();
+        }
 
-          boolean emptyColumn = true;
-          boolean onlyOneElement = (st.countTokens() == 1);
+        st = new StringTokenizer(line, "|", true);
 
-          while (st.hasMoreElements() && index < alWidth)
-          {
-            token = st.nextToken().trim();
+        boolean emptyColumn = true;
+        boolean onlyOneElement = (st.countTokens() == 1);
 
-            if (onlyOneElement)
-            {
-              try
-              {
-                score = Float.valueOf(token).floatValue();
-                break;
-              } catch (NumberFormatException ex)
-              {
-              }
-            }
+        while (st.hasMoreElements() && index < alWidth)
+        {
+          token = st.nextToken().trim();
 
-            if (token.equals("|"))
+          if (onlyOneElement)
+          {
+            try
             {
-              if (emptyColumn)
-              {
-                index++;
-              }
-
-              emptyColumn = true;
-            }
-            else
+              score = Float.valueOf(token).floatValue();
+              break;
+            } catch (NumberFormatException ex)
             {
-              annotations[index++] = parseAnnotation(token, graphStyle);
-              emptyColumn = false;
             }
           }
 
-        }
-
-        annotation = new AlignmentAnnotation(label, description,
-                (index == 0) ? null : annotations, 0, 0, graphStyle);
-
-        annotation.score = score;
-        if (!overrideAutoAnnot
-                && autoAnnots.containsKey(autoAnnotsKey(annotation, refSeq,
-                        groupRef)))
-        {
-          // skip - we've already got an automatic annotation of this type.
-          continue;
-        }
-        // otherwise add it!
-        if (refSeq != null)
-        {
-
-          annotation.belowAlignment = false;
-          // make a copy of refSeq so we can find other matches in the alignment
-          SequenceI referedSeq = refSeq;
-          do
+          if (token.equals("|"))
           {
-            // copy before we do any mapping business.
-            // TODO: verify that undo/redo with 1:many sequence associated
-            // annotations can be undone correctly
-            AlignmentAnnotation ann = new AlignmentAnnotation(annotation);
-            annotation
-                    .createSequenceMapping(referedSeq, refSeqIndex, false);
-            annotation.adjustForAlignment();
-            referedSeq.addAlignmentAnnotation(annotation);
-            al.addAnnotation(annotation);
-            al.setAnnotationIndex(annotation,
-                    al.getAlignmentAnnotation().length
-                            - existingAnnotations - 1);
-            if (groupRef != null)
+            if (emptyColumn)
             {
-              ((Vector) groupRefRows.get(groupRef)).addElement(annotation);
+              index++;
             }
-            // and recover our virgin copy to use again if necessary.
-            annotation = ann;
 
-          } while (refSeqId != null
-                  && (referedSeq = al.findName(referedSeq, refSeqId, true)) != null);
+            emptyColumn = true;
+          }
+          else
+          {
+            annotations[index++] = parseAnnotation(token, graphStyle);
+            emptyColumn = false;
+          }
         }
-        else
+
+      }
+
+      annotation = new AlignmentAnnotation(label, description,
+              (index == 0) ? null : annotations, 0, 0, graphStyle);
+
+      annotation.score = score;
+      if (!overrideAutoAnnot && autoAnnots
+              .contains(autoAnnotsKey(annotation, refSeq, groupRef)))
+      {
+        // skip - we've already got an automatic annotation of this type.
+        continue;
+      }
+      // otherwise add it!
+      if (refSeq != null)
+      {
+
+        annotation.belowAlignment = false;
+        // make a copy of refSeq so we can find other matches in the alignment
+        SequenceI referedSeq = refSeq;
+        do
         {
+          // copy before we do any mapping business.
+          // TODO: verify that undo/redo with 1:many sequence associated
+          // annotations can be undone correctly
+          AlignmentAnnotation ann = new AlignmentAnnotation(annotation);
+          annotation.createSequenceMapping(referedSeq, refSeqIndex, false);
+          annotation.adjustForAlignment();
+          referedSeq.addAlignmentAnnotation(annotation);
           al.addAnnotation(annotation);
           al.setAnnotationIndex(annotation,
-                  al.getAlignmentAnnotation().length - existingAnnotations
-                          - 1);
+                  al.getAlignmentAnnotation().length
+                          - existingAnnotationCount - 1);
           if (groupRef != null)
           {
-            ((Vector) groupRefRows.get(groupRef)).addElement(annotation);
+            groupRefRows.get(groupRef).addElement(annotation);
           }
+          // and recover our virgin copy to use again if necessary.
+          annotation = ann;
+
+        } while (refSeqId != null && (referedSeq = al.findName(referedSeq,
+                refSeqId, true)) != null);
+      }
+      else
+      {
+        al.addAnnotation(annotation);
+        al.setAnnotationIndex(annotation, al.getAlignmentAnnotation().length
+                - existingAnnotationCount - 1);
+        if (groupRef != null)
+        {
+          groupRefRows.get(groupRef).addElement(annotation);
         }
-        // and set modification flag
-        modified = true;
       }
-      // Resolve the groupRefs
-      Hashtable<String, SequenceGroup> groupRefLookup = new Hashtable<String, SequenceGroup>();
-      Enumeration en = groupRefRows.keys();
+      // and set modification flag
+      modified = true;
+    }
+    // Resolve the groupRefs
+    Hashtable<String, SequenceGroup> groupRefLookup = new Hashtable<>();
+    Iterator<String> en = groupRefRows.keySet().iterator();
 
-      while (en.hasMoreElements())
+    while (en.hasNext())
+    {
+      groupRef = en.next();
+      boolean matched = false;
+      // Resolve group: TODO: add a getGroupByName method to alignments
+      for (SequenceGroup theGroup : al.getGroups())
       {
-        groupRef = (String) en.nextElement();
-        boolean matched = false;
-        // Resolve group: TODO: add a getGroupByName method to alignments
-        for (SequenceGroup theGroup : al.getGroups())
+        if (theGroup.getName().equals(groupRef))
         {
-          if (theGroup.getName().equals(groupRef))
+          if (matched)
           {
-            if (matched)
-            {
-              // TODO: specify and implement duplication of alignment annotation
-              // for multiple group references.
-              System.err
-                      .println("Ignoring 1:many group reference mappings for group name '"
-                              + groupRef + "'");
-            }
-            else
+            // TODO: specify and implement duplication of alignment annotation
+            // for multiple group references.
+            System.err.println(
+                    "Ignoring 1:many group reference mappings for group name '"
+                            + groupRef + "'");
+          }
+          else
+          {
+            matched = true;
+            Vector<AlignmentAnnotation> rowset = groupRefRows.get(groupRef);
+            groupRefLookup.put(groupRef, theGroup);
+            if (rowset != null && rowset.size() > 0)
             {
-              matched = true;
-              Vector rowset = (Vector) groupRefRows.get(groupRef);
-              groupRefLookup.put(groupRef, theGroup);
-              if (rowset != null && rowset.size() > 0)
+              AlignmentAnnotation alan = null;
+              for (int elm = 0, elmSize = rowset
+                      .size(); elm < elmSize; elm++)
               {
-                AlignmentAnnotation alan = null;
-                for (int elm = 0, elmSize = rowset.size(); elm < elmSize; elm++)
-                {
-                  alan = (AlignmentAnnotation) rowset.elementAt(elm);
-                  alan.groupRef = theGroup;
-                }
+                alan = rowset.elementAt(elm);
+                alan.groupRef = theGroup;
               }
             }
           }
         }
-        ((Vector) groupRefRows.get(groupRef)).removeAllElements();
-      }
-      // process any deferred attribute settings for each context
-      for (Object[] _deferred_args : deferredAnnotation_calls)
-      {
-        if (_deferred_args[0] == GRAPHLINE)
-        {
-          addLine(al,
-                  (StringTokenizer) _deferred_args[1], // st
-                  (SequenceI) _deferred_args[2], // refSeq
-                  (_deferred_args[3] == null) ? null : groupRefLookup
-                          .get(_deferred_args[3]) // the reference
-                                                  // group, or null
-          );
-        }
       }
-
-      // finally, combine all the annotation rows within each context.
-      /**
-       * number of combine statements in this annotation file. Used to create
-       * new groups for combined annotation graphs without disturbing existing
-       * ones
-       */
-      int combinecount = 0;
-      for (Object[] _combine_args : combineAnnotation_calls)
-      {
-        combineAnnotations(al,
-                ++combinecount,
-                (StringTokenizer) _combine_args[0], // st
-                (SequenceI) _combine_args[1], // refSeq
-                (_combine_args[2] == null) ? null : groupRefLookup
-                        .get(_combine_args[2]) // the reference group,
-                                               // or null
+      groupRefRows.get(groupRef).removeAllElements();
+    }
+    // process any deferred attribute settings for each context
+    for (Object[] _deferred_args : deferredAnnotation_calls)
+    {
+      if (_deferred_args[0] == GRAPHLINE)
+      {
+        addLine(al, (StringTokenizer) _deferred_args[1], // st
+                (SequenceI) _deferred_args[2], // refSeq
+                (_deferred_args[3] == null) ? null
+                        : groupRefLookup.get(_deferred_args[3]) // the
+                                                                // reference
+                                                                // group, or
+                                                                // null
         );
       }
     }
+
+    // finally, combine all the annotation rows within each context.
+    /**
+     * number of combine statements in this annotation file. Used to create new
+     * groups for combined annotation graphs without disturbing existing ones
+     */
+    int combinecount = 0;
+    for (Object[] _combine_args : combineAnnotation_calls)
+    {
+      combineAnnotations(al, ++combinecount,
+              (StringTokenizer) _combine_args[0], // st
+              (SequenceI) _combine_args[1], // refSeq
+              (_combine_args[2] == null) ? null
+                      : groupRefLookup.get(_combine_args[2]) // the reference
+                                                             // group,
+                                                             // or null
+      );
+    }
+
     return modified;
   }
 
-  private void parseHideCols(ColumnSelection colSel, String nextToken)
+  private void parseHideCols(HiddenColumns hidden, String nextToken)
   {
     StringTokenizer inval = new StringTokenizer(nextToken, ",");
     while (inval.hasMoreTokens())
@@ -1191,7 +1182,7 @@ public class AnnotationFile
         from = to = Integer.parseInt(range);
         if (from >= 0)
         {
-          colSel.hideColumns(from, to);
+          hidden.hideColumns(from, to);
         }
       }
       else
@@ -1207,13 +1198,13 @@ public class AnnotationFile
         }
         if (from > 0 && to >= from)
         {
-          colSel.hideColumns(from, to);
+          hidden.hideColumns(from, to);
         }
       }
     }
   }
 
-  private Object autoAnnotsKey(AlignmentAnnotation annotation,
+  private String autoAnnotsKey(AlignmentAnnotation annotation,
           SequenceI refSeq, String groupRef)
   {
     return annotation.graph + "\t" + annotation.label + "\t"
@@ -1223,29 +1214,20 @@ public class AnnotationFile
 
   Annotation parseAnnotation(String string, int graphStyle)
   {
-    boolean hasSymbols = (graphStyle == AlignmentAnnotation.NO_GRAPH); // don't
-    // do the
-    // glyph
-    // test
-    // if we
-    // don't
-    // want
-    // secondary
-    // structure
+    // don't do the glyph test if we don't want secondary structure
+    boolean hasSymbols = (graphStyle == AlignmentAnnotation.NO_GRAPH);
     String desc = null, displayChar = null;
     char ss = ' '; // secondaryStructure
     float value = 0;
     boolean parsedValue = false, dcset = false;
 
     // find colour here
-    java.awt.Color colour = null;
+    Color colour = null;
     int i = string.indexOf("[");
     int j = string.indexOf("]");
     if (i > -1 && j > -1)
     {
-      UserColourScheme ucs = new UserColourScheme();
-
-      colour = ucs.getColourFromString(string.substring(i + 1, j));
+      colour = ColorUtils.parseColourString(string.substring(i + 1, j));
       if (i > 0 && string.charAt(i - 1) == ',')
       {
         // clip the preceding comma as well
@@ -1298,8 +1280,8 @@ public class AnnotationFile
           displayChar = token;
         }
       }
-      if (hasSymbols
-              && (token.length() == 1 && "()<>[]{}AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"
+      if (hasSymbols && (token.length() == 1
+              && "()<>[]{}AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"
                       .contains(token)))
       {
         // Either this character represents a helix or sheet
@@ -1347,7 +1329,7 @@ public class AnnotationFile
 
   void colourAnnotations(AlignmentI al, String label, String colour)
   {
-    UserColourScheme ucs = new UserColourScheme(colour);
+    Color awtColour = ColorUtils.parseColourString(colour);
     Annotation[] annotations;
     for (int i = 0; i < al.getAlignmentAnnotation().length; i++)
     {
@@ -1358,7 +1340,7 @@ public class AnnotationFile
         {
           if (annotations[j] != null)
           {
-            annotations[j].colour = ucs.findColour('A');
+            annotations[j].colour = awtColour;
           }
         }
       }
@@ -1419,8 +1401,8 @@ public class AnnotationFile
     }
     else
     {
-      System.err
-              .println("Couldn't combine annotations. None are added to alignment yet!");
+      System.err.println(
+              "Couldn't combine annotations. None are added to alignment yet!");
     }
   }
 
@@ -1428,15 +1410,22 @@ public class AnnotationFile
           SequenceGroup groupRef)
   {
     String group = st.nextToken();
-    AlignmentAnnotation annotation = null, alannot[] = al
-            .getAlignmentAnnotation();
-    float value = new Float(st.nextToken()).floatValue();
+    AlignmentAnnotation[] alannot = al.getAlignmentAnnotation();
+    String nextToken = st.nextToken();
+    float value = 0f;
+    try
+    {
+      value = Float.valueOf(nextToken);
+    } catch (NumberFormatException e)
+    {
+      System.err.println("line " + nlinesread + ": Threshold '" + nextToken
+              + "' invalid, setting to zero");
+    }
     String label = st.hasMoreTokens() ? st.nextToken() : null;
-    java.awt.Color colour = null;
+    Color colour = null;
     if (st.hasMoreTokens())
     {
-      UserColourScheme ucs = new UserColourScheme(st.nextToken());
-      colour = ucs.findColour('A');
+      colour = ColorUtils.parseColourString(st.nextToken());
     }
     if (alannot != null)
     {
@@ -1450,10 +1439,6 @@ public class AnnotationFile
         }
       }
     }
-    if (annotation == null)
-    {
-      return;
-    }
   }
 
   void addGroup(AlignmentI al, StringTokenizer st)
@@ -1483,8 +1468,8 @@ public class AnnotationFile
       }
     } catch (Exception e)
     {
-      System.err
-              .println("Couldn't parse Group Start or End Field as '*' or a valid column or sequence index: '"
+      System.err.println(
+              "Couldn't parse Group Start or End Field as '*' or a valid column or sequence index: '"
                       + rng + "' - assuming alignment width for group.");
       // assume group is full width
       sg.setStartRes(0);
@@ -1530,7 +1515,8 @@ public class AnnotationFile
         }
         else
         {
-          sg.addSequence(al.getSequenceAt(Integer.parseInt(tmp) - 1), false);
+          sg.addSequence(al.getSequenceAt(Integer.parseInt(tmp) - 1),
+                  false);
         }
       }
     }
@@ -1613,8 +1599,7 @@ public class AnnotationFile
     if (sg != null)
     {
       String keyValue, key, value;
-      ColourSchemeI def = sg.cs;
-      sg.cs = null;
+      ColourSchemeI def = sg.getColourScheme();
       while (st.hasMoreTokens())
       {
         keyValue = st.nextToken();
@@ -1627,7 +1612,10 @@ public class AnnotationFile
         }
         else if (key.equalsIgnoreCase("colour"))
         {
-          sg.cs = ColourSchemeProperty.getColour(al, value);
+          // TODO need to notify colourscheme of view reference once it is
+          // available
+          sg.cs.setColourScheme(
+                  ColourSchemeProperty.getColourScheme(null, al, value));
         }
         else if (key.equalsIgnoreCase("pidThreshold"))
         {
@@ -1637,9 +1625,8 @@ public class AnnotationFile
         else if (key.equalsIgnoreCase("consThreshold"))
         {
           sg.cs.setConservationInc(Integer.parseInt(value));
-          Conservation c = new Conservation("Group", 3,
-                  sg.getSequences(null), sg.getStartRes(),
-                  sg.getEndRes() + 1);
+          Conservation c = new Conservation("Group", sg.getSequences(null),
+                  sg.getStartRes(), sg.getEndRes() + 1);
 
           c.calculate();
           c.verdict(false, 25); // TODO: refer to conservation percent threshold
@@ -1649,7 +1636,7 @@ public class AnnotationFile
         }
         else if (key.equalsIgnoreCase("outlineColour"))
         {
-          sg.setOutlineColour(new UserColourScheme(value).findColour('A'));
+          sg.setOutlineColour(ColorUtils.parseColourString(value));
         }
         else if (key.equalsIgnoreCase("displayBoxes"))
         {
@@ -1669,11 +1656,11 @@ public class AnnotationFile
         }
         else if (key.equalsIgnoreCase("textCol1"))
         {
-          sg.textColour = new UserColourScheme(value).findColour('A');
+          sg.textColour = ColorUtils.parseColourString(value);
         }
         else if (key.equalsIgnoreCase("textCol2"))
         {
-          sg.textColour2 = new UserColourScheme(value).findColour('A');
+          sg.textColour2 = ColorUtils.parseColourString(value);
         }
         else if (key.equalsIgnoreCase("textColThreshold"))
         {
@@ -1681,9 +1668,8 @@ public class AnnotationFile
         }
         else if (key.equalsIgnoreCase("idColour"))
         {
-          // consider warning if colour doesn't resolve to a real colour
-          sg.setIdColour((def = new UserColourScheme(value))
-                  .findColour('A'));
+          Color idColour = ColorUtils.parseColourString(value);
+          sg.setIdColour(idColour == null ? Color.black : idColour);
         }
         else if (key.equalsIgnoreCase("hide"))
         {
@@ -1697,9 +1683,9 @@ public class AnnotationFile
         }
         sg.recalcConservation();
       }
-      if (sg.cs == null)
+      if (sg.getColourScheme() == null)
       {
-        sg.cs = def;
+        sg.setColourScheme(def);
       }
     }
   }
@@ -1710,8 +1696,8 @@ public class AnnotationFile
     AlignmentAnnotation aa, ala[] = al.getAlignmentAnnotation();
     if (ala == null)
     {
-      System.err
-              .print("Warning - no annotation to set below for sequence associated annotation:");
+      System.err.print(
+              "Warning - no annotation to set below for sequence associated annotation:");
     }
     while (st.hasMoreTokens())
     {
@@ -1790,10 +1776,13 @@ public class AnnotationFile
 
   public String printAnnotationsForView(AlignViewportI viewport)
   {
-    return printAnnotations(viewport.isShowAnnotation() ? viewport
-            .getAlignment().getAlignmentAnnotation() : null, viewport
-            .getAlignment().getGroups(), viewport.getAlignment()
-            .getProperties(), viewport.getColumnSelection(),
+    return printAnnotations(
+            viewport.isShowAnnotation()
+                    ? viewport.getAlignment().getAlignmentAnnotation()
+                    : null,
+            viewport.getAlignment().getGroups(),
+            viewport.getAlignment().getProperties(),
+            viewport.getAlignment().getHiddenColumns(),
             viewport.getAlignment(), null);
   }