Merge branch 'bug/JAL-3120restoreFeatureColour' into merge/JAL-3120
[jalview.git] / src / jalview / project / Jalview2XML.java
similarity index 73%
rename from src/jalview/gui/Jalview2XML.java
rename to src/jalview/project/Jalview2XML.java
index 28077e6..53e9a83 100644 (file)
  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
  * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
-package jalview.gui;
+package jalview.project;
+
+import static jalview.math.RotatableMatrix.Axis.X;
+import static jalview.math.RotatableMatrix.Axis.Y;
+import static jalview.math.RotatableMatrix.Axis.Z;
 
 import jalview.analysis.Conservation;
+import jalview.analysis.PCA;
+import jalview.analysis.scoremodels.ScoreModels;
+import jalview.analysis.scoremodels.SimilarityParams;
 import jalview.api.FeatureColourI;
 import jalview.api.ViewStyleI;
+import jalview.api.analysis.ScoreModelI;
+import jalview.api.analysis.SimilarityParamsI;
 import jalview.api.structures.JalviewStructureDisplayI;
 import jalview.bin.Cache;
 import jalview.datamodel.AlignedCodonFrame;
@@ -31,6 +40,7 @@ import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.GraphLine;
 import jalview.datamodel.PDBEntry;
+import jalview.datamodel.Point;
 import jalview.datamodel.RnaViewerModel;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
@@ -42,49 +52,29 @@ import jalview.datamodel.features.FeatureMatcherI;
 import jalview.datamodel.features.FeatureMatcherSet;
 import jalview.datamodel.features.FeatureMatcherSetI;
 import jalview.ext.varna.RnaModel;
+import jalview.gui.AlignFrame;
+import jalview.gui.AlignViewport;
+import jalview.gui.AlignmentPanel;
+import jalview.gui.AppVarna;
+import jalview.gui.ChimeraViewFrame;
+import jalview.gui.Desktop;
+import jalview.gui.FeatureRenderer;
+import jalview.gui.JvOptionPane;
+import jalview.gui.OOMWarning;
+import jalview.gui.PCAPanel;
+import jalview.gui.PaintRefresher;
+import jalview.gui.SplitFrame;
+import jalview.gui.StructureViewer;
 import jalview.gui.StructureViewer.ViewerType;
+import jalview.gui.StructureViewerBase;
+import jalview.gui.TreePanel;
+import jalview.io.BackupFiles;
 import jalview.io.DataSourceType;
 import jalview.io.FileFormat;
+import jalview.io.NewickFile;
+import jalview.math.Matrix;
+import jalview.math.MatrixI;
 import jalview.renderer.ResidueShaderI;
-import jalview.schemabinding.version2.AlcodMap;
-import jalview.schemabinding.version2.AlcodonFrame;
-import jalview.schemabinding.version2.Annotation;
-import jalview.schemabinding.version2.AnnotationColours;
-import jalview.schemabinding.version2.AnnotationElement;
-import jalview.schemabinding.version2.CalcIdParam;
-import jalview.schemabinding.version2.CompoundMatcher;
-import jalview.schemabinding.version2.DBRef;
-import jalview.schemabinding.version2.Features;
-import jalview.schemabinding.version2.Group;
-import jalview.schemabinding.version2.HiddenColumns;
-import jalview.schemabinding.version2.JGroup;
-import jalview.schemabinding.version2.JSeq;
-import jalview.schemabinding.version2.JalviewModel;
-import jalview.schemabinding.version2.JalviewModelSequence;
-import jalview.schemabinding.version2.MapListFrom;
-import jalview.schemabinding.version2.MapListTo;
-import jalview.schemabinding.version2.Mapping;
-import jalview.schemabinding.version2.MappingChoice;
-import jalview.schemabinding.version2.MatchCondition;
-import jalview.schemabinding.version2.MatcherSet;
-import jalview.schemabinding.version2.OtherData;
-import jalview.schemabinding.version2.PdbentryItem;
-import jalview.schemabinding.version2.Pdbids;
-import jalview.schemabinding.version2.Property;
-import jalview.schemabinding.version2.RnaViewer;
-import jalview.schemabinding.version2.SecondaryStructure;
-import jalview.schemabinding.version2.Sequence;
-import jalview.schemabinding.version2.SequenceSet;
-import jalview.schemabinding.version2.SequenceSetProperties;
-import jalview.schemabinding.version2.Setting;
-import jalview.schemabinding.version2.StructureState;
-import jalview.schemabinding.version2.ThresholdLine;
-import jalview.schemabinding.version2.Tree;
-import jalview.schemabinding.version2.UserColours;
-import jalview.schemabinding.version2.Viewport;
-import jalview.schemabinding.version2.types.ColourThreshTypeType;
-import jalview.schemabinding.version2.types.FeatureMatcherByType;
-import jalview.schemabinding.version2.types.NoValueColour;
 import jalview.schemes.AnnotationColourGradient;
 import jalview.schemes.ColourSchemeI;
 import jalview.schemes.ColourSchemeProperty;
@@ -100,6 +90,7 @@ import jalview.util.StringUtils;
 import jalview.util.jarInputStreamProvider;
 import jalview.util.matcher.Condition;
 import jalview.viewmodel.AlignmentViewport;
+import jalview.viewmodel.PCAModel;
 import jalview.viewmodel.ViewportRanges;
 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
 import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
@@ -109,8 +100,56 @@ import jalview.ws.jws2.jabaws2.Jws2Instance;
 import jalview.ws.params.ArgumentI;
 import jalview.ws.params.AutoCalcSetting;
 import jalview.ws.params.WsParamSetI;
+import jalview.xml.binding.jalview.AlcodonFrame;
+import jalview.xml.binding.jalview.AlcodonFrame.AlcodMap;
+import jalview.xml.binding.jalview.Annotation;
+import jalview.xml.binding.jalview.Annotation.ThresholdLine;
+import jalview.xml.binding.jalview.AnnotationColourScheme;
+import jalview.xml.binding.jalview.AnnotationElement;
+import jalview.xml.binding.jalview.DoubleMatrix;
+import jalview.xml.binding.jalview.DoubleVector;
+import jalview.xml.binding.jalview.Feature;
+import jalview.xml.binding.jalview.Feature.OtherData;
+import jalview.xml.binding.jalview.FeatureMatcherSet.CompoundMatcher;
+import jalview.xml.binding.jalview.FilterBy;
+import jalview.xml.binding.jalview.JalviewModel;
+import jalview.xml.binding.jalview.JalviewModel.FeatureSettings;
+import jalview.xml.binding.jalview.JalviewModel.FeatureSettings.Group;
+import jalview.xml.binding.jalview.JalviewModel.FeatureSettings.Setting;
+import jalview.xml.binding.jalview.JalviewModel.JGroup;
+import jalview.xml.binding.jalview.JalviewModel.JSeq;
+import jalview.xml.binding.jalview.JalviewModel.JSeq.Pdbids;
+import jalview.xml.binding.jalview.JalviewModel.JSeq.Pdbids.StructureState;
+import jalview.xml.binding.jalview.JalviewModel.JSeq.RnaViewer;
+import jalview.xml.binding.jalview.JalviewModel.JSeq.RnaViewer.SecondaryStructure;
+import jalview.xml.binding.jalview.JalviewModel.PcaViewer;
+import jalview.xml.binding.jalview.JalviewModel.PcaViewer.Axis;
+import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SeqPointMax;
+import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SeqPointMin;
+import jalview.xml.binding.jalview.JalviewModel.PcaViewer.SequencePoint;
+import jalview.xml.binding.jalview.JalviewModel.Tree;
+import jalview.xml.binding.jalview.JalviewModel.UserColours;
+import jalview.xml.binding.jalview.JalviewModel.Viewport;
+import jalview.xml.binding.jalview.JalviewModel.Viewport.CalcIdParam;
+import jalview.xml.binding.jalview.JalviewModel.Viewport.HiddenColumns;
+import jalview.xml.binding.jalview.JalviewUserColours;
+import jalview.xml.binding.jalview.JalviewUserColours.Colour;
+import jalview.xml.binding.jalview.MapListType.MapListFrom;
+import jalview.xml.binding.jalview.MapListType.MapListTo;
+import jalview.xml.binding.jalview.Mapping;
+import jalview.xml.binding.jalview.NoValueColour;
+import jalview.xml.binding.jalview.ObjectFactory;
+import jalview.xml.binding.jalview.PcaDataType;
+import jalview.xml.binding.jalview.Pdbentry.Property;
+import jalview.xml.binding.jalview.Sequence;
+import jalview.xml.binding.jalview.Sequence.DBRef;
+import jalview.xml.binding.jalview.SequenceSet;
+import jalview.xml.binding.jalview.SequenceSet.SequenceSetProperties;
+import jalview.xml.binding.jalview.ThresholdType;
+import jalview.xml.binding.jalview.VAMSAS;
 
 import java.awt.Color;
+import java.awt.Font;
 import java.awt.Rectangle;
 import java.io.BufferedReader;
 import java.io.DataInputStream;
@@ -123,12 +162,14 @@ import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.lang.reflect.InvocationTargetException;
+import java.math.BigInteger;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Enumeration;
+import java.util.GregorianCalendar;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Hashtable;
@@ -146,9 +187,14 @@ import java.util.jar.JarOutputStream;
 
 import javax.swing.JInternalFrame;
 import javax.swing.SwingUtilities;
-
-import org.exolab.castor.xml.Marshaller;
-import org.exolab.castor.xml.Unmarshaller;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.Marshaller;
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.XMLGregorianCalendar;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamReader;
 
 /**
  * Write out the current jalview desktop state as a Jalview XML stream.
@@ -168,6 +214,12 @@ public class Jalview2XML
 
   private static final String UTF_8 = "UTF-8";
 
+  /**
+   * prefix for recovering datasets for alignments with multiple views where
+   * non-existent dataset IDs were written for some views
+   */
+  private static final String UNIQSEQSETID = "uniqueSeqSetId.";
+
   // use this with nextCounter() to make unique names for entities
   private int counter = 0;
 
@@ -203,6 +255,45 @@ public class Jalview2XML
   private Map<RnaModel, String> rnaSessions = new HashMap<>();
 
   /**
+   * A helper method for safely using the value of an optional attribute that
+   * may be null if not present in the XML. Answers the boolean value, or false
+   * if null.
+   * 
+   * @param b
+   * @return
+   */
+  public static boolean safeBoolean(Boolean b)
+  {
+    return b == null ? false : b.booleanValue();
+  }
+
+  /**
+   * A helper method for safely using the value of an optional attribute that
+   * may be null if not present in the XML. Answers the integer value, or zero
+   * if null.
+   * 
+   * @param i
+   * @return
+   */
+  public static int safeInt(Integer i)
+  {
+    return i == null ? 0 : i.intValue();
+  }
+
+  /**
+   * A helper method for safely using the value of an optional attribute that
+   * may be null if not present in the XML. Answers the float value, or zero if
+   * null.
+   * 
+   * @param f
+   * @return
+   */
+  public static float safeFloat(Float f)
+  {
+    return f == null ? 0f : f.floatValue();
+  }
+
+  /**
    * create/return unique hash string for sq
    * 
    * @param sq
@@ -460,24 +551,30 @@ public class Jalview2XML
   public void saveState(File statefile)
   {
     FileOutputStream fos = null;
+
     try
     {
+
       fos = new FileOutputStream(statefile);
+
       JarOutputStream jout = new JarOutputStream(fos);
       saveState(jout);
+      fos.close();
 
     } catch (Exception e)
     {
+      Cache.log.error("Couln't write Jalview state to " + statefile, e);
       // TODO: inform user of the problem - they need to know if their data was
       // not saved !
       if (errorMessage == null)
       {
-        errorMessage = "Couldn't write Jalview Archive to output file '"
+        errorMessage = "Did't write Jalview Archive to output file '"
                 + statefile + "' - See console error log for details";
       }
       else
       {
-        errorMessage += "(output file was '" + statefile + "')";
+        errorMessage += "(Didn't write Jalview Archive to output file '"
+                + statefile + ")";
       }
       e.printStackTrace();
     } finally
@@ -554,11 +651,12 @@ public class Jalview2XML
 
         String shortName = makeFilename(af, shortNames);
 
-        int ap, apSize = af.alignPanels.size();
+        int apSize = af.getAlignPanels().size();
 
-        for (ap = 0; ap < apSize; ap++)
+        for (int ap = 0; ap < apSize; ap++)
         {
-          AlignmentPanel apanel = af.alignPanels.get(ap);
+          AlignmentPanel apanel = (AlignmentPanel) af.getAlignPanels()
+                  .get(ap);
           String fileName = apSize == 1 ? shortName : ap + shortName;
           if (!fileName.endsWith(".xml"))
           {
@@ -646,7 +744,11 @@ public class Jalview2XML
   {
     try
     {
-      FileOutputStream fos = new FileOutputStream(jarFile);
+      // create backupfiles object and get new temp filename destination
+      BackupFiles backupfiles = new BackupFiles(jarFile);
+      FileOutputStream fos = new FileOutputStream(
+              backupfiles.getTempFilePath());
+
       JarOutputStream jout = new JarOutputStream(fos);
       List<AlignFrame> frames = new ArrayList<>();
 
@@ -668,7 +770,12 @@ public class Jalview2XML
       }
       ;
       jout.close();
-      return true;
+      boolean success = true;
+
+      backupfiles.setWriteSuccess(success);
+      success = backupfiles.rollBackupsAndRenameTempFile();
+
+      return success;
     } catch (Exception ex)
     {
       errorMessage = "Couldn't Write alignment view to Jalview Archive - see error output for details";
@@ -744,10 +851,21 @@ public class Jalview2XML
     AlignViewport av = ap.av;
     ViewportRanges vpRanges = av.getRanges();
 
-    JalviewModel object = new JalviewModel();
-    object.setVamsasModel(new jalview.schemabinding.version2.VamsasModel());
+    final ObjectFactory objectFactory = new ObjectFactory();
+    JalviewModel object = objectFactory.createJalviewModel();
+    object.setVamsasModel(new VAMSAS());
 
-    object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
+    // object.setCreationDate(new java.util.Date(System.currentTimeMillis()));
+    try
+    {
+      GregorianCalendar c = new GregorianCalendar();
+      DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
+      XMLGregorianCalendar now = datatypeFactory.newXMLGregorianCalendar(c);// gregorianCalendar);
+      object.setCreationDate(now);
+    } catch (DatatypeConfigurationException e)
+    {
+      System.err.println("error writing date: " + e.toString());
+    }
     object.setVersion(
             jalview.bin.Cache.getDefault("VERSION", "Development Build"));
 
@@ -764,7 +882,7 @@ public class Jalview2XML
 
     SequenceSet vamsasSet = new SequenceSet();
     Sequence vamsasSeq;
-    JalviewModelSequence jms = new JalviewModelSequence();
+    // JalviewModelSequence jms = new JalviewModelSequence();
 
     vamsasSet.setGapChar(jal.getGapCharacter() + "");
 
@@ -788,7 +906,8 @@ public class Jalview2XML
         SequenceSetProperties ssp = new SequenceSetProperties();
         ssp.setKey(key);
         ssp.setValue(jal.getProperties().get(key).toString());
-        vamsasSet.addSequenceSetProperties(ssp);
+        // vamsasSet.addSequenceSetProperties(ssp);
+        vamsasSet.getSequenceSetProperties().add(ssp);
       }
     }
 
@@ -825,7 +944,8 @@ public class Jalview2XML
         else
         {
           vamsasSeq = createVamsasSequence(id, jds);
-          vamsasSet.addSequence(vamsasSeq);
+//          vamsasSet.addSequence(vamsasSeq);
+          vamsasSet.getSequence().add(vamsasSeq);
           vamsasSetIds.put(id, vamsasSeq);
           seqRefIds.put(id, jds);
         }
@@ -854,7 +974,8 @@ public class Jalview2XML
             {
               if (reps[h] != jds)
               {
-                jseq.addHiddenSequences(rjal.findIndex(reps[h]));
+                // jseq.addHiddenSequences(rjal.findIndex(reps[h]));
+                jseq.getHiddenSequences().add(rjal.findIndex(reps[h]));
               }
             }
           }
@@ -868,11 +989,11 @@ public class Jalview2XML
 
       // TODO: omit sequence features from each alignment view's XML dump if we
       // are storing dataset
-      List<jalview.datamodel.SequenceFeature> sfs = jds
-              .getSequenceFeatures();
+      List<SequenceFeature> sfs = jds.getSequenceFeatures();
       for (SequenceFeature sf : sfs)
       {
-        Features features = new Features();
+        // Features features = new Features();
+        Feature features = new Feature();
 
         features.setBegin(sf.getBegin());
         features.setEnd(sf.getEnd());
@@ -887,7 +1008,8 @@ public class Jalview2XML
             OtherData keyValue = new OtherData();
             keyValue.setKey("LINK_" + l);
             keyValue.setValue(sf.links.elementAt(l).toString());
-            features.addOtherData(keyValue);
+            // features.addOtherData(keyValue);
+            features.getOtherData().add(keyValue);
           }
         }
         if (sf.otherDetails != null)
@@ -909,7 +1031,8 @@ public class Jalview2XML
                 otherData.setKey(key);
                 otherData.setKey2(subAttribute.getKey());
                 otherData.setValue(subAttribute.getValue().toString());
-                features.addOtherData(otherData);
+                // features.addOtherData(otherData);
+                features.getOtherData().add(otherData);
               }
             }
             else
@@ -917,22 +1040,23 @@ public class Jalview2XML
               OtherData otherData = new OtherData();
               otherData.setKey(key);
               otherData.setValue(value.toString());
-              features.addOtherData(otherData);
+              // features.addOtherData(otherData);
+              features.getOtherData().add(otherData);
             }
           }
         }
 
-        jseq.addFeatures(features);
+        // jseq.addFeatures(features);
+        jseq.getFeatures().add(features);
       }
 
       if (jdatasq.getAllPDBEntries() != null)
       {
-        Enumeration en = jdatasq.getAllPDBEntries().elements();
+        Enumeration<PDBEntry> en = jdatasq.getAllPDBEntries().elements();
         while (en.hasMoreElements())
         {
           Pdbids pdb = new Pdbids();
-          jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
-                  .nextElement();
+          jalview.datamodel.PDBEntry entry = en.nextElement();
 
           String pdbId = entry.getId();
           pdb.setId(pdbId);
@@ -998,25 +1122,28 @@ public class Jalview2XML
           Enumeration<String> props = entry.getProperties();
           if (props.hasMoreElements())
           {
-            PdbentryItem item = new PdbentryItem();
+            // PdbentryItem item = new PdbentryItem();
             while (props.hasMoreElements())
             {
               Property prop = new Property();
               String key = props.nextElement();
               prop.setName(key);
               prop.setValue(entry.getProperty(key).toString());
-              item.addProperty(prop);
+              // item.addProperty(prop);
+              pdb.getProperty().add(prop);
             }
-            pdb.addPdbentryItem(item);
+            // pdb.addPdbentryItem(item);
           }
 
-          jseq.addPdbids(pdb);
+          // jseq.addPdbids(pdb);
+          jseq.getPdbids().add(pdb);
         }
       }
 
       saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
 
-      jms.addJSeq(jseq);
+      // jms.addJSeq(jseq);
+      object.getJSeq().add(jseq);
     }
 
     if (!storeDS && av.hasHiddenRows())
@@ -1043,12 +1170,14 @@ public class Jalview2XML
             alcmap.setDnasq(seqHash(dnas[m]));
             alcmap.setMapping(
                     createVamsasMapping(pmaps[m], dnas[m], null, false));
-            alc.addAlcodMap(alcmap);
+            // alc.addAlcodMap(alcmap);
+            alc.getAlcodMap().add(alcmap);
             hasMap = true;
           }
           if (hasMap)
           {
-            vamsasSet.addAlcodonFrame(alc);
+            // vamsasSet.addAlcodonFrame(alc);
+            vamsasSet.getAlcodonFrame().add(alc);
           }
         }
         // TODO: delete this ? dead code from 2.8.3->2.9 ?
@@ -1101,13 +1230,13 @@ public class Jalview2XML
           {
             TreePanel tp = (TreePanel) frames[t];
 
-            if (tp.treeCanvas.av.getAlignment() == jal)
+            if (tp.getTreeCanvas().getViewport().getAlignment() == jal)
             {
-              Tree tree = new Tree();
+              JalviewModel.Tree tree = new JalviewModel.Tree();
               tree.setTitle(tp.getTitle());
               tree.setCurrentTree((av.getCurrentTree() == tp.getTree()));
               tree.setNewick(tp.getTree().print());
-              tree.setThreshold(tp.treeCanvas.threshold);
+              tree.setThreshold(tp.getTreeCanvas().getThreshold());
 
               tree.setFitToWindow(tp.fitToWindow.getState());
               tree.setFontName(tp.getTreeFont().getName());
@@ -1123,13 +1252,35 @@ public class Jalview2XML
               tree.setXpos(tp.getX());
               tree.setYpos(tp.getY());
               tree.setId(makeHashCode(tp, null));
-              jms.addTree(tree);
+              tree.setLinkToAllViews(
+                      tp.getTreeCanvas().isApplyToAllViews());
+
+              // jms.addTree(tree);
+              object.getTree().add(tree);
             }
           }
         }
       }
     }
 
+    /*
+     * save PCA viewers
+     */
+    if (!storeDS && Desktop.desktop != null)
+    {
+      for (JInternalFrame frame : Desktop.desktop.getAllFrames())
+      {
+        if (frame instanceof PCAPanel)
+        {
+          PCAPanel panel = (PCAPanel) frame;
+          if (panel.getAlignViewport().getAlignment() == jal)
+          {
+            savePCA(panel, object);
+          }
+        }
+      }
+    }
+
     // SAVE ANNOTATIONS
     /**
      * store forward refs from an annotationRow to any groups
@@ -1187,7 +1338,8 @@ public class Jalview2XML
             if (colourScheme instanceof jalview.schemes.UserColourScheme)
             {
               jGroup.setColour(
-                      setUserColourScheme(colourScheme, userColours, jms));
+                      setUserColourScheme(colourScheme, userColours,
+                              object));
             }
             else
             {
@@ -1199,12 +1351,12 @@ public class Jalview2XML
             jGroup.setColour("AnnotationColourGradient");
             jGroup.setAnnotationColours(constructAnnotationColours(
                     (jalview.schemes.AnnotationColourGradient) colourScheme,
-                    userColours, jms));
+                    userColours, object));
           }
           else if (colourScheme instanceof jalview.schemes.UserColourScheme)
           {
             jGroup.setColour(
-                    setUserColourScheme(colourScheme, userColours, jms));
+                    setUserColourScheme(colourScheme, userColours, object));
           }
           else
           {
@@ -1228,11 +1380,17 @@ public class Jalview2XML
         jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
         for (SequenceI seq : sg.getSequences())
         {
-          jGroup.addSeq(seqHash(seq));
+          // jGroup.addSeq(seqHash(seq));
+          jGroup.getSeq().add(seqHash(seq));
         }
       }
 
-      jms.setJGroup(groups);
+      //jms.setJGroup(groups);
+      Object group;
+      for (JGroup grp : groups)
+      {
+        object.getJGroup().add(grp);
+      }
     }
     if (!storeDS)
     {
@@ -1246,7 +1404,7 @@ public class Jalview2XML
       {
         view.setComplementId(av.getCodingComplement().getViewId());
       }
-      view.setViewName(av.viewName);
+      view.setViewName(av.getViewName());
       view.setGatheredViews(av.isGatherViewsHere());
 
       Rectangle size = ap.av.getExplodedGeometry();
@@ -1276,15 +1434,15 @@ public class Jalview2XML
       if (av.getGlobalColourScheme() instanceof jalview.schemes.UserColourScheme)
       {
         view.setBgColour(setUserColourScheme(av.getGlobalColourScheme(),
-                userColours, jms));
+                userColours, object));
       }
       else if (av
               .getGlobalColourScheme() instanceof jalview.schemes.AnnotationColourGradient)
       {
-        AnnotationColours ac = constructAnnotationColours(
+        AnnotationColourScheme ac = constructAnnotationColours(
                 (jalview.schemes.AnnotationColourGradient) av
                         .getGlobalColourScheme(),
-                userColours, jms);
+                userColours, object);
 
         view.setAnnotationColours(ac);
         view.setBgColour("AnnotationColourGradient");
@@ -1305,7 +1463,7 @@ public class Jalview2XML
           view.setConsThreshold(vcs.getConservationInc());
           if (cs instanceof jalview.schemes.UserColourScheme)
           {
-            view.setBgColour(setUserColourScheme(cs, userColours, jms));
+            view.setBgColour(setUserColourScheme(cs, userColours, object));
           }
         }
         view.setPidThreshold(vcs.getThreshold());
@@ -1313,9 +1471,10 @@ public class Jalview2XML
 
       view.setConservationSelected(av.getConservationSelected());
       view.setPidSelected(av.getAbovePIDThreshold());
-      view.setFontName(av.font.getName());
-      view.setFontSize(av.font.getSize());
-      view.setFontStyle(av.font.getStyle());
+      final Font font = av.getFont();
+      view.setFontName(font.getName());
+      view.setFontSize(font.getSize());
+      view.setFontStyle(font.getStyle());
       view.setScaleProteinAsCdna(av.getViewStyle().isScaleProteinAsCdna());
       view.setRenderGaps(av.isRenderGaps());
       view.setShowAnnotation(av.isShowAnnotation());
@@ -1342,7 +1501,7 @@ public class Jalview2XML
       view.setIgnoreGapsinConsensus(av.isIgnoreGapsConsensus());
       if (av.getFeaturesDisplayed() != null)
       {
-        jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
+        FeatureSettings fs = new FeatureSettings();
 
         FeatureRenderer fr = ap.getSeqPanel().seqCanvas
                 .getFeatureRenderer();
@@ -1353,7 +1512,7 @@ public class Jalview2XML
         {
           for (String featureType : renderOrder)
           {
-            Setting setting = new Setting();
+            FeatureSettings.Setting setting = new FeatureSettings.Setting();
             setting.setType(featureType);
 
             /*
@@ -1380,7 +1539,12 @@ public class Jalview2XML
               setting.setColourByLabel(fcol.isColourByLabel());
               if (fcol.isColourByAttribute())
               {
-                setting.setAttributeName(fcol.getAttributeName());
+                String[] attName = fcol.getAttributeName();
+                setting.getAttributeName().add(attName[0]);
+                if (attName.length > 1)
+                {
+                  setting.getAttributeName().add(attName[1]);
+                }
               }
               setting.setAutoScale(fcol.isAutoScaled());
               setting.setThreshold(fcol.getThreshold());
@@ -1414,7 +1578,8 @@ public class Jalview2XML
             {
               setting.setOrder(rorder);
             }
-            fs.addSetting(setting);
+            /// fs.addSetting(setting);
+            fs.getSetting().add(setting);
             settingsAdded.addElement(featureType);
           }
         }
@@ -1433,10 +1598,12 @@ public class Jalview2XML
           g.setName(grp);
           g.setDisplay(((Boolean) fr.checkGroupVisibility(grp, false))
                           .booleanValue());
-          fs.addGroup(g);
+          // fs.addGroup(g);
+          fs.getGroup().add(g);
           groupsAdded.addElement(grp);
         }
-        jms.setFeatureSettings(fs);
+        // jms.setFeatureSettings(fs);
+        object.setFeatureSettings(fs);
       }
 
       if (av.hasHiddenColumns())
@@ -1456,7 +1623,8 @@ public class Jalview2XML
             HiddenColumns hc = new HiddenColumns();
             hc.setStart(region[0]);
             hc.setEnd(region[1]);
-            view.addHiddenColumns(hc);
+            // view.addHiddenColumns(hc);
+            view.getHiddenColumns().add(hc);
           }
         }
       }
@@ -1470,16 +1638,19 @@ public class Jalview2XML
             // Some calcIds have no parameters.
             if (cidp != null)
             {
-              view.addCalcIdParam(cidp);
+              // view.addCalcIdParam(cidp);
+              view.getCalcIdParam().add(cidp);
             }
           }
         }
       }
 
-      jms.addViewport(view);
+      // jms.addViewport(view);
+      object.getViewport().add(view);
     }
-    object.setJalviewModelSequence(jms);
-    object.getVamsasModel().addSequenceSet(vamsasSet);
+    // object.setJalviewModelSequence(jms);
+    // object.getVamsasModel().addSequenceSet(vamsasSet);
+    object.getVamsasModel().getSequenceSet().add(vamsasSet);
 
     if (jout != null && fileName != null)
     {
@@ -1493,13 +1664,23 @@ public class Jalview2XML
         jout.putNextEntry(entry);
         PrintWriter pout = new PrintWriter(
                 new OutputStreamWriter(jout, UTF_8));
-        Marshaller marshaller = new Marshaller(pout);
-        marshaller.marshal(object);
+        JAXBContext jaxbContext = JAXBContext
+                .newInstance(JalviewModel.class);
+        Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
+
+        // output pretty printed
+        // jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+        jaxbMarshaller.marshal(
+                new ObjectFactory().createJalviewModel(object), pout);
+
+        // jaxbMarshaller.marshal(object, pout);
+        // marshaller.marshal(object);
         pout.flush();
         jout.closeEntry();
       } catch (Exception ex)
       {
         // TODO: raise error in GUI if marshalling failed.
+        System.err.println("Error writing Jalview project");
         ex.printStackTrace();
       }
     }
@@ -1507,6 +1688,196 @@ public class Jalview2XML
   }
 
   /**
+   * Writes PCA viewer attributes and computed values to an XML model object and
+   * adds it to the JalviewModel. Any exceptions are reported by logging.
+   */
+  protected void savePCA(PCAPanel panel, JalviewModel object)
+  {
+    try
+    {
+      PcaViewer viewer = new PcaViewer();
+      viewer.setHeight(panel.getHeight());
+      viewer.setWidth(panel.getWidth());
+      viewer.setXpos(panel.getX());
+      viewer.setYpos(panel.getY());
+      viewer.setTitle(panel.getTitle());
+      PCAModel pcaModel = panel.getPcaModel();
+      viewer.setScoreModelName(pcaModel.getScoreModelName());
+      viewer.setXDim(panel.getSelectedDimensionIndex(X));
+      viewer.setYDim(panel.getSelectedDimensionIndex(Y));
+      viewer.setZDim(panel.getSelectedDimensionIndex(Z));
+      viewer.setBgColour(
+              panel.getRotatableCanvas().getBackgroundColour().getRGB());
+      viewer.setScaleFactor(panel.getRotatableCanvas().getScaleFactor());
+      float[] spMin = panel.getRotatableCanvas().getSeqMin();
+      SeqPointMin spmin = new SeqPointMin();
+      spmin.setXPos(spMin[0]);
+      spmin.setYPos(spMin[1]);
+      spmin.setZPos(spMin[2]);
+      viewer.setSeqPointMin(spmin);
+      float[] spMax = panel.getRotatableCanvas().getSeqMax();
+      SeqPointMax spmax = new SeqPointMax();
+      spmax.setXPos(spMax[0]);
+      spmax.setYPos(spMax[1]);
+      spmax.setZPos(spMax[2]);
+      viewer.setSeqPointMax(spmax);
+      viewer.setShowLabels(panel.getRotatableCanvas().isShowLabels());
+      viewer.setLinkToAllViews(
+              panel.getRotatableCanvas().isApplyToAllViews());
+      SimilarityParamsI sp = pcaModel.getSimilarityParameters();
+      viewer.setIncludeGaps(sp.includeGaps());
+      viewer.setMatchGaps(sp.matchGaps());
+      viewer.setIncludeGappedColumns(sp.includeGappedColumns());
+      viewer.setDenominateByShortestLength(sp.denominateByShortestLength());
+
+      /*
+       * sequence points on display
+       */
+      for (jalview.datamodel.SequencePoint spt : pcaModel
+              .getSequencePoints())
+      {
+        SequencePoint point = new SequencePoint();
+        point.setSequenceRef(seqHash(spt.getSequence()));
+        point.setXPos(spt.coord.x);
+        point.setYPos(spt.coord.y);
+        point.setZPos(spt.coord.z);
+        viewer.getSequencePoint().add(point);
+      }
+
+      /*
+       * (end points of) axes on display
+       */
+      for (Point p : panel.getRotatableCanvas().getAxisEndPoints())
+      {
+
+        Axis axis = new Axis();
+        axis.setXPos(p.x);
+        axis.setYPos(p.y);
+        axis.setZPos(p.z);
+        viewer.getAxis().add(axis);
+      }
+
+      /*
+       * raw PCA data (note we are not restoring PCA inputs here -
+       * alignment view, score model, similarity parameters)
+       */
+      PcaDataType data = new PcaDataType();
+      viewer.setPcaData(data);
+      PCA pca = pcaModel.getPcaData();
+
+      DoubleMatrix pm = new DoubleMatrix();
+      saveDoubleMatrix(pca.getPairwiseScores(), pm);
+      data.setPairwiseMatrix(pm);
+
+      DoubleMatrix tm = new DoubleMatrix();
+      saveDoubleMatrix(pca.getTridiagonal(), tm);
+      data.setTridiagonalMatrix(tm);
+
+      DoubleMatrix eigenMatrix = new DoubleMatrix();
+      data.setEigenMatrix(eigenMatrix);
+      saveDoubleMatrix(pca.getEigenmatrix(), eigenMatrix);
+
+      object.getPcaViewer().add(viewer);
+    } catch (Throwable t)
+    {
+      Cache.log.error("Error saving PCA: " + t.getMessage());
+    }
+  }
+
+  /**
+   * Stores values from a matrix into an XML element, including (if present) the
+   * D or E vectors
+   * 
+   * @param m
+   * @param xmlMatrix
+   * @see #loadDoubleMatrix(DoubleMatrix)
+   */
+  protected void saveDoubleMatrix(MatrixI m, DoubleMatrix xmlMatrix)
+  {
+    xmlMatrix.setRows(m.height());
+    xmlMatrix.setColumns(m.width());
+    for (int i = 0; i < m.height(); i++)
+    {
+      DoubleVector row = new DoubleVector();
+      for (int j = 0; j < m.width(); j++)
+      {
+        row.getV().add(m.getValue(i, j));
+      }
+      xmlMatrix.getRow().add(row);
+    }
+    if (m.getD() != null)
+    {
+      DoubleVector dVector = new DoubleVector();
+      for (double d : m.getD())
+      {
+        dVector.getV().add(d);
+      }
+      xmlMatrix.setD(dVector);
+    }
+    if (m.getE() != null)
+    {
+      DoubleVector eVector = new DoubleVector();
+      for (double e : m.getE())
+      {
+        eVector.getV().add(e);
+      }
+      xmlMatrix.setE(eVector);
+    }
+  }
+
+  /**
+   * Loads XML matrix data into a new Matrix object, including the D and/or E
+   * vectors (if present)
+   * 
+   * @param mData
+   * @return
+   * @see Jalview2XML#saveDoubleMatrix(MatrixI, DoubleMatrix)
+   */
+  protected MatrixI loadDoubleMatrix(DoubleMatrix mData)
+  {
+    int rows = mData.getRows();
+    double[][] vals = new double[rows][];
+
+    for (int i = 0; i < rows; i++)
+    {
+      List<Double> dVector = mData.getRow().get(i).getV();
+      vals[i] = new double[dVector.size()];
+      int dvi = 0;
+      for (Double d : dVector)
+      {
+        vals[i][dvi++] = d;
+      }
+    }
+
+    MatrixI m = new Matrix(vals);
+
+    if (mData.getD() != null)
+    {
+      List<Double> dVector = mData.getD().getV();
+      double[] vec = new double[dVector.size()];
+      int dvi = 0;
+      for (Double d : dVector)
+      {
+        vec[dvi++] = d;
+      }
+      m.setD(vec);
+    }
+    if (mData.getE() != null)
+    {
+      List<Double> dVector = mData.getE().getV();
+      double[] vec = new double[dVector.size()];
+      int dvi = 0;
+      for (Double d : dVector)
+      {
+        vec[dvi++] = d;
+      }
+      m.setE(vec);
+    }
+
+    return m;
+  }
+
+  /**
    * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
    * for each viewer, with
    * <ul>
@@ -1560,7 +1931,8 @@ public class Jalview2XML
           rna.setHeight(varna.getHeight());
           rna.setDividerLocation(varna.getDividerLocation());
           rna.setSelectedRna(varna.getSelectedIndex());
-          jseq.addRnaViewer(rna);
+          // jseq.addRnaViewer(rna);
+          jseq.getRnaViewer().add(rna);
 
           /*
            * Store each Varna panel's state once in the project per sequence.
@@ -1596,7 +1968,8 @@ public class Jalview2XML
               ss.setViewerState(jarEntryName);
               ss.setGapped(model.gapped);
               ss.setTitle(model.title);
-              rna.addSecondaryStructure(ss);
+              // rna.addSecondaryStructure(ss);
+              rna.getSecondaryStructure().add(ss);
             }
           }
         }
@@ -1735,7 +2108,8 @@ public class Jalview2XML
           state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap));
           state.setColourByJmol(viewFrame.isColouredByViewer());
           state.setType(viewFrame.getViewerType().toString());
-          pdb.addStructureState(state);
+          // pdb.addStructureState(state);
+          pdb.getStructureState().add(state);
         }
       }
     }
@@ -1743,19 +2117,19 @@ public class Jalview2XML
   }
 
   /**
-   * Populates the AnnotationColours xml for save. This captures the settings of
-   * the options in the 'Colour by Annotation' dialog.
+   * Populates the AnnotationColourScheme xml for save. This captures the
+   * settings of the options in the 'Colour by Annotation' dialog.
    * 
    * @param acg
    * @param userColours
-   * @param jms
+   * @param jm
    * @return
    */
-  private AnnotationColours constructAnnotationColours(
+  private AnnotationColourScheme constructAnnotationColours(
           AnnotationColourGradient acg, List<UserColourScheme> userColours,
-          JalviewModelSequence jms)
+          JalviewModel jm)
   {
-    AnnotationColours ac = new AnnotationColours();
+    AnnotationColourScheme ac = new AnnotationColourScheme();
     ac.setAboveThreshold(acg.getAboveThreshold());
     ac.setThreshold(acg.getAnnotationThreshold());
     // 2.10.2 save annotationId (unique) not annotation label
@@ -1763,7 +2137,7 @@ public class Jalview2XML
     if (acg.getBaseColour() instanceof UserColourScheme)
     {
       ac.setColourScheme(
-              setUserColourScheme(acg.getBaseColour(), userColours, jms));
+              setUserColourScheme(acg.getBaseColour(), userColours, jm));
     }
     else
     {
@@ -1869,10 +2243,11 @@ public class Jalview2XML
       {
         for (String pr : annotation.getProperties())
         {
-          Property prop = new Property();
+          jalview.xml.binding.jalview.Annotation.Property prop = new jalview.xml.binding.jalview.Annotation.Property();
           prop.setName(pr);
           prop.setValue(annotation.getProperty(pr));
-          an.addProperty(prop);
+          // an.addProperty(prop);
+          an.getProperty().add(prop);
         }
       }
 
@@ -1916,7 +2291,8 @@ public class Jalview2XML
             ae.setColour(annotation.annotations[a].colour.getRGB());
           }
 
-          an.addAnnotationElement(ae);
+          // an.addAnnotationElement(ae);
+          an.getAnnotationElement().add(ae);
           if (annotation.autoCalculated)
           {
             // only write one non-null entry into the annotation row -
@@ -1934,7 +2310,8 @@ public class Jalview2XML
       {
         // skip autocalculated annotation - these are only provided for
         // alignments
-        vamsasSet.addAnnotation(an);
+        // vamsasSet.addAnnotation(an);
+        vamsasSet.getAnnotation().add(an);
       }
     }
 
@@ -1947,12 +2324,14 @@ public class Jalview2XML
     {
       CalcIdParam vCalcIdParam = new CalcIdParam();
       vCalcIdParam.setCalcId(calcId);
-      vCalcIdParam.addServiceURL(settings.getServiceURI());
+      // vCalcIdParam.addServiceURL(settings.getServiceURI());
+      vCalcIdParam.getServiceURL().add(settings.getServiceURI());
       // generic URI allowing a third party to resolve another instance of the
       // service used for this calculation
-      for (String urls : settings.getServiceURLs())
+      for (String url : settings.getServiceURLs())
       {
-        vCalcIdParam.addServiceURL(urls);
+        // vCalcIdParam.addServiceURL(urls);
+        vCalcIdParam.getServiceURL().add(url);
       }
       vCalcIdParam.setVersion("1.0");
       if (settings.getPreset() != null)
@@ -1984,8 +2363,9 @@ public class Jalview2XML
   {
     if (calcIdParam.getVersion().equals("1.0"))
     {
+      final String[] calcIds = calcIdParam.getServiceURL().toArray(new String[0]);
       Jws2Instance service = Jws2Discoverer.getDiscoverer()
-              .getPreferredServiceFor(calcIdParam.getServiceURL());
+              .getPreferredServiceFor(calcIds);
       if (service != null)
       {
         WsParamSetI parmSet = null;
@@ -1993,7 +2373,7 @@ public class Jalview2XML
         {
           parmSet = service.getParamStore().parseServiceParameterFile(
                   calcIdParam.getName(), calcIdParam.getDescription(),
-                  calcIdParam.getServiceURL(),
+                  calcIds,
                   calcIdParam.getParameters().replace("|\\n|", "\n"));
         } catch (IOException x)
         {
@@ -2139,7 +2519,8 @@ public class Jalview2XML
                   jds, recurse);
           dbref.setMapping(mp);
         }
-        vamsasSeq.addDBRef(dbref);
+        // vamsasSeq.addDBRef(dbref);
+        vamsasSeq.getDBRef().add(dbref);
       }
     }
     return vamsasSeq;
@@ -2160,7 +2541,8 @@ public class Jalview2XML
         MapListFrom mfrom = new MapListFrom();
         mfrom.setStart(range[0]);
         mfrom.setEnd(range[1]);
-        mp.addMapListFrom(mfrom);
+        // mp.addMapListFrom(mfrom);
+        mp.getMapListFrom().add(mfrom);
       }
       r = mlst.getToRanges();
       for (int[] range : r)
@@ -2168,13 +2550,14 @@ public class Jalview2XML
         MapListTo mto = new MapListTo();
         mto.setStart(range[0]);
         mto.setEnd(range[1]);
-        mp.addMapListTo(mto);
+        // mp.addMapListTo(mto);
+        mp.getMapListTo().add(mto);
       }
-      mp.setMapFromUnit(mlst.getFromRatio());
-      mp.setMapToUnit(mlst.getToRatio());
+      mp.setMapFromUnit(BigInteger.valueOf(mlst.getFromRatio()));
+      mp.setMapToUnit(BigInteger.valueOf(mlst.getToRatio()));
       if (jmp.getTo() != null)
       {
-        MappingChoice mpc = new MappingChoice();
+        // MappingChoice mpc = new MappingChoice();
 
         // check/create ID for the sequence referenced by getTo()
 
@@ -2190,25 +2573,26 @@ public class Jalview2XML
         {
           jmpid = seqHash(ps = parentseq);
         }
-        mpc.setDseqFor(jmpid);
-        if (!seqRefIds.containsKey(mpc.getDseqFor()))
+        // mpc.setDseqFor(jmpid);
+        mp.setDseqFor(jmpid);
+        if (!seqRefIds.containsKey(jmpid))
         {
           jalview.bin.Cache.log.debug("creatign new DseqFor ID");
-          seqRefIds.put(mpc.getDseqFor(), ps);
+          seqRefIds.put(jmpid, ps);
         }
         else
         {
           jalview.bin.Cache.log.debug("reusing DseqFor ID");
         }
 
-        mp.setMappingChoice(mpc);
+        // mp.setMappingChoice(mpc);
       }
     }
     return mp;
   }
 
   String setUserColourScheme(jalview.schemes.ColourSchemeI cs,
-          List<UserColourScheme> userColours, JalviewModelSequence jms)
+          List<UserColourScheme> userColours, JalviewModel jm)
   {
     String id = null;
     jalview.schemes.UserColourScheme ucs = (jalview.schemes.UserColourScheme) cs;
@@ -2223,48 +2607,60 @@ public class Jalview2XML
     {
       // actually create the scheme's entry in the XML model
       java.awt.Color[] colours = ucs.getColours();
-      jalview.schemabinding.version2.UserColours uc = new jalview.schemabinding.version2.UserColours();
-      jalview.schemabinding.version2.UserColourScheme jbucs = new jalview.schemabinding.version2.UserColourScheme();
+      UserColours uc = new UserColours();
+      // UserColourScheme jbucs = new UserColourScheme();
+      JalviewUserColours jbucs = new JalviewUserColours();
 
       for (int i = 0; i < colours.length; i++)
       {
-        jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
+        Colour col = new Colour();
         col.setName(ResidueProperties.aa[i]);
         col.setRGB(jalview.util.Format.getHexString(colours[i]));
-        jbucs.addColour(col);
+        // jbucs.addColour(col);
+        jbucs.getColour().add(col);
       }
       if (ucs.getLowerCaseColours() != null)
       {
         colours = ucs.getLowerCaseColours();
         for (int i = 0; i < colours.length; i++)
         {
-          jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
+          Colour col = new Colour();
           col.setName(ResidueProperties.aa[i].toLowerCase());
           col.setRGB(jalview.util.Format.getHexString(colours[i]));
-          jbucs.addColour(col);
+          // jbucs.addColour(col);
+          jbucs.getColour().add(col);
         }
       }
 
       uc.setId(id);
       uc.setUserColourScheme(jbucs);
-      jms.addUserColours(uc);
+      // jm.addUserColours(uc);
+      jm.getUserColours().add(uc);
     }
 
     return id;
   }
 
   jalview.schemes.UserColourScheme getUserColourScheme(
-          JalviewModelSequence jms, String id)
+          JalviewModel jm, String id)
   {
-    UserColours[] uc = jms.getUserColours();
+    List<UserColours> uc = jm.getUserColours();
     UserColours colours = null;
-
+/*
     for (int i = 0; i < uc.length; i++)
     {
       if (uc[i].getId().equals(id))
       {
         colours = uc[i];
-
+        break;
+      }
+    }
+*/
+    for (UserColours c : uc)
+    {
+      if (c.getId().equals(id))
+      {
+        colours = c;
         break;
       }
     }
@@ -2274,19 +2670,22 @@ public class Jalview2XML
     for (int i = 0; i < 24; i++)
     {
       newColours[i] = new java.awt.Color(Integer.parseInt(
-              colours.getUserColourScheme().getColour(i).getRGB(), 16));
+              // colours.getUserColourScheme().getColour(i).getRGB(), 16));
+              colours.getUserColourScheme().getColour().get(i).getRGB(),
+              16));
     }
 
     jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
             newColours);
 
-    if (colours.getUserColourScheme().getColourCount() > 24)
+    if (colours.getUserColourScheme().getColour().size()/*Count()*/ > 24)
     {
       newColours = new java.awt.Color[23];
       for (int i = 0; i < 23; i++)
       {
         newColours[i] = new java.awt.Color(Integer.parseInt(
-                colours.getUserColourScheme().getColour(i + 24).getRGB(),
+                colours.getUserColourScheme().getColour().get(i + 24)
+                        .getRGB(),
                 16));
       }
       ucs.setLowerCaseColours(newColours);
@@ -2304,7 +2703,7 @@ public class Jalview2XML
    * flag to control whether the Jalview2XML_V1 parser should be deferred to if
    * exceptions are raised during project XML parsing
    */
-  public boolean attemptversion1parse = true;
+  public boolean attemptversion1parse = false;
 
   /**
    * Load a jalview project archive from a jar file
@@ -2328,8 +2727,10 @@ public class Jalview2XML
 
       jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
       af = loadJalviewAlign(jprovider);
-      af.setMenusForViewport();
-
+      if (af != null)
+      {
+        af.setMenusForViewport();
+      }
     } catch (MalformedURLException e)
     {
       errorMessage = "Invalid URL format for '" + file + "'";
@@ -2434,32 +2835,45 @@ public class Jalview2XML
         if (jarentry != null && jarentry.getName().endsWith(".xml"))
         {
           InputStreamReader in = new InputStreamReader(jin, UTF_8);
-          JalviewModel object = new JalviewModel();
+          // JalviewModel object = new JalviewModel();
 
+          JAXBContext jc = JAXBContext
+                  .newInstance("jalview.xml.binding.jalview");
+          XMLStreamReader streamReader = XMLInputFactory.newInstance()
+                  .createXMLStreamReader(jin);
+          javax.xml.bind.Unmarshaller um = jc.createUnmarshaller();
+          JAXBElement<JalviewModel> jbe = um
+                  .unmarshal(streamReader, JalviewModel.class);
+          JalviewModel object = jbe.getValue();
+
+          /*
           Unmarshaller unmar = new Unmarshaller(object);
           unmar.setValidation(false);
           object = (JalviewModel) unmar.unmarshal(in);
+          */
           if (true) // !skipViewport(object))
           {
             _af = loadFromObject(object, file, true, jprovider);
-            if (_af != null && object.getJalviewModelSequence()
-                    .getViewportCount() > 0)
+            if (_af != null && object.getViewport().size() > 0)
+            // getJalviewModelSequence().getViewportCount() > 0)
             {
               if (af == null)
               {
                 // store a reference to the first view
                 af = _af;
               }
-              if (_af.viewport.isGatherViewsHere())
+              if (_af.getViewport().isGatherViewsHere())
               {
                 // if this is a gathered view, keep its reference since
                 // after gathering views, only this frame will remain
                 af = _af;
-                gatherToThisFrame.put(_af.viewport.getSequenceSetId(), _af);
+                gatherToThisFrame.put(_af.getViewport().getSequenceSetId(),
+                        _af);
               }
               // Save dataset to register mappings once all resolved
-              importedDatasets.put(af.viewport.getAlignment().getDataset(),
-                      af.viewport.getAlignment().getDataset());
+              importedDatasets.put(
+                      af.getViewport().getAlignment().getDataset(),
+                      af.getViewport().getAlignment().getDataset());
             }
           }
           entryCount++;
@@ -2483,16 +2897,7 @@ public class Jalview2XML
       ex.printStackTrace(System.err);
       if (attemptversion1parse)
       {
-        // Is Version 1 Jar file?
-        try
-        {
-          af = new Jalview2XML_V1(raiseGUI).LoadJalviewAlign(jprovider);
-        } catch (Exception ex2)
-        {
-          System.err.println("Exception whilst loading as jalviewXMLV1:");
-          ex2.printStackTrace();
-          af = null;
-        }
+        // used to attempt to parse as V1 castor-generated xml
       }
       if (Desktop.instance != null)
       {
@@ -2593,7 +2998,7 @@ public class Jalview2XML
           addedToSplitFrames.add(af);
           dnaFrame.setMenusForViewport();
           af.setMenusForViewport();
-          if (af.viewport.isGatherViewsHere())
+          if (af.getViewport().isGatherViewsHere())
           {
             gatherTo.add(sf);
           }
@@ -2612,8 +3017,8 @@ public class Jalview2XML
       if (!addedToSplitFrames.contains(af))
       {
         Viewport view = candidate.getKey();
-        Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
-                view.getHeight());
+        Desktop.addInternalFrame(af, view.getTitle(),
+                safeInt(view.getWidth()), safeInt(view.getHeight()));
         af.setMenusForViewport();
         System.err.println("Failed to restore view " + view.getTitle()
                 + " to split frame");
@@ -2657,7 +3062,7 @@ public class Jalview2XML
      * And compute cDNA consensus (couldn't do earlier with consensus as
      * mappings were not yet present)
      */
-    proteinFrame.viewport.alignmentChanged(proteinFrame.alignPanel);
+    proteinFrame.getViewport().alignmentChanged(proteinFrame.alignPanel);
 
     return splitFrame;
   }
@@ -2845,7 +3250,7 @@ public class Jalview2XML
   /**
    * Load alignment frame from jalview XML DOM object
    * 
-   * @param object
+   * @param jalviewModel
    *          DOM
    * @param file
    *          filename source string
@@ -2855,18 +3260,43 @@ public class Jalview2XML
    *          data source provider
    * @return alignment frame created from view stored in DOM
    */
-  AlignFrame loadFromObject(JalviewModel object, String file,
+  AlignFrame loadFromObject(JalviewModel jalviewModel, String file,
           boolean loadTreesAndStructures, jarInputStreamProvider jprovider)
   {
-    SequenceSet vamsasSet = object.getVamsasModel().getSequenceSet(0);
-    Sequence[] vamsasSeq = vamsasSet.getSequence();
+    SequenceSet vamsasSet = jalviewModel.getVamsasModel().getSequenceSet().get(0);
+    List<Sequence> vamsasSeqs = vamsasSet.getSequence();
 
-    JalviewModelSequence jms = object.getJalviewModelSequence();
+    // JalviewModelSequence jms = object.getJalviewModelSequence();
 
-    Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
+    // Viewport view = (jms.getViewportCount() > 0) ? jms.getViewport(0)
+    // : null;
+    Viewport view = (jalviewModel.getViewport().size() > 0)
+            ? jalviewModel.getViewport().get(0)
             : null;
 
     // ////////////////////////////////
+    // INITIALISE ALIGNMENT SEQUENCESETID AND VIEWID
+    //
+    //
+    // If we just load in the same jar file again, the sequenceSetId
+    // will be the same, and we end up with multiple references
+    // to the same sequenceSet. We must modify this id on load
+    // so that each load of the file gives a unique id
+
+    /**
+     * used to resolve correct alignment dataset for alignments with multiple
+     * views
+     */
+    String uniqueSeqSetId = null;
+    String viewId = null;
+    if (view != null)
+    {
+      uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
+      viewId = (view.getId() == null ? null
+              : view.getId() + uniqueSetSuffix);
+    }
+
+    // ////////////////////////////////
     // LOAD SEQUENCES
 
     List<SequenceI> hiddenSeqs = null;
@@ -2875,11 +3305,13 @@ public class Jalview2XML
 
     boolean multipleView = false;
     SequenceI referenceseqForView = null;
-    JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
+    // JSeq[] jseqs = object.getJalviewModelSequence().getJSeq();
+    List<JSeq> jseqs = jalviewModel.getJSeq();
     int vi = 0; // counter in vamsasSeq array
-    for (int i = 0; i < jseqs.length; i++)
+    for (int i = 0; i < jseqs.size(); i++)
     {
-      String seqId = jseqs[i].getId();
+      JSeq jseq = jseqs.get(i);
+      String seqId = jseq.getId();
 
       SequenceI tmpSeq = seqRefIds.get(seqId);
       if (tmpSeq != null)
@@ -2887,25 +3319,26 @@ public class Jalview2XML
         if (!incompleteSeqs.containsKey(seqId))
         {
           // may not need this check, but keep it for at least 2.9,1 release
-          if (tmpSeq.getStart() != jseqs[i].getStart()
-                  || tmpSeq.getEnd() != jseqs[i].getEnd())
+          if (tmpSeq.getStart() != jseq.getStart()
+                  || tmpSeq.getEnd() != jseq.getEnd())
           {
             System.err.println(
                     "Warning JAL-2154 regression: updating start/end for sequence "
-                            + tmpSeq.toString() + " to " + jseqs[i]);
+                            + tmpSeq.toString() + " to " + jseq);
           }
         }
         else
         {
           incompleteSeqs.remove(seqId);
         }
-        if (vamsasSeq.length > vi && vamsasSeq[vi].getId().equals(seqId))
+        if (vamsasSeqs.size() > vi
+                && vamsasSeqs.get(vi).getId().equals(seqId))
         {
           // most likely we are reading a dataset XML document so
           // update from vamsasSeq section of XML for this sequence
-          tmpSeq.setName(vamsasSeq[vi].getName());
-          tmpSeq.setDescription(vamsasSeq[vi].getDescription());
-          tmpSeq.setSequence(vamsasSeq[vi].getSequence());
+          tmpSeq.setName(vamsasSeqs.get(vi).getName());
+          tmpSeq.setDescription(vamsasSeqs.get(vi).getDescription());
+          tmpSeq.setSequence(vamsasSeqs.get(vi).getSequence());
           vi++;
         }
         else
@@ -2913,29 +3346,30 @@ public class Jalview2XML
           // reading multiple views, so vamsasSeq set is a subset of JSeq
           multipleView = true;
         }
-        tmpSeq.setStart(jseqs[i].getStart());
-        tmpSeq.setEnd(jseqs[i].getEnd());
+        tmpSeq.setStart(jseq.getStart());
+        tmpSeq.setEnd(jseq.getEnd());
         tmpseqs.add(tmpSeq);
       }
       else
       {
-        tmpSeq = new jalview.datamodel.Sequence(vamsasSeq[vi].getName(),
-                vamsasSeq[vi].getSequence());
-        tmpSeq.setDescription(vamsasSeq[vi].getDescription());
-        tmpSeq.setStart(jseqs[i].getStart());
-        tmpSeq.setEnd(jseqs[i].getEnd());
+        Sequence vamsasSeq = vamsasSeqs.get(vi);
+        tmpSeq = new jalview.datamodel.Sequence(vamsasSeq.getName(),
+                vamsasSeq.getSequence());
+        tmpSeq.setDescription(vamsasSeq.getDescription());
+        tmpSeq.setStart(jseq.getStart());
+        tmpSeq.setEnd(jseq.getEnd());
         tmpSeq.setVamsasId(uniqueSetSuffix + seqId);
-        seqRefIds.put(vamsasSeq[vi].getId(), tmpSeq);
+        seqRefIds.put(vamsasSeq.getId(), tmpSeq);
         tmpseqs.add(tmpSeq);
         vi++;
       }
 
-      if (jseqs[i].hasViewreference() && jseqs[i].getViewreference())
+      if (safeBoolean(jseq.isViewreference()))
       {
         referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
       }
 
-      if (jseqs[i].getHidden())
+      if (jseq.isHidden() != null && jseq.isHidden().booleanValue())
       {
         if (hiddenSeqs == null)
         {
@@ -2964,8 +3398,7 @@ public class Jalview2XML
     }
     else
     {
-      boolean isdsal = object.getJalviewModelSequence()
-              .getViewportCount() == 0;
+      boolean isdsal = jalviewModel.getViewport().isEmpty();
       if (isdsal)
       {
         // we are importing a dataset record, so
@@ -2984,7 +3417,7 @@ public class Jalview2XML
 
       // finally, verify all data in vamsasSet is actually present in al
       // passing on flag indicating if it is actually a stored dataset
-      recoverDatasetFor(vamsasSet, al, isdsal);
+      recoverDatasetFor(vamsasSet, al, isdsal, uniqueSeqSetId);
     }
 
     if (referenceseqForView != null)
@@ -2992,9 +3425,10 @@ public class Jalview2XML
       al.setSeqrep(referenceseqForView);
     }
     // / Add the alignment properties
-    for (int i = 0; i < vamsasSet.getSequenceSetPropertiesCount(); i++)
+    for (int i = 0; i < vamsasSet.getSequenceSetProperties().size(); i++)
     {
-      SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties(i);
+      SequenceSetProperties ssp = vamsasSet.getSequenceSetProperties()
+              .get(i);
       al.setProperty(ssp.getKey(), ssp.getValue());
     }
 
@@ -3011,26 +3445,27 @@ public class Jalview2XML
       // now, for 2.10 projects, this is also done if the xml doc includes
       // dataset sequences not actually present in any particular view.
       //
-      for (int i = 0; i < vamsasSeq.length; i++)
+      for (int i = 0; i < vamsasSeqs.size(); i++)
       {
-        if (jseqs[i].getFeaturesCount() > 0)
+        JSeq jseq = jseqs.get(i);
+        if (jseq.getFeatures().size() > 0)
         {
-          Features[] features = jseqs[i].getFeatures();
-          for (int f = 0; f < features.length; f++)
+          List<Feature> features = jseq.getFeatures();
+          for (int f = 0; f < features.size(); f++)
           {
-            SequenceFeature sf = new SequenceFeature(features[f].getType(),
-                    features[f].getDescription(), features[f].getBegin(),
-                    features[f].getEnd(), features[f].getScore(),
-                    features[f].getFeatureGroup());
-            sf.setStatus(features[f].getStatus());
+            Feature feat = features.get(f);
+            SequenceFeature sf = new SequenceFeature(feat.getType(),
+                    feat.getDescription(), feat.getBegin(), feat.getEnd(),
+                    safeFloat(feat.getScore()), feat.getFeatureGroup());
+            sf.setStatus(feat.getStatus());
 
             /*
              * load any feature attributes - include map-valued attributes
              */
             Map<String, Map<String, String>> mapAttributes = new HashMap<>();
-            for (int od = 0; od < features[f].getOtherDataCount(); od++)
+            for (int od = 0; od < feat.getOtherData().size(); od++)
             {
-              OtherData keyValue = features[f].getOtherData(od);
+              OtherData keyValue = feat.getOtherData().get(od);
               String attributeName = keyValue.getKey();
               String attributeValue = keyValue.getValue();
               if (attributeName.startsWith("LINK"))
@@ -3067,27 +3502,28 @@ public class Jalview2XML
             al.getSequenceAt(i).addSequenceFeature(sf);
           }
         }
-        if (vamsasSeq[i].getDBRefCount() > 0)
+        if (vamsasSeqs.get(i).getDBRef().size() > 0)
         {
           // adds dbrefs to datasequence's set (since Jalview 2.10)
           addDBRefs(
                   al.getSequenceAt(i).getDatasetSequence() == null
                           ? al.getSequenceAt(i)
                           : al.getSequenceAt(i).getDatasetSequence(),
-                  vamsasSeq[i]);
+                  vamsasSeqs.get(i));
         }
-        if (jseqs[i].getPdbidsCount() > 0)
+        if (jseq.getPdbids().size() > 0)
         {
-          Pdbids[] ids = jseqs[i].getPdbids();
-          for (int p = 0; p < ids.length; p++)
+          List<Pdbids> ids = jseq.getPdbids();
+          for (int p = 0; p < ids.size(); p++)
           {
+            Pdbids pdbid = ids.get(p);
             jalview.datamodel.PDBEntry entry = new jalview.datamodel.PDBEntry();
-            entry.setId(ids[p].getId());
-            if (ids[p].getType() != null)
+            entry.setId(pdbid.getId());
+            if (pdbid.getType() != null)
             {
-              if (PDBEntry.Type.getType(ids[p].getType()) != null)
+              if (PDBEntry.Type.getType(pdbid.getType()) != null)
               {
-                entry.setType(PDBEntry.Type.getType(ids[p].getType()));
+                entry.setType(PDBEntry.Type.getType(pdbid.getType()));
               }
               else
               {
@@ -3095,21 +3531,22 @@ public class Jalview2XML
               }
             }
             // jprovider is null when executing 'New View'
-            if (ids[p].getFile() != null && jprovider != null)
+            if (pdbid.getFile() != null && jprovider != null)
             {
-              if (!pdbloaded.containsKey(ids[p].getFile()))
+              if (!pdbloaded.containsKey(pdbid.getFile()))
               {
-                entry.setFile(loadPDBFile(jprovider, ids[p].getId(),
-                        ids[p].getFile()));
+                entry.setFile(loadPDBFile(jprovider, pdbid.getId(),
+                        pdbid.getFile()));
               }
               else
               {
-                entry.setFile(pdbloaded.get(ids[p].getId()).toString());
+                entry.setFile(pdbloaded.get(pdbid.getId()).toString());
               }
             }
-            if (ids[p].getPdbentryItem() != null)
+            /*
+            if (pdbid.getPdbentryItem() != null)
             {
-              for (PdbentryItem item : ids[p].getPdbentryItem())
+              for (PdbentryItem item : pdbid.getPdbentryItem())
               {
                 for (Property pr : item.getProperty())
                 {
@@ -3117,6 +3554,11 @@ public class Jalview2XML
                 }
               }
             }
+            */
+            for (Property prop : pdbid.getProperty())
+            {
+              entry.setProperty(prop.getName(), prop.getValue());
+            }
             StructureSelectionManager
                     .getStructureSelectionManager(Desktop.instance)
                     .registerPDBEntry(entry);
@@ -3137,26 +3579,27 @@ public class Jalview2XML
     // ///////////////////////////////
     // LOAD SEQUENCE MAPPINGS
 
-    if (vamsasSet.getAlcodonFrameCount() > 0)
+    if (vamsasSet.getAlcodonFrame().size() > 0)
     {
       // TODO Potentially this should only be done once for all views of an
       // alignment
-      AlcodonFrame[] alc = vamsasSet.getAlcodonFrame();
-      for (int i = 0; i < alc.length; i++)
+      List<AlcodonFrame> alc = vamsasSet.getAlcodonFrame();
+      for (int i = 0; i < alc.size(); i++)
       {
         AlignedCodonFrame cf = new AlignedCodonFrame();
-        if (alc[i].getAlcodMapCount() > 0)
+        if (alc.get(i).getAlcodMap().size() > 0)
         {
-          AlcodMap[] maps = alc[i].getAlcodMap();
-          for (int m = 0; m < maps.length; m++)
+          List<AlcodMap> maps = alc.get(i).getAlcodMap();
+          for (int m = 0; m < maps.size(); m++)
           {
-            SequenceI dnaseq = seqRefIds.get(maps[m].getDnasq());
+            AlcodMap map = maps.get(m);
+            SequenceI dnaseq = seqRefIds.get(map.getDnasq());
             // Load Mapping
             jalview.datamodel.Mapping mapping = null;
             // attach to dna sequence reference.
-            if (maps[m].getMapping() != null)
+            if (map.getMapping() != null)
             {
-              mapping = addMapping(maps[m].getMapping());
+              mapping = addMapping(map.getMapping());
               if (dnaseq != null && mapping.getTo() != null)
               {
                 cf.addMap(dnaseq, mapping.getTo(), mapping.getMap());
@@ -3165,7 +3608,7 @@ public class Jalview2XML
               {
                 // defer to later
                 frefedSequence.add(
-                        newAlcodMapRef(maps[m].getDnasq(), cf, mapping));
+                        newAlcodMapRef(map.getDnasq(), cf, mapping));
               }
             }
           }
@@ -3183,13 +3626,13 @@ public class Jalview2XML
      */
     Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<>();
 
-    if (vamsasSet.getAnnotationCount() > 0)
+    if (vamsasSet.getAnnotation().size()/*Count()*/ > 0)
     {
-      Annotation[] an = vamsasSet.getAnnotation();
+      List<Annotation> an = vamsasSet.getAnnotation();
 
-      for (int i = 0; i < an.length; i++)
+      for (int i = 0; i < an.size(); i++)
       {
-        Annotation annotation = an[i];
+        Annotation annotation = an.get(i);
 
         /**
          * test if annotation is automatically calculated for this view only
@@ -3201,29 +3644,29 @@ public class Jalview2XML
         {
           // Kludge for pre 2.5 projects which lacked the autocalculated flag
           autoForView = true;
-          if (!annotation.hasAutoCalculated())
-          {
-            annotation.setAutoCalculated(true);
-          }
+          // JAXB has no has() test; schema defaults value to false
+          // if (!annotation.hasAutoCalculated())
+          // {
+          // annotation.setAutoCalculated(true);
+          // }
         }
-        if (autoForView || (annotation.hasAutoCalculated()
-                && annotation.isAutoCalculated()))
+        if (autoForView || annotation.isAutoCalculated())
         {
           // remove ID - we don't recover annotation from other views for
           // view-specific annotation
           annotation.setId(null);
         }
 
-        // set visiblity for other annotation in this view
+        // set visibility for other annotation in this view
         String annotationId = annotation.getId();
         if (annotationId != null && annotationIds.containsKey(annotationId))
         {
           AlignmentAnnotation jda = annotationIds.get(annotationId);
           // in principle Visible should always be true for annotation displayed
           // in multiple views
-          if (annotation.hasVisible())
+          if (annotation.isVisible() != null)
           {
-            jda.visible = annotation.getVisible();
+            jda.visible = annotation.isVisible();
           }
 
           al.addAnnotation(jda);
@@ -3231,41 +3674,36 @@ public class Jalview2XML
           continue;
         }
         // Construct new annotation from model.
-        AnnotationElement[] ae = annotation.getAnnotationElement();
+        List<AnnotationElement> ae = annotation.getAnnotationElement();
         jalview.datamodel.Annotation[] anot = null;
         java.awt.Color firstColour = null;
         int anpos;
-        if (!annotation.getScoreOnly())
+        if (!annotation.isScoreOnly())
         {
           anot = new jalview.datamodel.Annotation[al.getWidth()];
-          for (int aa = 0; aa < ae.length && aa < anot.length; aa++)
+          for (int aa = 0; aa < ae.size() && aa < anot.length; aa++)
           {
-            anpos = ae[aa].getPosition();
+            AnnotationElement annElement = ae.get(aa);
+            anpos = annElement.getPosition();
 
             if (anpos >= anot.length)
             {
               continue;
             }
 
+            float value = safeFloat(annElement.getValue());
             anot[anpos] = new jalview.datamodel.Annotation(
-
-                    ae[aa].getDisplayCharacter(), ae[aa].getDescription(),
-                    (ae[aa].getSecondaryStructure() == null
-                            || ae[aa].getSecondaryStructure().length() == 0)
-                                    ? ' '
-                                    : ae[aa].getSecondaryStructure()
-                                            .charAt(0),
-                    ae[aa].getValue()
-
-            );
-            // JBPNote: Consider verifying dataflow for IO of secondary
-            // structure annotation read from Stockholm files
-            // this was added to try to ensure that
-            // if (anot[ae[aa].getPosition()].secondaryStructure>' ')
-            // {
-            // anot[ae[aa].getPosition()].displayCharacter = "";
-            // }
-            anot[anpos].colour = new java.awt.Color(ae[aa].getColour());
+                    annElement.getDisplayCharacter(),
+                    annElement.getDescription(),
+                    (annElement.getSecondaryStructure() == null
+                            || annElement.getSecondaryStructure()
+                                    .length() == 0)
+                                            ? ' '
+                                            : annElement
+                                                    .getSecondaryStructure()
+                                                    .charAt(0),
+                    value);
+            anot[anpos].colour = new Color(safeInt(annElement.getColour()));
             if (firstColour == null)
             {
               firstColour = anot[anpos].colour;
@@ -3274,7 +3712,7 @@ public class Jalview2XML
         }
         jalview.datamodel.AlignmentAnnotation jaa = null;
 
-        if (annotation.getGraph())
+        if (annotation.isGraph())
         {
           float llim = 0, hlim = 0;
           // if (autoForView || an[i].isAutoCalculated()) {
@@ -3282,18 +3720,17 @@ public class Jalview2XML
           // }
           jaa = new jalview.datamodel.AlignmentAnnotation(
                   annotation.getLabel(), annotation.getDescription(), anot,
-                  llim, hlim, annotation.getGraphType());
+                  llim, hlim, safeInt(annotation.getGraphType()));
 
-          jaa.graphGroup = annotation.getGraphGroup();
+          jaa.graphGroup = safeInt(annotation.getGraphGroup());
           jaa._linecolour = firstColour;
           if (annotation.getThresholdLine() != null)
           {
             jaa.setThreshold(new jalview.datamodel.GraphLine(
-                    annotation.getThresholdLine().getValue(),
+                    safeFloat(annotation.getThresholdLine().getValue()),
                     annotation.getThresholdLine().getLabel(),
-                    new java.awt.Color(
-                            annotation.getThresholdLine().getColour())));
-
+                    new java.awt.Color(safeInt(
+                            annotation.getThresholdLine().getColour()))));
           }
           if (autoForView || annotation.isAutoCalculated())
           {
@@ -3304,18 +3741,18 @@ public class Jalview2XML
         }
         else
         {
-          jaa = new jalview.datamodel.AlignmentAnnotation(an[i].getLabel(),
-                  an[i].getDescription(), anot);
+          jaa = new jalview.datamodel.AlignmentAnnotation(
+                  annotation.getLabel(), annotation.getDescription(), anot);
           jaa._linecolour = firstColour;
         }
         // register new annotation
-        if (an[i].getId() != null)
+        if (annotation.getId() != null)
         {
-          annotationIds.put(an[i].getId(), jaa);
-          jaa.annotationId = an[i].getId();
+          annotationIds.put(annotation.getId(), jaa);
+          jaa.annotationId = annotation.getId();
         }
         // recover sequence association
-        String sequenceRef = an[i].getSequenceRef();
+        String sequenceRef = annotation.getSequenceRef();
         if (sequenceRef != null)
         {
           // from 2.9 sequenceRef is to sequence id (JAL-1781)
@@ -3332,55 +3769,54 @@ public class Jalview2XML
           }
         }
         // and make a note of any group association
-        if (an[i].getGroupRef() != null && an[i].getGroupRef().length() > 0)
+        if (annotation.getGroupRef() != null
+                && annotation.getGroupRef().length() > 0)
         {
           List<jalview.datamodel.AlignmentAnnotation> aal = groupAnnotRefs
-                  .get(an[i].getGroupRef());
+                  .get(annotation.getGroupRef());
           if (aal == null)
           {
             aal = new ArrayList<>();
-            groupAnnotRefs.put(an[i].getGroupRef(), aal);
+            groupAnnotRefs.put(annotation.getGroupRef(), aal);
           }
           aal.add(jaa);
         }
 
-        if (an[i].hasScore())
+        if (annotation.getScore() != null)
         {
-          jaa.setScore(an[i].getScore());
+          jaa.setScore(annotation.getScore().doubleValue());
         }
-        if (an[i].hasVisible())
+        if (annotation.isVisible() != null)
         {
-          jaa.visible = an[i].getVisible();
+          jaa.visible = annotation.isVisible().booleanValue();
         }
 
-        if (an[i].hasCentreColLabels())
+        if (annotation.isCentreColLabels() != null)
         {
-          jaa.centreColLabels = an[i].getCentreColLabels();
+          jaa.centreColLabels = annotation.isCentreColLabels()
+                  .booleanValue();
         }
 
-        if (an[i].hasScaleColLabels())
+        if (annotation.isScaleColLabels() != null)
         {
-          jaa.scaleColLabel = an[i].getScaleColLabels();
+          jaa.scaleColLabel = annotation.isScaleColLabels().booleanValue();
         }
-        if (an[i].hasAutoCalculated() && an[i].isAutoCalculated())
+        if (annotation.isAutoCalculated())
         {
           // newer files have an 'autoCalculated' flag and store calculation
           // state in viewport properties
           jaa.autoCalculated = true; // means annotation will be marked for
           // update at end of load.
         }
-        if (an[i].hasGraphHeight())
-        {
-          jaa.graphHeight = an[i].getGraphHeight();
-        }
-        if (an[i].hasBelowAlignment())
+        if (annotation.getGraphHeight() != null)
         {
-          jaa.belowAlignment = an[i].isBelowAlignment();
+          jaa.graphHeight = annotation.getGraphHeight().intValue();
         }
-        jaa.setCalcId(an[i].getCalcId());
-        if (an[i].getPropertyCount() > 0)
+        jaa.belowAlignment = annotation.isBelowAlignment();
+        jaa.setCalcId(annotation.getCalcId());
+        if (annotation.getProperty().size() > 0)
         {
-          for (jalview.schemabinding.version2.Property prop : an[i]
+          for (Annotation.Property prop : annotation
                   .getProperty())
           {
             jaa.setProperty(prop.getName(), prop.getValue());
@@ -3402,19 +3838,19 @@ public class Jalview2XML
     // ///////////////////////
     // LOAD GROUPS
     // Create alignment markup and styles for this view
-    if (jms.getJGroupCount() > 0)
+    if (jalviewModel.getJGroup().size() > 0)
     {
-      JGroup[] groups = jms.getJGroup();
+      List<JGroup> groups = jalviewModel.getJGroup();
       boolean addAnnotSchemeGroup = false;
-      for (int i = 0; i < groups.length; i++)
+      for (int i = 0; i < groups.size(); i++)
       {
-        JGroup jGroup = groups[i];
+        JGroup jGroup = groups.get(i);
         ColourSchemeI cs = null;
         if (jGroup.getColour() != null)
         {
           if (jGroup.getColour().startsWith("ucs"))
           {
-            cs = getUserColourScheme(jms, jGroup.getColour());
+            cs = getUserColourScheme(jalviewModel, jGroup.getColour());
           }
           else if (jGroup.getColour().equals("AnnotationColourGradient")
                   && jGroup.getAnnotationColours() != null)
@@ -3427,13 +3863,13 @@ public class Jalview2XML
                     jGroup.getColour());
           }
         }
-        int pidThreshold = jGroup.getPidThreshold();
+        int pidThreshold = safeInt(jGroup.getPidThreshold());
 
         Vector<SequenceI> seqs = new Vector<>();
 
-        for (int s = 0; s < jGroup.getSeqCount(); s++)
+        for (int s = 0; s < jGroup.getSeq().size(); s++)
         {
-          String seqId = jGroup.getSeq(s) + "";
+          String seqId = jGroup.getSeq().get(s);
           SequenceI ts = seqRefIds.get(seqId);
 
           if (ts != null)
@@ -3448,37 +3884,26 @@ public class Jalview2XML
         }
 
         SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
-                jGroup.getDisplayBoxes(), jGroup.getDisplayText(),
-                jGroup.getColourText(), jGroup.getStart(), jGroup.getEnd());
+                safeBoolean(jGroup.isDisplayBoxes()),
+                safeBoolean(jGroup.isDisplayText()),
+                safeBoolean(jGroup.isColourText()),
+                safeInt(jGroup.getStart()), safeInt(jGroup.getEnd()));
         sg.getGroupColourScheme().setThreshold(pidThreshold, true);
         sg.getGroupColourScheme()
-                .setConservationInc(jGroup.getConsThreshold());
-        sg.setOutlineColour(new java.awt.Color(jGroup.getOutlineColour()));
-
-        sg.textColour = new java.awt.Color(jGroup.getTextCol1());
-        sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
-        sg.setShowNonconserved(
-                jGroup.hasShowUnconserved() ? jGroup.isShowUnconserved()
-                        : false);
-        sg.thresholdTextColour = jGroup.getTextColThreshold();
-        if (jGroup.hasShowConsensusHistogram())
-        {
+                .setConservationInc(safeInt(jGroup.getConsThreshold()));
+        sg.setOutlineColour(new Color(safeInt(jGroup.getOutlineColour())));
+
+        sg.textColour = new Color(safeInt(jGroup.getTextCol1()));
+        sg.textColour2 = new Color(safeInt(jGroup.getTextCol2()));
+        sg.setShowNonconserved(safeBoolean(jGroup.isShowUnconserved()));
+        sg.thresholdTextColour = safeInt(jGroup.getTextColThreshold());
+        // attributes with a default in the schema are never null
           sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
-        }
-        ;
-        if (jGroup.hasShowSequenceLogo())
-        {
           sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
-        }
-        if (jGroup.hasNormaliseSequenceLogo())
-        {
           sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
-        }
-        if (jGroup.hasIgnoreGapsinConsensus())
-        {
-          sg.setIgnoreGapsConsensus(jGroup.getIgnoreGapsinConsensus());
-        }
-        if (jGroup.getConsThreshold() != 0)
+        sg.setIgnoreGapsConsensus(jGroup.isIgnoreGapsinConsensus());
+        if (jGroup.getConsThreshold() != null
+                && jGroup.getConsThreshold().intValue() != 0)
         {
           Conservation c = new Conservation("All", sg.getSequences(null), 0,
                   sg.getWidth() - 1);
@@ -3520,7 +3945,7 @@ public class Jalview2XML
         {
           // reconstruct the annotation colourscheme
           sg.setColourScheme(constructAnnotationColour(
-                  jGroup.getAnnotationColours(), null, al, jms, false));
+                  jGroup.getAnnotationColours(), null, al, jalviewModel, false));
         }
       }
     }
@@ -3532,13 +3957,6 @@ public class Jalview2XML
     // ///////////////////////////////
     // LOAD VIEWPORT
 
-    // If we just load in the same jar file again, the sequenceSetId
-    // will be the same, and we end up with multiple references
-    // to the same sequenceSet. We must modify this id on load
-    // so that each load of the file gives a unique id
-    String uniqueSeqSetId = view.getSequenceSetId() + uniqueSetSuffix;
-    String viewId = (view.getId() == null ? null
-            : view.getId() + uniqueSetSuffix);
     AlignFrame af = null;
     AlignViewport av = null;
     // now check to see if we really need to create a new viewport.
@@ -3577,7 +3995,7 @@ public class Jalview2XML
      * Jalview 2.8.1 behaviour)
      */
     boolean doGroupAnnColour = Jalview2XML.isVersionStringLaterThan("2.8.1",
-            object.getVersion());
+            jalviewModel.getVersion());
 
     AlignmentPanel ap = null;
     boolean isnewview = true;
@@ -3606,9 +4024,9 @@ public class Jalview2XML
 
     if (isnewview)
     {
-      af = loadViewport(file, jseqs, hiddenSeqs, al, jms, view,
+      af = loadViewport(file, jseqs, hiddenSeqs, al, jalviewModel, view,
               uniqueSeqSetId, viewId, autoAlan);
-      av = af.viewport;
+      av = af.getViewport();
       ap = af.alignPanel;
     }
 
@@ -3619,7 +4037,8 @@ public class Jalview2XML
      */
     if (loadTreesAndStructures)
     {
-      loadTrees(jms, view, af, av, ap);
+      loadTrees(jalviewModel, view, af, av, ap);
+      loadPCAViewers(jalviewModel, ap);
       loadPDBStructures(jprovider, jseqs, af, ap);
       loadRnaViewers(jprovider, jseqs, ap);
     }
@@ -3641,7 +4060,7 @@ public class Jalview2XML
    * @param ap
    */
   private void loadRnaViewers(jarInputStreamProvider jprovider,
-          JSeq[] jseqs, AlignmentPanel ap)
+          List<JSeq> jseqs, AlignmentPanel ap)
   {
     /*
      * scan the sequences for references to viewers; create each one the first
@@ -3649,15 +4068,15 @@ public class Jalview2XML
      */
     for (JSeq jseq : jseqs)
     {
-      for (int i = 0; i < jseq.getRnaViewerCount(); i++)
+      for (int i = 0; i < jseq.getRnaViewer().size(); i++)
       {
-        RnaViewer viewer = jseq.getRnaViewer(i);
+        RnaViewer viewer = jseq.getRnaViewer().get(i);
         AppVarna appVarna = findOrCreateVarnaViewer(viewer, uniqueSetSuffix,
                 ap);
 
-        for (int j = 0; j < viewer.getSecondaryStructureCount(); j++)
+        for (int j = 0; j < viewer.getSecondaryStructure().size(); j++)
         {
-          SecondaryStructure ss = viewer.getSecondaryStructure(j);
+          SecondaryStructure ss = viewer.getSecondaryStructure().get(j);
           SequenceI seq = seqRefIds.get(jseq.getId());
           AlignmentAnnotation ann = this.annotationIds
                   .get(ss.getAnnotationId());
@@ -3666,7 +4085,7 @@ public class Jalview2XML
            * add the structure to the Varna display (with session state copied
            * from the jar to a temporary file)
            */
-          boolean gapped = ss.isGapped();
+          boolean gapped = safeBoolean(ss.isGapped());
           String rnaTitle = ss.getTitle();
           String sessionState = ss.getViewerState();
           String tempStateFile = copyJarEntry(jprovider, sessionState,
@@ -3674,7 +4093,7 @@ public class Jalview2XML
           RnaModel rna = new RnaModel(rnaTitle, ann, seq, null, gapped);
           appVarna.addModelSession(rna, rnaTitle, tempStateFile);
         }
-        appVarna.setInitialSelection(viewer.getSelectedRna());
+        appVarna.setInitialSelection(safeInt(viewer.getSelectedRna()));
       }
     }
   }
@@ -3715,8 +4134,9 @@ public class Jalview2XML
      * viewer not found - make it
      */
     RnaViewerModel model = new RnaViewerModel(postLoadId, viewer.getTitle(),
-            viewer.getXpos(), viewer.getYpos(), viewer.getWidth(),
-            viewer.getHeight(), viewer.getDividerLocation());
+            safeInt(viewer.getXpos()), safeInt(viewer.getYpos()),
+            safeInt(viewer.getWidth()), safeInt(viewer.getHeight()),
+            safeInt(viewer.getDividerLocation()));
     AppVarna varna = new AppVarna(model, ap);
 
     return varna;
@@ -3725,30 +4145,30 @@ public class Jalview2XML
   /**
    * Load any saved trees
    * 
-   * @param jms
+   * @param jm
    * @param view
    * @param af
    * @param av
    * @param ap
    */
-  protected void loadTrees(JalviewModelSequence jms, Viewport view,
+  protected void loadTrees(JalviewModel jm, Viewport view,
           AlignFrame af, AlignViewport av, AlignmentPanel ap)
   {
     // TODO result of automated refactoring - are all these parameters needed?
     try
     {
-      for (int t = 0; t < jms.getTreeCount(); t++)
+      for (int t = 0; t < jm.getTree().size(); t++)
       {
 
-        Tree tree = jms.getTree(t);
+        Tree tree = jm.getTree().get(t);
 
         TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
         if (tp == null)
         {
-          tp = af.showNewickTree(
-                  new jalview.io.NewickFile(tree.getNewick()),
-                  tree.getTitle(), tree.getWidth(), tree.getHeight(),
-                  tree.getXpos(), tree.getYpos());
+          tp = af.showNewickTree(new NewickFile(tree.getNewick()),
+                  tree.getTitle(), safeInt(tree.getWidth()),
+                  safeInt(tree.getHeight()), safeInt(tree.getXpos()),
+                  safeInt(tree.getYpos()));
           if (tree.getId() != null)
           {
             // perhaps bind the tree id to something ?
@@ -3760,13 +4180,15 @@ public class Jalview2XML
           // TODO: should check if tp has been manipulated by user - if so its
           // settings shouldn't be modified
           tp.setTitle(tree.getTitle());
-          tp.setBounds(new Rectangle(tree.getXpos(), tree.getYpos(),
-                  tree.getWidth(), tree.getHeight()));
-          tp.av = av; // af.viewport; // TODO: verify 'associate with all
-          // views'
-          // works still
-          tp.treeCanvas.av = av; // af.viewport;
-          tp.treeCanvas.ap = ap; // af.alignPanel;
+          tp.setBounds(new Rectangle(safeInt(tree.getXpos()),
+                  safeInt(tree.getYpos()), safeInt(tree.getWidth()),
+                  safeInt(tree.getHeight())));
+          tp.setViewport(av); // af.viewport;
+          // TODO: verify 'associate with all views' works still
+          tp.getTreeCanvas().setViewport(av); // af.viewport;
+          tp.getTreeCanvas().setAssociatedPanel(ap); // af.alignPanel;
+          // FIXME: should we use safeBoolean here ?
+          tp.getTreeCanvas().setApplyToAllViews(tree.isLinkToAllViews());
 
         }
         if (tp == null)
@@ -3776,29 +4198,31 @@ public class Jalview2XML
           continue;
         }
 
-        tp.fitToWindow.setState(tree.getFitToWindow());
+        tp.fitToWindow.setState(safeBoolean(tree.isFitToWindow()));
         tp.fitToWindow_actionPerformed(null);
 
         if (tree.getFontName() != null)
         {
-          tp.setTreeFont(new java.awt.Font(tree.getFontName(),
-                  tree.getFontStyle(), tree.getFontSize()));
+          tp.setTreeFont(
+                  new Font(tree.getFontName(), safeInt(tree.getFontStyle()),
+                          safeInt(tree.getFontSize())));
         }
         else
         {
-          tp.setTreeFont(new java.awt.Font(view.getFontName(),
-                  view.getFontStyle(), tree.getFontSize()));
+          tp.setTreeFont(
+                  new Font(view.getFontName(), safeInt(view.getFontStyle()),
+                          safeInt(view.getFontSize())));
         }
 
-        tp.showPlaceholders(tree.getMarkUnlinked());
-        tp.showBootstrap(tree.getShowBootstrap());
-        tp.showDistances(tree.getShowDistances());
+        tp.showPlaceholders(safeBoolean(tree.isMarkUnlinked()));
+        tp.showBootstrap(safeBoolean(tree.isShowBootstrap()));
+        tp.showDistances(safeBoolean(tree.isShowDistances()));
 
-        tp.treeCanvas.threshold = tree.getThreshold();
+        tp.getTreeCanvas().setThreshold(safeFloat(tree.getThreshold()));
 
-        if (tree.getCurrentTree())
+        if (safeBoolean(tree.isCurrentTree()))
         {
-          af.viewport.setCurrentTree(tp.getTree());
+          af.getViewport().setCurrentTree(tp.getTree());
         }
       }
 
@@ -3817,7 +4241,7 @@ public class Jalview2XML
    * @param ap
    */
   protected void loadPDBStructures(jarInputStreamProvider jprovider,
-          JSeq[] jseqs, AlignFrame af, AlignmentPanel ap)
+          List<JSeq> jseqs, AlignFrame af, AlignmentPanel ap)
   {
     /*
      * Run through all PDB ids on the alignment, and collect mappings between
@@ -3825,41 +4249,43 @@ public class Jalview2XML
      */
     Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
 
-    for (int i = 0; i < jseqs.length; i++)
+    for (int i = 0; i < jseqs.size(); i++)
     {
-      if (jseqs[i].getPdbidsCount() > 0)
+      JSeq jseq = jseqs.get(i);
+      if (jseq.getPdbids().size() > 0)
       {
-        Pdbids[] ids = jseqs[i].getPdbids();
-        for (int p = 0; p < ids.length; p++)
+        List<Pdbids> ids = jseq.getPdbids();
+        for (int p = 0; p < ids.size(); p++)
         {
-          final int structureStateCount = ids[p].getStructureStateCount();
+          Pdbids pdbid = ids.get(p);
+          final int structureStateCount = pdbid.getStructureState().size();
           for (int s = 0; s < structureStateCount; s++)
           {
             // check to see if we haven't already created this structure view
-            final StructureState structureState = ids[p]
-                    .getStructureState(s);
+            final StructureState structureState = pdbid
+                    .getStructureState().get(s);
             String sviewid = (structureState.getViewId() == null) ? null
                     : structureState.getViewId() + uniqueSetSuffix;
             jalview.datamodel.PDBEntry jpdb = new jalview.datamodel.PDBEntry();
-            // Originally : ids[p].getFile()
+            // Originally : pdbid.getFile()
             // : TODO: verify external PDB file recovery still works in normal
             // jalview project load
-            jpdb.setFile(loadPDBFile(jprovider, ids[p].getId(),
-                    ids[p].getFile()));
-            jpdb.setId(ids[p].getId());
+            jpdb.setFile(
+                    loadPDBFile(jprovider, pdbid.getId(), pdbid.getFile()));
+            jpdb.setId(pdbid.getId());
 
-            int x = structureState.getXpos();
-            int y = structureState.getYpos();
-            int width = structureState.getWidth();
-            int height = structureState.getHeight();
+            int x = safeInt(structureState.getXpos());
+            int y = safeInt(structureState.getYpos());
+            int width = safeInt(structureState.getWidth());
+            int height = safeInt(structureState.getHeight());
 
             // Probably don't need to do this anymore...
             // Desktop.desktop.getComponentAt(x, y);
             // TODO: NOW: check that this recovers the PDB file correctly.
-            String pdbFile = loadPDBFile(jprovider, ids[p].getId(),
-                    ids[p].getFile());
+            String pdbFile = loadPDBFile(jprovider, pdbid.getId(),
+                    pdbid.getFile());
             jalview.datamodel.SequenceI seq = seqRefIds
-                    .get(jseqs[i].getId() + "");
+                    .get(jseq.getId() + "");
             if (sviewid == null)
             {
               sviewid = "_jalview_pre2_4_" + x + "," + y + "," + width + ","
@@ -3882,19 +4308,14 @@ public class Jalview2XML
             // linkAlignPanel,superposeWithAlignpanel}} from hash
             StructureViewerModel jmoldat = structureViewers.get(sviewid);
             jmoldat.setAlignWithPanel(jmoldat.isAlignWithPanel()
-                    | (structureState.hasAlignwithAlignPanel()
-                            ? structureState.getAlignwithAlignPanel()
-                            : false));
+                    || structureState.isAlignwithAlignPanel());
 
             /*
              * Default colour by linked panel to false if not specified (e.g.
              * for pre-2.7 projects)
              */
             boolean colourWithAlignPanel = jmoldat.isColourWithAlignPanel();
-            colourWithAlignPanel |= (structureState
-                    .hasColourwithAlignPanel()
-                            ? structureState.getColourwithAlignPanel()
-                            : false);
+            colourWithAlignPanel |= structureState.isColourwithAlignPanel();
             jmoldat.setColourWithAlignPanel(colourWithAlignPanel);
 
             /*
@@ -3902,27 +4323,23 @@ public class Jalview2XML
              * pre-2.7 projects)
              */
             boolean colourByViewer = jmoldat.isColourByViewer();
-            colourByViewer &= structureState.hasColourByJmol()
-                    ? structureState.getColourByJmol()
-                    : true;
+            colourByViewer &= structureState.isColourByJmol();
             jmoldat.setColourByViewer(colourByViewer);
 
             if (jmoldat.getStateData().length() < structureState
-                    .getContent().length())
+                    .getValue()/*Content()*/.length())
             {
-              {
-                jmoldat.setStateData(structureState.getContent());
-              }
+              jmoldat.setStateData(structureState.getValue());// Content());
             }
-            if (ids[p].getFile() != null)
+            if (pdbid.getFile() != null)
             {
-              File mapkey = new File(ids[p].getFile());
+              File mapkey = new File(pdbid.getFile());
               StructureData seqstrmaps = jmoldat.getFileData().get(mapkey);
               if (seqstrmaps == null)
               {
                 jmoldat.getFileData().put(mapkey,
                         seqstrmaps = jmoldat.new StructureData(pdbFile,
-                                ids[p].getId()));
+                                pdbid.getId()));
               }
               if (!seqstrmaps.getSeqList().contains(seq))
               {
@@ -4417,46 +4834,47 @@ public class Jalview2XML
     }
   }
 
-  AlignFrame loadViewport(String file, JSeq[] JSEQ,
+  AlignFrame loadViewport(String file, List<JSeq> JSEQ,
           List<SequenceI> hiddenSeqs, AlignmentI al,
-          JalviewModelSequence jms, Viewport view, String uniqueSeqSetId,
+          JalviewModel jm, Viewport view, String uniqueSeqSetId,
           String viewId, List<JvAnnotRow> autoAlan)
   {
     AlignFrame af = null;
-    af = new AlignFrame(al, view.getWidth(), view.getHeight(),
-            uniqueSeqSetId, viewId);
+    af = new AlignFrame(al, safeInt(view.getWidth()),
+            safeInt(view.getHeight()), uniqueSeqSetId, viewId);
 
     af.setFileName(file, FileFormat.Jalview);
 
-    for (int i = 0; i < JSEQ.length; i++)
+    final AlignViewport viewport = af.getViewport();
+    for (int i = 0; i < JSEQ.size(); i++)
     {
-      af.viewport.setSequenceColour(
-              af.viewport.getAlignment().getSequenceAt(i),
-              new java.awt.Color(JSEQ[i].getColour()));
+      int colour = safeInt(JSEQ.get(i).getColour());
+      viewport.setSequenceColour(viewport.getAlignment().getSequenceAt(i),
+              new Color(colour));
     }
 
     if (al.hasSeqrep())
     {
-      af.getViewport().setColourByReferenceSeq(true);
-      af.getViewport().setDisplayReferenceSeq(true);
+      viewport.setColourByReferenceSeq(true);
+      viewport.setDisplayReferenceSeq(true);
     }
 
-    af.viewport.setGatherViewsHere(view.getGatheredViews());
+    viewport.setGatherViewsHere(safeBoolean(view.isGatheredViews()));
 
     if (view.getSequenceSetId() != null)
     {
       AlignmentViewport av = viewportsAdded.get(uniqueSeqSetId);
 
-      af.viewport.setSequenceSetId(uniqueSeqSetId);
+      viewport.setSequenceSetId(uniqueSeqSetId);
       if (av != null)
       {
         // propagate shared settings to this new view
-        af.viewport.setHistoryList(av.getHistoryList());
-        af.viewport.setRedoList(av.getRedoList());
+        viewport.setHistoryList(av.getHistoryList());
+        viewport.setRedoList(av.getRedoList());
       }
       else
       {
-        viewportsAdded.put(uniqueSeqSetId, af.viewport);
+        viewportsAdded.put(uniqueSeqSetId, viewport);
       }
       // TODO: check if this method can be called repeatedly without
       // side-effects if alignpanel already registered.
@@ -4465,15 +4883,15 @@ public class Jalview2XML
     // apply Hidden regions to view.
     if (hiddenSeqs != null)
     {
-      for (int s = 0; s < JSEQ.length; s++)
+      for (int s = 0; s < JSEQ.size(); s++)
       {
         SequenceGroup hidden = new SequenceGroup();
         boolean isRepresentative = false;
-        for (int r = 0; r < JSEQ[s].getHiddenSequencesCount(); r++)
+        for (int r = 0; r < JSEQ.get(s).getHiddenSequences().size(); r++)
         {
           isRepresentative = true;
           SequenceI sequenceToHide = al
-                  .getSequenceAt(JSEQ[s].getHiddenSequences(r));
+                  .getSequenceAt(JSEQ.get(s).getHiddenSequences().get(r));
           hidden.addSequence(sequenceToHide, false);
           // remove from hiddenSeqs list so we don't try to hide it twice
           hiddenSeqs.remove(sequenceToHide);
@@ -4482,56 +4900,59 @@ public class Jalview2XML
         {
           SequenceI representativeSequence = al.getSequenceAt(s);
           hidden.addSequence(representativeSequence, false);
-          af.viewport.hideRepSequences(representativeSequence, hidden);
+          viewport.hideRepSequences(representativeSequence, hidden);
         }
       }
 
       SequenceI[] hseqs = hiddenSeqs
               .toArray(new SequenceI[hiddenSeqs.size()]);
-      af.viewport.hideSequence(hseqs);
+      viewport.hideSequence(hseqs);
 
     }
     // recover view properties and display parameters
 
-    af.viewport.setShowAnnotation(view.getShowAnnotation());
-    af.viewport.setAbovePIDThreshold(view.getPidSelected());
-    af.viewport.setThreshold(view.getPidThreshold());
-
-    af.viewport.setColourText(view.getShowColourText());
-
-    af.viewport.setConservationSelected(view.getConservationSelected());
-    af.viewport.setIncrement(view.getConsThreshold());
-    af.viewport.setShowJVSuffix(view.getShowFullId());
-    af.viewport.setRightAlignIds(view.getRightAlignIds());
-    af.viewport.setFont(new java.awt.Font(view.getFontName(),
-            view.getFontStyle(), view.getFontSize()), true);
-    ViewStyleI vs = af.viewport.getViewStyle();
+    viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
+    viewport.setAbovePIDThreshold(safeBoolean(view.isPidSelected()));
+    final int pidThreshold = safeInt(view.getPidThreshold());
+    viewport.setThreshold(pidThreshold);
+
+    viewport.setColourText(safeBoolean(view.isShowColourText()));
+
+    viewport
+            .setConservationSelected(
+                    safeBoolean(view.isConservationSelected()));
+    viewport.setIncrement(safeInt(view.getConsThreshold()));
+    viewport.setShowJVSuffix(safeBoolean(view.isShowFullId()));
+    viewport.setRightAlignIds(safeBoolean(view.isRightAlignIds()));
+    viewport.setFont(new Font(view.getFontName(),
+            safeInt(view.getFontStyle()), safeInt(view.getFontSize())),
+            true);
+    ViewStyleI vs = viewport.getViewStyle();
     vs.setScaleProteinAsCdna(view.isScaleProteinAsCdna());
-    af.viewport.setViewStyle(vs);
+    viewport.setViewStyle(vs);
     // TODO: allow custom charWidth/Heights to be restored by updating them
     // after setting font - which means set above to false
-    af.viewport.setRenderGaps(view.getRenderGaps());
-    af.viewport.setWrapAlignment(view.getWrapAlignment());
-    af.viewport.setShowAnnotation(view.getShowAnnotation());
+    viewport.setRenderGaps(safeBoolean(view.isRenderGaps()));
+    viewport.setWrapAlignment(safeBoolean(view.isWrapAlignment()));
+    viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
 
-    af.viewport.setShowBoxes(view.getShowBoxes());
+    viewport.setShowBoxes(safeBoolean(view.isShowBoxes()));
 
-    af.viewport.setShowText(view.getShowText());
+    viewport.setShowText(safeBoolean(view.isShowText()));
 
-    af.viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
-    af.viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
-    af.viewport.setThresholdTextColour(view.getTextColThreshold());
-    af.viewport.setShowUnconserved(
-            view.hasShowUnconserved() ? view.isShowUnconserved() : false);
-    af.viewport.getRanges().setStartRes(view.getStartRes());
+    viewport.setTextColour(new Color(safeInt(view.getTextCol1())));
+    viewport.setTextColour2(new Color(safeInt(view.getTextCol2())));
+    viewport.setThresholdTextColour(safeInt(view.getTextColThreshold()));
+    viewport.setShowUnconserved(view.isShowUnconserved());
+    viewport.getRanges().setStartRes(safeInt(view.getStartRes()));
 
     if (view.getViewName() != null)
     {
-      af.viewport.viewName = view.getViewName();
+      viewport.setViewName(view.getViewName());
       af.setInitialTabVisible();
     }
-    af.setBounds(view.getXpos(), view.getYpos(), view.getWidth(),
-            view.getHeight());
+    af.setBounds(safeInt(view.getXpos()), safeInt(view.getYpos()),
+            safeInt(view.getWidth()), safeInt(view.getHeight()));
     // startSeq set in af.alignPanel.updateLayout below
     af.alignPanel.updateLayout();
     ColourSchemeI cs = null;
@@ -4540,12 +4961,12 @@ public class Jalview2XML
     {
       if (view.getBgColour().startsWith("ucs"))
       {
-        cs = getUserColourScheme(jms, view.getBgColour());
+        cs = getUserColourScheme(jm, view.getBgColour());
       }
       else if (view.getBgColour().startsWith("Annotation"))
       {
-        AnnotationColours viewAnnColour = view.getAnnotationColours();
-        cs = constructAnnotationColour(viewAnnColour, af, al, jms, true);
+        AnnotationColourScheme viewAnnColour = view.getAnnotationColours();
+        cs = constructAnnotationColour(viewAnnColour, af, al, jm, true);
 
         // annpos
 
@@ -4556,114 +4977,66 @@ public class Jalview2XML
       }
     }
 
-    af.viewport.setGlobalColourScheme(cs);
-    af.viewport.getResidueShading().setThreshold(view.getPidThreshold(),
-            view.getIgnoreGapsinConsensus());
-    af.viewport.getResidueShading()
-            .setConsensus(af.viewport.getSequenceConsensusHash());
-    af.viewport.setColourAppliesToAllGroups(false);
+    viewport.setGlobalColourScheme(cs);
+    viewport.getResidueShading().setThreshold(pidThreshold,
+            view.isIgnoreGapsinConsensus());
+    viewport.getResidueShading()
+            .setConsensus(viewport.getSequenceConsensusHash());
+    viewport.setColourAppliesToAllGroups(false);
 
-    if (view.getConservationSelected() && cs != null)
+    if (safeBoolean(view.isConservationSelected()) && cs != null)
     {
-      af.viewport.getResidueShading()
-              .setConservationInc(view.getConsThreshold());
+      viewport.getResidueShading()
+              .setConservationInc(safeInt(view.getConsThreshold()));
     }
 
     af.changeColour(cs);
 
-    af.viewport.setColourAppliesToAllGroups(true);
+    viewport.setColourAppliesToAllGroups(true);
 
-    af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures());
+    viewport
+            .setShowSequenceFeatures(
+                    safeBoolean(view.isShowSequenceFeatures()));
 
-    if (view.hasCentreColumnLabels())
-    {
-      af.viewport.setCentreColumnLabels(view.getCentreColumnLabels());
-    }
-    if (view.hasIgnoreGapsinConsensus())
-    {
-      af.viewport.setIgnoreGapsConsensus(view.getIgnoreGapsinConsensus(),
-              null);
-    }
-    if (view.hasFollowHighlight())
-    {
-      af.viewport.setFollowHighlight(view.getFollowHighlight());
-    }
-    if (view.hasFollowSelection())
-    {
-      af.viewport.followSelection = view.getFollowSelection();
-    }
-    if (view.hasShowConsensusHistogram())
-    {
-      af.viewport
-              .setShowConsensusHistogram(view.getShowConsensusHistogram());
-    }
-    else
-    {
-      af.viewport.setShowConsensusHistogram(true);
-    }
-    if (view.hasShowSequenceLogo())
-    {
-      af.viewport.setShowSequenceLogo(view.getShowSequenceLogo());
-    }
-    else
-    {
-      af.viewport.setShowSequenceLogo(false);
-    }
-    if (view.hasNormaliseSequenceLogo())
-    {
-      af.viewport.setNormaliseSequenceLogo(view.getNormaliseSequenceLogo());
-    }
-    if (view.hasShowDbRefTooltip())
-    {
-      af.viewport.setShowDBRefs(view.getShowDbRefTooltip());
-    }
-    if (view.hasShowNPfeatureTooltip())
-    {
-      af.viewport.setShowNPFeats(view.hasShowNPfeatureTooltip());
-    }
-    if (view.hasShowGroupConsensus())
-    {
-      af.viewport.setShowGroupConsensus(view.getShowGroupConsensus());
-    }
-    else
-    {
-      af.viewport.setShowGroupConsensus(false);
-    }
-    if (view.hasShowGroupConservation())
-    {
-      af.viewport.setShowGroupConservation(view.getShowGroupConservation());
-    }
-    else
-    {
-      af.viewport.setShowGroupConservation(false);
-    }
+    viewport.setCentreColumnLabels(view.isCentreColumnLabels());
+    viewport.setIgnoreGapsConsensus(view.isIgnoreGapsinConsensus(), null);
+    viewport.setFollowHighlight(view.isFollowHighlight());
+    viewport.followSelection = view.isFollowSelection();
+    viewport.setShowConsensusHistogram(view.isShowConsensusHistogram());
+    viewport.setShowSequenceLogo(view.isShowSequenceLogo());
+    viewport.setNormaliseSequenceLogo(view.isNormaliseSequenceLogo());
+    viewport.setShowDBRefs(safeBoolean(view.isShowDbRefTooltip()));
+    viewport.setShowNPFeats(safeBoolean(view.isShowNPfeatureTooltip()));
+    viewport.setShowGroupConsensus(view.isShowGroupConsensus());
+    viewport.setShowGroupConservation(view.isShowGroupConservation());
 
     // recover feature settings
-    if (jms.getFeatureSettings() != null)
+    if (jm.getFeatureSettings() != null)
     {
       FeatureRenderer fr = af.alignPanel.getSeqPanel().seqCanvas
               .getFeatureRenderer();
       FeaturesDisplayed fdi;
-      af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
-      String[] renderOrder = new String[jms.getFeatureSettings()
-              .getSettingCount()];
+      viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
+      String[] renderOrder = new String[jm.getFeatureSettings()
+              .getSetting().size()];
       Map<String, FeatureColourI> featureColours = new Hashtable<>();
       Map<String, Float> featureOrder = new Hashtable<>();
 
-      for (int fs = 0; fs < jms.getFeatureSettings()
-              .getSettingCount(); fs++)
+      for (int fs = 0; fs < jm.getFeatureSettings()
+              .getSetting().size(); fs++)
       {
-        Setting setting = jms.getFeatureSettings().getSetting(fs);
+        Setting setting = jm.getFeatureSettings().getSetting().get(fs);
         String featureType = setting.getType();
 
         /*
          * restore feature filters (if any)
          */
-        MatcherSet filters = setting.getMatcherSet();
+        jalview.xml.binding.jalview.FeatureMatcherSet filters = setting
+                .getMatcherSet();
         if (filters != null)
         {
           FeatureMatcherSetI filter = Jalview2XML
-                  .unmarshalFilter(featureType, filters);
+                  .parseFilter(featureType, filters);
           if (!filter.isEmpty())
           {
             fr.setFeatureFilter(featureType, filter);
@@ -4674,13 +5047,13 @@ public class Jalview2XML
          * restore feature colour scheme
          */
         Color maxColour = new Color(setting.getColour());
-        if (setting.hasMincolour())
+        if (setting.getMincolour() != null)
         {
           /*
            * minColour is always set unless a simple colour
            * (including for colour by label though it doesn't use it)
            */
-          Color minColour = new Color(setting.getMincolour());
+          Color minColour = new Color(setting.getMincolour().intValue());
           Color noValueColour = minColour;
           NoValueColour noColour = setting.getNoValueColour();
           if (noColour == NoValueColour.NONE)
@@ -4691,18 +5064,21 @@ public class Jalview2XML
           {
             noValueColour = maxColour;
           }
-          float min = setting.hasMin() ? setting.getMin() : 0f;
-          float max = setting.hasMin() ? setting.getMax() : 1f;
+          float min = safeFloat(safeFloat(setting.getMin()));
+          float max = setting.getMax() == null ? 1f
+                  : setting.getMax().floatValue();
           FeatureColourI gc = new FeatureColour(maxColour, minColour,
-                  maxColour, noValueColour, min, max);
-          if (setting.getAttributeNameCount() > 0)
+                  maxColour,
+                  noValueColour, min, max);
+          if (setting.getAttributeName().size() > 0)
           {
-            gc.setAttributeName(setting.getAttributeName());
+            gc.setAttributeName(setting.getAttributeName().toArray(
+                    new String[setting.getAttributeName().size()]));
           }
-          if (setting.hasThreshold())
+          if (setting.getThreshold() != null)
           {
-            gc.setThreshold(setting.getThreshold());
-            int threshstate = setting.getThreshstate();
+            gc.setThreshold(setting.getThreshold().floatValue());
+            int threshstate = safeInt(setting.getThreshstate());
             // -1 = None, 0 = Below, 1 = Above threshold
             if (threshstate == 0)
             {
@@ -4714,13 +5090,13 @@ public class Jalview2XML
             }
           }
           gc.setAutoScaled(true); // default
-          if (setting.hasAutoScale())
+          if (setting.isAutoScale() != null)
           {
-            gc.setAutoScaled(setting.getAutoScale());
+            gc.setAutoScaled(setting.isAutoScale());
           }
-          if (setting.hasColourByLabel())
+          if (setting.isColourByLabel() != null)
           {
-            gc.setColourByLabel(setting.getColourByLabel());
+            gc.setColourByLabel(setting.isColourByLabel());
           }
           // and put in the feature colour table.
           featureColours.put(featureType, gc);
@@ -4731,25 +5107,25 @@ public class Jalview2XML
                   new FeatureColour(maxColour));
         }
         renderOrder[fs] = featureType;
-        if (setting.hasOrder())
+        if (setting.getOrder() != null)
         {
-          featureOrder.put(featureType, setting.getOrder());
+          featureOrder.put(featureType, setting.getOrder().floatValue());
         }
         else
         {
           featureOrder.put(featureType, new Float(
-                  fs / jms.getFeatureSettings().getSettingCount()));
+                  fs / jm.getFeatureSettings().getSetting().size()));
         }
-        if (setting.getDisplay())
+        if (safeBoolean(setting.isDisplay()))
         {
           fdi.setVisible(featureType);
         }
       }
       Map<String, Boolean> fgtable = new Hashtable<>();
-      for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
+      for (int gs = 0; gs < jm.getFeatureSettings().getGroup().size(); gs++)
       {
-        Group grp = jms.getFeatureSettings().getGroup(gs);
-        fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
+        Group grp = jm.getFeatureSettings().getGroup().get(gs);
+        fgtable.put(grp.getName(), new Boolean(grp.isDisplay()));
       }
       // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
       // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
@@ -4759,13 +5135,13 @@ public class Jalview2XML
       fr.transferSettings(frs);
     }
 
-    if (view.getHiddenColumnsCount() > 0)
+    if (view.getHiddenColumns().size() > 0)
     {
-      for (int c = 0; c < view.getHiddenColumnsCount(); c++)
+      for (int c = 0; c < view.getHiddenColumns().size(); c++)
       {
-        af.viewport.hideColumns(view.getHiddenColumns(c).getStart(),
-                view.getHiddenColumns(c).getEnd() // +1
-        );
+        final HiddenColumns hc = view.getHiddenColumns().get(c);
+        viewport.hideColumns(safeInt(hc.getStart()),
+                safeInt(hc.getEnd()) /* +1 */);
       }
     }
     if (view.getCalcIdParam() != null)
@@ -4774,7 +5150,7 @@ public class Jalview2XML
       {
         if (calcIdParam != null)
         {
-          if (recoverCalcIdParam(calcIdParam, af.viewport))
+          if (recoverCalcIdParam(calcIdParam, viewport))
           {
           }
           else
@@ -4785,7 +5161,7 @@ public class Jalview2XML
         }
       }
     }
-    af.setMenusFromViewport(af.viewport);
+    af.setMenusFromViewport(viewport);
     af.setTitle(view.getTitle());
     // TODO: we don't need to do this if the viewport is aready visible.
     /*
@@ -4796,8 +5172,8 @@ public class Jalview2XML
     String complementaryViewId = view.getComplementId();
     if (complementaryViewId == null)
     {
-      Desktop.addInternalFrame(af, view.getTitle(), view.getWidth(),
-              view.getHeight());
+      Desktop.addInternalFrame(af, view.getTitle(),
+              safeInt(view.getWidth()), safeInt(view.getHeight()));
       // recompute any autoannotation
       af.alignPanel.updateAnnotation(false, true);
       reorderAutoannotation(af, al, autoAlan);
@@ -4816,16 +5192,17 @@ public class Jalview2XML
    * @param viewAnnColour
    * @param af
    * @param al
-   * @param jms
+   * @param model
    * @param checkGroupAnnColour
    * @return
    */
   private ColourSchemeI constructAnnotationColour(
-          AnnotationColours viewAnnColour, AlignFrame af, AlignmentI al,
-          JalviewModelSequence jms, boolean checkGroupAnnColour)
+          AnnotationColourScheme viewAnnColour, AlignFrame af,
+          AlignmentI al, JalviewModel model, boolean checkGroupAnnColour)
   {
     boolean propagateAnnColour = false;
-    AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
+    AlignmentI annAlignment = af != null ? af.getViewport().getAlignment()
+            : al;
     if (checkGroupAnnColour && al.getGroups() != null
             && al.getGroups().size() > 0)
     {
@@ -4871,34 +5248,36 @@ public class Jalview2XML
     }
     if (matchedAnnotation.getThreshold() == null)
     {
-      matchedAnnotation.setThreshold(new GraphLine(
-              viewAnnColour.getThreshold(), "Threshold", Color.black));
+      matchedAnnotation.setThreshold(
+              new GraphLine(safeFloat(viewAnnColour.getThreshold()),
+                      "Threshold", Color.black));
     }
 
     AnnotationColourGradient cs = null;
     if (viewAnnColour.getColourScheme().equals("None"))
     {
       cs = new AnnotationColourGradient(matchedAnnotation,
-              new Color(viewAnnColour.getMinColour()),
-              new Color(viewAnnColour.getMaxColour()),
-              viewAnnColour.getAboveThreshold());
+              new Color(safeInt(viewAnnColour.getMinColour())),
+              new Color(safeInt(viewAnnColour.getMaxColour())),
+              safeInt(viewAnnColour.getAboveThreshold()));
     }
     else if (viewAnnColour.getColourScheme().startsWith("ucs"))
     {
       cs = new AnnotationColourGradient(matchedAnnotation,
-              getUserColourScheme(jms, viewAnnColour.getColourScheme()),
-              viewAnnColour.getAboveThreshold());
+              getUserColourScheme(model, viewAnnColour.getColourScheme()),
+              safeInt(viewAnnColour.getAboveThreshold()));
     }
     else
     {
       cs = new AnnotationColourGradient(matchedAnnotation,
               ColourSchemeProperty.getColourScheme(al,
                       viewAnnColour.getColourScheme()),
-              viewAnnColour.getAboveThreshold());
+              safeInt(viewAnnColour.getAboveThreshold()));
     }
 
-    boolean perSequenceOnly = viewAnnColour.isPerSequence();
-    boolean useOriginalColours = viewAnnColour.isPredefinedColours();
+    boolean perSequenceOnly = safeBoolean(viewAnnColour.isPerSequence());
+    boolean useOriginalColours = safeBoolean(
+            viewAnnColour.isPredefinedColours());
     cs.setSeqAssociated(perSequenceOnly);
     cs.setPredefinedColours(useOriginalColours);
 
@@ -4915,7 +5294,7 @@ public class Jalview2XML
 
         AnnotationColourGradient groupScheme = new AnnotationColourGradient(
                 matchedAnnotation, sg.getColourScheme(),
-                viewAnnColour.getAboveThreshold());
+                safeInt(viewAnnColour.getAboveThreshold()));
         sg.setColourScheme(groupScheme);
         groupScheme.setSeqAssociated(perSequenceOnly);
         groupScheme.setPredefinedColours(useOriginalColours);
@@ -5049,10 +5428,8 @@ public class Jalview2XML
     {
       return false;
     }
-    String id;
-    if (skipList.containsKey(
-            id = object.getJalviewModelSequence().getViewport()[0]
-                    .getSequenceSetId()))
+    String id = object.getViewport().get(0).getSequenceSetId();
+    if (skipList.containsKey(id))
     {
       if (Cache.log != null && Cache.log.isDebugEnabled())
       {
@@ -5082,19 +5459,57 @@ public class Jalview2XML
   }
 
   private void recoverDatasetFor(SequenceSet vamsasSet, AlignmentI al,
-          boolean ignoreUnrefed)
+          boolean ignoreUnrefed, String uniqueSeqSetId)
   {
     jalview.datamodel.AlignmentI ds = getDatasetFor(
             vamsasSet.getDatasetId());
+    AlignmentI xtant_ds = ds;
+    if (xtant_ds == null)
+    {
+      // good chance we are about to create a new dataset, but check if we've
+      // seen some of the dataset sequence IDs before.
+      // TODO: skip this check if we are working with project generated by
+      // version 2.11 or later
+      xtant_ds = checkIfHasDataset(vamsasSet.getSequence());
+      if (xtant_ds != null)
+      {
+        ds = xtant_ds;
+        addDatasetRef(vamsasSet.getDatasetId(), ds);
+      }
+    }
     Vector dseqs = null;
+    if (!ignoreUnrefed)
+    {
+      // recovering an alignment View
+      AlignmentI seqSetDS = getDatasetFor(UNIQSEQSETID + uniqueSeqSetId);
+      if (seqSetDS != null)
+      {
+        if (ds != null && ds != seqSetDS)
+        {
+          warn("JAL-3171 regression: Overwriting a dataset reference for an alignment"
+                  + " - CDS/Protein crossreference data may be lost");
+          if (xtant_ds != null)
+          {
+            // This can only happen if the unique sequence set ID was bound to a
+            // dataset that did not contain any of the sequences in the view
+            // currently being restored.
+            warn("JAL-3171 SERIOUS!  TOTAL CONFUSION - please consider contacting the Jalview Development team so they can investigate why your project caused this message to be displayed.");
+          }
+        }
+        ds = seqSetDS;
+        addDatasetRef(vamsasSet.getDatasetId(), ds);
+      }
+    }
     if (ds == null)
     {
+      // try even harder to restore dataset
+      AlignmentI xtantDS = checkIfHasDataset(vamsasSet.getSequence());
       // create a list of new dataset sequences
       dseqs = new Vector();
     }
-    for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
+    for (int i = 0, iSize = vamsasSet.getSequence().size(); i < iSize; i++)
     {
-      Sequence vamsasSeq = vamsasSet.getSequence(i);
+      Sequence vamsasSeq = vamsasSet.getSequence().get(i);
       ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed, i);
     }
     // create a new dataset
@@ -5111,10 +5526,58 @@ public class Jalview2XML
     if (al.getDataset() == null && !ignoreUnrefed)
     {
       al.setDataset(ds);
+      // register dataset for the alignment's uniqueSeqSetId for legacy projects
+      addDatasetRef(UNIQSEQSETID + uniqueSeqSetId, ds);
+    }
+    updateSeqDatasetBinding(vamsasSet.getSequence(), ds);
+  }
+
+  /**
+   * XML dataset sequence ID to materialised dataset reference
+   */
+  HashMap<String, AlignmentI> seqToDataset = new HashMap<>();
+
+  /**
+   * @return the first materialised dataset reference containing a dataset
+   *         sequence referenced in the given view
+   * @param list
+   *          - sequences from the view
+   */
+  AlignmentI checkIfHasDataset(List<Sequence> list)
+  {
+    for (Sequence restoredSeq : list)
+    {
+      AlignmentI datasetFor = seqToDataset.get(restoredSeq.getDsseqid());
+      if (datasetFor != null)
+      {
+        return datasetFor;
+      }
     }
+    return null;
   }
 
   /**
+   * Register ds as the containing dataset for the dataset sequences referenced
+   * by sequences in list
+   * 
+   * @param list
+   *          - sequences in a view
+   * @param ds
+   */
+  void updateSeqDatasetBinding(List<Sequence> list, AlignmentI ds)
+  {
+    for (Sequence restoredSeq : list)
+    {
+      AlignmentI prevDS = seqToDataset.put(restoredSeq.getDsseqid(), ds);
+      if (prevDS != null && prevDS != ds)
+      {
+        warn("Dataset sequence appears in many datasets: "
+                + restoredSeq.getDsseqid());
+        // TODO: try to merge!
+      }
+    }
+  }
+  /**
    * 
    * @param vamsasSeq
    *          sequence definition to create/merge dataset sequence for
@@ -5337,13 +5800,11 @@ public class Jalview2XML
 
   private void addDBRefs(SequenceI datasetSequence, Sequence sequence)
   {
-    for (int d = 0; d < sequence.getDBRefCount(); d++)
+    for (int d = 0; d < sequence.getDBRef().size(); d++)
     {
-      DBRef dr = sequence.getDBRef(d);
+      DBRef dr = sequence.getDBRef().get(d);
       jalview.datamodel.DBRefEntry entry = new jalview.datamodel.DBRefEntry(
-              sequence.getDBRef(d).getSource(),
-              sequence.getDBRef(d).getVersion(),
-              sequence.getDBRef(d).getAccessionId());
+              dr.getSource(), dr.getVersion(), dr.getAccessionId());
       if (dr.getMapping() != null)
       {
         entry.setMap(addMapping(dr.getMapping()));
@@ -5356,88 +5817,89 @@ public class Jalview2XML
   {
     SequenceI dsto = null;
     // Mapping m = dr.getMapping();
-    int fr[] = new int[m.getMapListFromCount() * 2];
-    Enumeration f = m.enumerateMapListFrom();
-    for (int _i = 0; f.hasMoreElements(); _i += 2)
+    int fr[] = new int[m.getMapListFrom().size() * 2];
+    Iterator<MapListFrom> from = m.getMapListFrom().iterator();// enumerateMapListFrom();
+    for (int _i = 0; from.hasNext(); _i += 2)
     {
-      MapListFrom mf = (MapListFrom) f.nextElement();
+      MapListFrom mf = from.next();
       fr[_i] = mf.getStart();
       fr[_i + 1] = mf.getEnd();
     }
-    int fto[] = new int[m.getMapListToCount() * 2];
-    f = m.enumerateMapListTo();
-    for (int _i = 0; f.hasMoreElements(); _i += 2)
+    int fto[] = new int[m.getMapListTo().size() * 2];
+    Iterator<MapListTo> to = m.getMapListTo().iterator();// enumerateMapListTo();
+    for (int _i = 0; to.hasNext(); _i += 2)
     {
-      MapListTo mf = (MapListTo) f.nextElement();
+      MapListTo mf = to.next();
       fto[_i] = mf.getStart();
       fto[_i + 1] = mf.getEnd();
     }
     jalview.datamodel.Mapping jmap = new jalview.datamodel.Mapping(dsto, fr,
-            fto, (int) m.getMapFromUnit(), (int) m.getMapToUnit());
-    if (m.getMappingChoice() != null)
+            fto, m.getMapFromUnit().intValue(),
+            m.getMapToUnit().intValue());
+
+    /*
+     * (optional) choice of dseqFor or Sequence
+     */
+    if (m.getDseqFor() != null)
     {
-      MappingChoice mc = m.getMappingChoice();
-      if (mc.getDseqFor() != null)
+      String dsfor = m.getDseqFor();
+      if (seqRefIds.containsKey(dsfor))
       {
-        String dsfor = "" + mc.getDseqFor();
-        if (seqRefIds.containsKey(dsfor))
-        {
-          /**
-           * recover from hash
-           */
-          jmap.setTo(seqRefIds.get(dsfor));
-        }
-        else
-        {
-          frefedSequence.add(newMappingRef(dsfor, jmap));
-        }
+        /*
+         * recover from hash
+         */
+        jmap.setTo(seqRefIds.get(dsfor));
       }
       else
       {
-        /**
-         * local sequence definition
+        frefedSequence.add(newMappingRef(dsfor, jmap));
+      }
+    }
+    else if (m.getSequence() != null)
+    {
+      /*
+       * local sequence definition
+       */
+      Sequence ms = m.getSequence();
+      SequenceI djs = null;
+      String sqid = ms.getDsseqid();
+      if (sqid != null && sqid.length() > 0)
+      {
+        /*
+         * recover dataset sequence
          */
-        Sequence ms = mc.getSequence();
-        SequenceI djs = null;
-        String sqid = ms.getDsseqid();
-        if (sqid != null && sqid.length() > 0)
-        {
-          /*
-           * recover dataset sequence
-           */
-          djs = seqRefIds.get(sqid);
-        }
-        else
-        {
-          System.err.println(
-                  "Warning - making up dataset sequence id for DbRef sequence map reference");
-          sqid = ((Object) ms).toString(); // make up a new hascode for
-          // undefined dataset sequence hash
-          // (unlikely to happen)
-        }
-
-        if (djs == null)
-        {
-          /**
-           * make a new dataset sequence and add it to refIds hash
-           */
-          djs = new jalview.datamodel.Sequence(ms.getName(),
-                  ms.getSequence());
-          djs.setStart(jmap.getMap().getToLowest());
-          djs.setEnd(jmap.getMap().getToHighest());
-          djs.setVamsasId(uniqueSetSuffix + sqid);
-          jmap.setTo(djs);
-          incompleteSeqs.put(sqid, djs);
-          seqRefIds.put(sqid, djs);
+        djs = seqRefIds.get(sqid);
+      }
+      else
+      {
+        System.err.println(
+                "Warning - making up dataset sequence id for DbRef sequence map reference");
+        sqid = ((Object) ms).toString(); // make up a new hascode for
+        // undefined dataset sequence hash
+        // (unlikely to happen)
+      }
 
-        }
-        jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
-        addDBRefs(djs, ms);
+      if (djs == null)
+      {
+        /**
+         * make a new dataset sequence and add it to refIds hash
+         */
+        djs = new jalview.datamodel.Sequence(ms.getName(),
+                ms.getSequence());
+        djs.setStart(jmap.getMap().getToLowest());
+        djs.setEnd(jmap.getMap().getToHighest());
+        djs.setVamsasId(uniqueSetSuffix + sqid);
+        jmap.setTo(djs);
+        incompleteSeqs.put(sqid, djs);
+        seqRefIds.put(sqid, djs);
 
       }
+      jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
+      addDBRefs(djs, ms);
+
     }
-    return (jmap);
 
+    return jmap;
   }
 
   /**
@@ -5452,8 +5914,13 @@ public class Jalview2XML
     initSeqRefs();
     JalviewModel jm = saveState(ap, null, null, null);
 
+    addDatasetRef(
+            jm.getVamsasModel().getSequenceSet().get(0).getDatasetId(),
+            ap.getAlignment().getDataset());
+
     uniqueSetSuffix = "";
-    jm.getJalviewModelSequence().getViewport(0).setId(null);
+    // jm.getJalviewModelSequence().getViewport(0).setId(null);
+    jm.getViewport().get(0).setId(null);
     // we don't overwrite the view we just copied
 
     if (this.frefedSequence == null)
@@ -5464,7 +5931,7 @@ public class Jalview2XML
     viewportsAdded.clear();
 
     AlignFrame af = loadFromObject(jm, null, false, null);
-    af.alignPanels.clear();
+    af.getAlignPanels().clear();
     af.closeMenuItem_actionPerformed(true);
 
     /*
@@ -5712,16 +6179,138 @@ public class Jalview2XML
   }
 
   /**
+   * Loads any saved PCA viewers
+   * 
+   * @param jms
+   * @param ap
+   */
+  protected void loadPCAViewers(JalviewModel model, AlignmentPanel ap)
+  {
+    try
+    {
+      List<PcaViewer> pcaviewers = model.getPcaViewer();
+      for (PcaViewer viewer : pcaviewers)
+      {
+        String modelName = viewer.getScoreModelName();
+        SimilarityParamsI params = new SimilarityParams(
+                viewer.isIncludeGappedColumns(), viewer.isMatchGaps(),
+                viewer.isIncludeGaps(),
+                viewer.isDenominateByShortestLength());
+
+        /*
+         * create the panel (without computing the PCA)
+         */
+        PCAPanel panel = new PCAPanel(ap, modelName, params);
+
+        panel.setTitle(viewer.getTitle());
+        panel.setBounds(new Rectangle(viewer.getXpos(), viewer.getYpos(),
+                viewer.getWidth(), viewer.getHeight()));
+
+        boolean showLabels = viewer.isShowLabels();
+        panel.setShowLabels(showLabels);
+        panel.getRotatableCanvas().setShowLabels(showLabels);
+        panel.getRotatableCanvas()
+                .setBgColour(new Color(viewer.getBgColour()));
+        panel.getRotatableCanvas()
+                .setApplyToAllViews(viewer.isLinkToAllViews());
+
+        /*
+         * load PCA output data
+         */
+        ScoreModelI scoreModel = ScoreModels.getInstance()
+                .getScoreModel(modelName, ap);
+        PCA pca = new PCA(null, scoreModel, params);
+        PcaDataType pcaData = viewer.getPcaData();
+
+        MatrixI pairwise = loadDoubleMatrix(pcaData.getPairwiseMatrix());
+        pca.setPairwiseScores(pairwise);
+
+        MatrixI triDiag = loadDoubleMatrix(pcaData.getTridiagonalMatrix());
+        pca.setTridiagonal(triDiag);
+
+        MatrixI result = loadDoubleMatrix(pcaData.getEigenMatrix());
+        pca.setEigenmatrix(result);
+
+        panel.getPcaModel().setPCA(pca);
+
+        /*
+         * we haven't saved the input data! (JAL-2647 to do)
+         */
+        panel.setInputData(null);
+
+        /*
+         * add the sequence points for the PCA display
+         */
+        List<jalview.datamodel.SequencePoint> seqPoints = new ArrayList<>();
+        for (SequencePoint sp : viewer.getSequencePoint())
+        {
+          String seqId = sp.getSequenceRef();
+          SequenceI seq = seqRefIds.get(seqId);
+          if (seq == null)
+          {
+            throw new IllegalStateException(
+                    "Unmatched seqref for PCA: " + seqId);
+          }
+          Point pt = new Point(sp.getXPos(), sp.getYPos(), sp.getZPos());
+          jalview.datamodel.SequencePoint seqPoint = new jalview.datamodel.SequencePoint(
+                  seq, pt);
+          seqPoints.add(seqPoint);
+        }
+        panel.getRotatableCanvas().setPoints(seqPoints, seqPoints.size());
+
+        /*
+         * set min-max ranges and scale after setPoints (which recomputes them)
+         */
+        panel.getRotatableCanvas().setScaleFactor(viewer.getScaleFactor());
+        SeqPointMin spMin = viewer.getSeqPointMin();
+        float[] min = new float[] { spMin.getXPos(), spMin.getYPos(),
+            spMin.getZPos() };
+        SeqPointMax spMax = viewer.getSeqPointMax();
+        float[] max = new float[] { spMax.getXPos(), spMax.getYPos(),
+            spMax.getZPos() };
+        panel.getRotatableCanvas().setSeqMinMax(min, max);
+
+        // todo: hold points list in PCAModel only
+        panel.getPcaModel().setSequencePoints(seqPoints);
+
+        panel.setSelectedDimensionIndex(viewer.getXDim(), X);
+        panel.setSelectedDimensionIndex(viewer.getYDim(), Y);
+        panel.setSelectedDimensionIndex(viewer.getZDim(), Z);
+
+        // is this duplication needed?
+        panel.setTop(seqPoints.size() - 1);
+        panel.getPcaModel().setTop(seqPoints.size() - 1);
+
+        /*
+         * add the axes' end points for the display
+         */
+        for (int i = 0; i < 3; i++)
+        {
+          Axis axis = viewer.getAxis().get(i);
+          panel.getRotatableCanvas().getAxisEndPoints()[i] = new Point(
+                  axis.getXPos(), axis.getYPos(), axis.getZPos());
+        }
+
+        Desktop.addInternalFrame(panel, MessageManager.formatMessage(
+                "label.calc_title", "PCA", modelName), 475, 450);
+      }
+    } catch (Exception ex)
+    {
+      Cache.log.error("Error loading PCA: " + ex.toString());
+    }
+  }
+
+  /**
    * Populates an XML model of the feature colour scheme for one feature type
    * 
    * @param featureType
    * @param fcol
    * @return
    */
-  protected static jalview.schemabinding.version2.Colour marshalColour(
+  public static Colour marshalColour(
           String featureType, FeatureColourI fcol)
   {
-    jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
+    Colour col = new Colour();
     if (fcol.isSimpleColour())
     {
       col.setRGB(Format.getHexString(fcol.getColour()));
@@ -5735,12 +6324,17 @@ public class Jalview2XML
       col.setAutoScale(fcol.isAutoScaled());
       col.setThreshold(fcol.getThreshold());
       col.setColourByLabel(fcol.isColourByLabel());
-      col.setThreshType(fcol.isAboveThreshold() ? ColourThreshTypeType.ABOVE
-              : (fcol.isBelowThreshold() ? ColourThreshTypeType.BELOW
-                      : ColourThreshTypeType.NONE));
+      col.setThreshType(fcol.isAboveThreshold() ? ThresholdType.ABOVE
+              : (fcol.isBelowThreshold() ? ThresholdType.BELOW
+                      : ThresholdType.NONE));
       if (fcol.isColourByAttribute())
       {
-        col.setAttributeName(fcol.getAttributeName());
+        final String[] attName = fcol.getAttributeName();
+        col.getAttributeName().add(attName[0]);
+        if (attName.length > 1)
+        {
+          col.getAttributeName().add(attName[1]);
+        }
       }
       Color noColour = fcol.getNoColour();
       if (noColour == null)
@@ -5770,10 +6364,11 @@ public class Jalview2XML
    * @param and
    *          if true, conditions are and-ed, else or-ed
    */
-  protected static MatcherSet marshalFilter(FeatureMatcherI firstMatcher,
-          Iterator<FeatureMatcherI> filters, boolean and)
+  public static jalview.xml.binding.jalview.FeatureMatcherSet marshalFilter(
+          FeatureMatcherI firstMatcher, Iterator<FeatureMatcherI> filters,
+          boolean and)
   {
-    MatcherSet result = new MatcherSet();
+    jalview.xml.binding.jalview.FeatureMatcherSet result = new jalview.xml.binding.jalview.FeatureMatcherSet();
   
     if (filters.hasNext())
     {
@@ -5782,12 +6377,15 @@ public class Jalview2XML
        */
       CompoundMatcher compound = new CompoundMatcher();
       compound.setAnd(and);
-      MatcherSet matcher1 = marshalFilter(firstMatcher,
-              Collections.emptyIterator(), and);
-      compound.addMatcherSet(matcher1);
+      jalview.xml.binding.jalview.FeatureMatcherSet matcher1 = marshalFilter(
+              firstMatcher, Collections.emptyIterator(), and);
+      // compound.addMatcherSet(matcher1);
+      compound.getMatcherSet().add(matcher1);
       FeatureMatcherI nextMatcher = filters.next();
-      MatcherSet matcher2 = marshalFilter(nextMatcher, filters, and);
-      compound.addMatcherSet(matcher2);
+      jalview.xml.binding.jalview.FeatureMatcherSet matcher2 = marshalFilter(
+              nextMatcher, filters, and);
+      // compound.addMatcherSet(matcher2);
+      compound.getMatcherSet().add(matcher2);
       result.setCompoundMatcher(compound);
     }
     else
@@ -5795,22 +6393,29 @@ public class Jalview2XML
       /*
        * single condition matcher
        */
-      MatchCondition matcherModel = new MatchCondition();
+      // MatchCondition matcherModel = new MatchCondition();
+      jalview.xml.binding.jalview.FeatureMatcher matcherModel = new jalview.xml.binding.jalview.FeatureMatcher();
       matcherModel.setCondition(
               firstMatcher.getMatcher().getCondition().getStableName());
       matcherModel.setValue(firstMatcher.getMatcher().getPattern());
       if (firstMatcher.isByAttribute())
       {
-        matcherModel.setBy(FeatureMatcherByType.BYATTRIBUTE);
-        matcherModel.setAttributeName(firstMatcher.getAttribute());
+        matcherModel.setBy(FilterBy.BY_ATTRIBUTE);
+        // matcherModel.setAttributeName(firstMatcher.getAttribute());
+        String[] attName = firstMatcher.getAttribute();
+        matcherModel.getAttributeName().add(attName[0]); // attribute
+        if (attName.length > 1)
+        {
+          matcherModel.getAttributeName().add(attName[1]); // sub-attribute
+        }
       }
       else if (firstMatcher.isByLabel())
       {
-        matcherModel.setBy(FeatureMatcherByType.BYLABEL);
+        matcherModel.setBy(FilterBy.BY_LABEL);
       }
       else if (firstMatcher.isByScore())
       {
-        matcherModel.setBy(FeatureMatcherByType.BYSCORE);
+        matcherModel.setBy(FilterBy.BY_SCORE);
       }
       result.setMatchCondition(matcherModel);
     }
@@ -5825,13 +6430,14 @@ public class Jalview2XML
    * @param matcherSetModel
    * @return
    */
-  protected static FeatureMatcherSetI unmarshalFilter(
-          String featureType, MatcherSet matcherSetModel)
+  public static FeatureMatcherSetI parseFilter(
+          String featureType,
+          jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel)
   {
     FeatureMatcherSetI result = new FeatureMatcherSet();
     try
     {
-      unmarshalFilterConditions(result, matcherSetModel, true);
+      parseFilterConditions(result, matcherSetModel, true);
     } catch (IllegalStateException e)
     {
       // mixing AND and OR conditions perhaps
@@ -5855,32 +6461,36 @@ public class Jalview2XML
    * @throws IllegalStateException
    *           if AND and OR conditions are mixed
    */
-  protected static void unmarshalFilterConditions(
-          FeatureMatcherSetI matcherSet, MatcherSet matcherSetModel,
+  protected static void parseFilterConditions(
+          FeatureMatcherSetI matcherSet,
+          jalview.xml.binding.jalview.FeatureMatcherSet matcherSetModel,
           boolean and)
   {
-    MatchCondition mc = matcherSetModel.getMatchCondition();
+    jalview.xml.binding.jalview.FeatureMatcher mc = matcherSetModel
+            .getMatchCondition();
     if (mc != null)
     {
       /*
        * single condition
        */
-      FeatureMatcherByType filterBy = mc.getBy();
+      FilterBy filterBy = mc.getBy();
       Condition cond = Condition.fromString(mc.getCondition());
       String pattern = mc.getValue();
       FeatureMatcherI matchCondition = null;
-      if (filterBy == FeatureMatcherByType.BYLABEL)
+      if (filterBy == FilterBy.BY_LABEL)
       {
         matchCondition = FeatureMatcher.byLabel(cond, pattern);
       }
-      else if (filterBy == FeatureMatcherByType.BYSCORE)
+      else if (filterBy == FilterBy.BY_SCORE)
       {
         matchCondition = FeatureMatcher.byScore(cond, pattern);
   
       }
-      else if (filterBy == FeatureMatcherByType.BYATTRIBUTE)
+      else if (filterBy == FilterBy.BY_ATTRIBUTE)
       {
-        String[] attNames = mc.getAttributeName();
+        final List<String> attributeName = mc.getAttributeName();
+        String[] attNames = attributeName
+                .toArray(new String[attributeName.size()]);
         matchCondition = FeatureMatcher.byAttribute(cond, pattern,
                 attNames);
       }
@@ -5903,13 +6513,13 @@ public class Jalview2XML
       /*
        * compound condition
        */
-      MatcherSet[] matchers = matcherSetModel.getCompoundMatcher()
-              .getMatcherSet();
-      boolean anded = matcherSetModel.getCompoundMatcher().getAnd();
-      if (matchers.length == 2)
+      List<jalview.xml.binding.jalview.FeatureMatcherSet> matchers = matcherSetModel
+              .getCompoundMatcher().getMatcherSet();
+      boolean anded = matcherSetModel.getCompoundMatcher().isAnd();
+      if (matchers.size() == 2)
       {
-        unmarshalFilterConditions(matcherSet, matchers[0], anded);
-        unmarshalFilterConditions(matcherSet, matchers[1], anded);
+        parseFilterConditions(matcherSet, matchers.get(0), anded);
+        parseFilterConditions(matcherSet, matchers.get(1), anded);
       }
       else
       {
@@ -5924,12 +6534,11 @@ public class Jalview2XML
    * @param colourModel
    * @return
    */
-  protected static FeatureColourI unmarshalColour(
-          jalview.schemabinding.version2.Colour colourModel)
+  public static FeatureColourI parseColour(Colour colourModel)
   {
     FeatureColourI colour = null;
   
-    if (colourModel.hasMax())
+    if (colourModel.getMax() != null)
     {
       Color mincol = null;
       Color maxcol = null;
@@ -5955,35 +6564,36 @@ public class Jalview2XML
       }
   
       colour = new FeatureColour(maxcol, mincol, maxcol, noValueColour,
-              colourModel.getMin(), colourModel.getMax());
-      String[] attributes = colourModel.getAttributeName();
+              safeFloat(colourModel.getMin()),
+              safeFloat(colourModel.getMax()));
+      final List<String> attributeName = colourModel.getAttributeName();
+      String[] attributes = attributeName
+              .toArray(new String[attributeName.size()]);
       if (attributes != null && attributes.length > 0)
       {
         colour.setAttributeName(attributes);
       }
-      if (colourModel.hasAutoScale())
+      if (colourModel.isAutoScale() != null)
       {
-        colour.setAutoScaled(colourModel.getAutoScale());
+        colour.setAutoScaled(colourModel.isAutoScale().booleanValue());
       }
-      if (colourModel.hasColourByLabel())
+      if (colourModel.isColourByLabel() != null)
       {
-        colour.setColourByLabel(colourModel.getColourByLabel());
+        colour.setColourByLabel(
+                colourModel.isColourByLabel().booleanValue());
       }
-      if (colourModel.hasThreshold())
+      if (colourModel.getThreshold() != null)
       {
-        colour.setThreshold(colourModel.getThreshold());
+        colour.setThreshold(colourModel.getThreshold().floatValue());
       }
-      ColourThreshTypeType ttyp = colourModel.getThreshType();
-      if (ttyp != null)
+      ThresholdType ttyp = colourModel.getThreshType();
+      if (ttyp == ThresholdType.ABOVE)
       {
-        if (ttyp == ColourThreshTypeType.ABOVE)
-        {
-          colour.setAboveThreshold(true);
-        }
-        else if (ttyp == ColourThreshTypeType.BELOW)
-        {
-          colour.setBelowThreshold(true);
-        }
+        colour.setAboveThreshold(true);
+      }
+      else if (ttyp == ThresholdType.BELOW)
+      {
+        colour.setBelowThreshold(true);
       }
     }
     else