JalviewJS pre-configured entry point for demos
[jalview.git] / src / jalview / project / Jalview2XML.java
index c4ad897..646cab5 100644 (file)
@@ -60,6 +60,7 @@ import jalview.gui.StructureViewerBase;
 import jalview.gui.TreePanel;
 import jalview.io.DataSourceType;
 import jalview.io.FileFormat;
+import jalview.io.NewickFile;
 import jalview.renderer.ResidueShaderI;
 import jalview.schemes.AnnotationColourGradient;
 import jalview.schemes.ColourSchemeI;
@@ -129,6 +130,7 @@ import java.awt.Color;
 import java.awt.Font;
 import java.awt.Rectangle;
 import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.File;
@@ -185,6 +187,27 @@ import javax.xml.stream.XMLStreamReader;
  */
 public class Jalview2XML
 {
+
+  // BH 2018 we add the .jvp binary extension to J2S so that
+  // it will declare that binary when we do the file save from the browser
+
+  private static void addJ2SBinaryType(String ext)
+  {
+    ext = "." + ext + "?";
+
+    /**
+     * @j2sNative
+     * 
+     *            J2S._binaryTypes.push(ext);
+     * 
+     */
+  }
+
+  static
+  {
+    addJ2SBinaryType(".jvp?");
+  }
+
   private static final String VIEWER_PREFIX = "viewer_";
 
   private static final String RNA_PREFIX = "rna_";
@@ -226,6 +249,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
@@ -1555,6 +1617,7 @@ public class Jalview2XML
       // using save and then load
       try
       {
+       fileName = fileName.replace('\\', '/');
         System.out.println("Writing jar entry " + fileName);
         JarEntry entry = new JarEntry(fileName);
         jout.putNextEntry(entry);
@@ -1735,6 +1798,7 @@ public class Jalview2XML
   {
     if (jout != null)
     {
+      jarEntryName = jarEntryName.replace('\\','/');
       System.out.println("Writing jar entry " + jarEntryName);
       jout.putNextEntry(new JarEntry(jarEntryName));
       DataOutputStream dout = new DataOutputStream(jout);
@@ -2417,7 +2481,7 @@ public class Jalview2XML
    * @param file
    *          - HTTP URL or filename
    */
-  public AlignFrame loadJalviewAlign(final String file)
+  public AlignFrame loadJalviewAlign(final Object file)
   {
 
     jalview.gui.AlignFrame af = null;
@@ -2461,44 +2525,52 @@ public class Jalview2XML
     return af;
   }
 
-  private jarInputStreamProvider createjarInputStreamProvider(
-          final String file) throws MalformedURLException
-  {
-    URL url = null;
-    errorMessage = null;
-    uniqueSetSuffix = null;
-    seqRefIds = null;
-    viewportsAdded.clear();
-    frefedSequence = null;
-
-    if (file.startsWith("http://"))
-    {
-      url = new URL(file);
-    }
-    final URL _url = url;
-    return new jarInputStreamProvider()
-    {
-
-      @Override
-      public JarInputStream getJarInputStream() throws IOException
-      {
-        if (_url != null)
-        {
-          return new JarInputStream(_url.openStream());
-        }
-        else
-        {
-          return new JarInputStream(new FileInputStream(file));
-        }
-      }
-
-      @Override
-      public String getFilename()
-      {
-        return file;
-      }
-    };
-  }
+       @SuppressWarnings("unused")
+       private jarInputStreamProvider createjarInputStreamProvider(final Object ofile) throws MalformedURLException {
+
+               // BH 2018 allow for bytes already attached to File object
+               try {
+                       String file = (ofile instanceof File ? ((File) ofile).getCanonicalPath() : ofile.toString());
+                       byte[] bytes = /** @j2sNative ofile._bytes || */
+                                       null;
+                       URL url = null;
+                       errorMessage = null;
+                       uniqueSetSuffix = null;
+                       seqRefIds = null;
+                       viewportsAdded.clear();
+                       frefedSequence = null;
+
+                       if (file.startsWith("http://")) {
+                               url = new URL(file);
+                       }
+                       final URL _url = url;
+                       return new jarInputStreamProvider() {
+
+                               @Override
+                               public JarInputStream getJarInputStream() throws IOException {
+                                       if (bytes != null) {
+//                                             System.out.println("Jalview2XML: opening byte jarInputStream for bytes.length=" + bytes.length);
+                                               return new JarInputStream(new ByteArrayInputStream(bytes));
+                                       }
+                                       if (_url != null) {
+//                                             System.out.println("Jalview2XML: opening url jarInputStream for " + _url);
+                                               return new JarInputStream(_url.openStream());
+                                       } else {
+//                                             System.out.println("Jalview2XML: opening file jarInputStream for " + file);
+                                               return new JarInputStream(new FileInputStream(file));
+                                       }
+                               }
+
+                               @Override
+                               public String getFilename() {
+                                       return file;
+                               }
+                       };
+               } catch (IOException e) {
+                       e.printStackTrace();
+                       return null;
+               }
+       }
 
   /**
    * Recover jalview session from a jalview project archive. Caller may
@@ -2540,9 +2612,6 @@ public class Jalview2XML
 
         if (jarentry != null && jarentry.getName().endsWith(".xml"))
         {
-          InputStreamReader in = new InputStreamReader(jin, UTF_8);
-          // JalviewModel object = new JalviewModel();
-
           JAXBContext jc = JAXBContext
                   .newInstance("jalview.xml.binding.jalview");
           XMLStreamReader streamReader = XMLInputFactory.newInstance()
@@ -2552,11 +2621,6 @@ public class Jalview2XML
                   .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);
@@ -2732,8 +2796,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");
@@ -3057,8 +3121,7 @@ public class Jalview2XML
         vi++;
       }
 
-      if (jseq.isViewreference() != null
-              && jseq.isViewreference().booleanValue())
+      if (safeBoolean(jseq.isViewreference()))
       {
         referenceseqForView = tmpseqs.get(tmpseqs.size() - 1);
       }
@@ -3150,7 +3213,7 @@ public class Jalview2XML
             Feature feat = features.get(f);
             SequenceFeature sf = new SequenceFeature(feat.getType(),
                     feat.getDescription(), feat.getBegin(), feat.getEnd(),
-                    feat.getScore(), feat.getFeatureGroup());
+                    safeFloat(feat.getScore()), feat.getFeatureGroup());
             sf.setStatus(feat.getStatus());
 
             /*
@@ -3344,22 +3407,21 @@ public class Jalview2XML
           // 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.isVisible() != null) // annotation.hasVisible())
+          if (annotation.isVisible() != null)
           {
             jda.visible = annotation.isVisible();
           }
@@ -3386,8 +3448,7 @@ public class Jalview2XML
               continue;
             }
 
-            float value = annElement.getValue() == null ? 0f
-                    : annElement.getValue().floatValue();
+            float value = safeFloat(annElement.getValue());
             anot[anpos] = new jalview.datamodel.Annotation(
                     annElement.getDisplayCharacter(),
                     annElement.getDescription(),
@@ -3399,16 +3460,7 @@ public class Jalview2XML
                                                     .getSecondaryStructure()
                                                     .charAt(0),
                     value);
-            // JBPNote: Consider verifying dataflow for IO of secondary
-            // structure annotation read from Stockholm files
-            // this was added to try to ensure that
-            // if (anot[ annElement.getPosition()].secondaryStructure>' ')
-            // {
-            // anot[ annElement.getPosition()].displayCharacter = "";
-            // }
-            final int colourValue = annElement.getColour() == null ? 0
-                    : annElement.getColour().intValue();
-            anot[anpos].colour = new java.awt.Color(colourValue);
+            anot[anpos].colour = new Color(safeInt(annElement.getColour()));
             if (firstColour == null)
             {
               firstColour = anot[anpos].colour;
@@ -3425,18 +3477,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())
           {
@@ -3490,7 +3541,7 @@ public class Jalview2XML
 
         if (annotation.getScore() != null)
         {
-          jaa.setScore(annotation.getScore());
+          jaa.setScore(annotation.getScore().doubleValue());
         }
         if (annotation.isVisible() != null)
         {
@@ -3507,8 +3558,7 @@ public class Jalview2XML
         {
           jaa.scaleColLabel = annotation.isScaleColLabels().booleanValue();
         }
-        if (/*annotation.hasAutoCalculated() && */annotation
-                .isAutoCalculated())
+        if (annotation.isAutoCalculated())
         {
           // newer files have an 'autoCalculated' flag and store calculation
           // state in viewport properties
@@ -3519,11 +3569,7 @@ public class Jalview2XML
         {
           jaa.graphHeight = annotation.getGraphHeight().intValue();
         }
-        // if (annotation.hasBelowAlignment())
-        // {
-        // schema specifies default for optional attribute
-          jaa.belowAlignment = annotation.isBelowAlignment();
-        // }
+        jaa.belowAlignment = annotation.isBelowAlignment();
         jaa.setCalcId(annotation.getCalcId());
         if (annotation.getProperty().size() > 0)
         {
@@ -3574,8 +3620,7 @@ public class Jalview2XML
                     jGroup.getColour());
           }
         }
-        int pidThreshold = jGroup.getPidThreshold() == null ? 0
-                : jGroup.getPidThreshold().intValue();
+        int pidThreshold = safeInt(jGroup.getPidThreshold());
 
         Vector<SequenceI> seqs = new Vector<>();
 
@@ -3596,40 +3641,24 @@ public class Jalview2XML
         }
 
         SequenceGroup sg = new SequenceGroup(seqs, jGroup.getName(), cs,
-                jGroup.isDisplayBoxes(), jGroup.isDisplayText(),
-                jGroup.isColourText(), 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() == null ? 0
-                        : jGroup.getConsThreshold().intValue());
-        sg.setOutlineColour(
-                new java.awt.Color(jGroup.getOutlineColour() == null ? 0
-                        : jGroup.getOutlineColour().intValue()));
-
-        sg.textColour = new java.awt.Color(jGroup.getTextCol1());
-        sg.textColour2 = new java.awt.Color(jGroup.getTextCol2());
-        sg.setShowNonconserved(
-                jGroup.isShowUnconserved() != null
-                        ? jGroup.isShowUnconserved().booleanValue()
-                        : false);
-        sg.thresholdTextColour = jGroup.getTextColThreshold();
+                .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
-        // if (jGroup.hasShowConsensusHistogram())
-        // {
           sg.setShowConsensusHistogram(jGroup.isShowConsensusHistogram());
-        // }
-        // if (jGroup.hasShowSequenceLogo())
-        // {
           sg.setshowSequenceLogo(jGroup.isShowSequenceLogo());
-        // }
-        // if (jGroup.hasNormaliseSequenceLogo())
-        // {
           sg.setNormaliseSequenceLogo(jGroup.isNormaliseSequenceLogo());
-        // }
-        // if (jGroup.hasIgnoreGapsinConsensus())
-        // {
         sg.setIgnoreGapsConsensus(jGroup.isIgnoreGapsinConsensus());
-        // }
         if (jGroup.getConsThreshold() != null
                 && jGroup.getConsThreshold().intValue() != 0)
         {
@@ -3819,7 +3848,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,
@@ -3827,7 +3856,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()));
       }
     }
   }
@@ -3868,8 +3897,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;
@@ -3898,10 +3928,10 @@ public class Jalview2XML
         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 ?
@@ -3913,11 +3943,11 @@ 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.setViewport(av); // af.viewport; // TODO: verify 'associate with all
-          // views'
-          // works still
+          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;
 
@@ -3929,27 +3959,29 @@ public class Jalview2XML
           continue;
         }
 
-        tp.fitToWindow.setState(tree.isFitToWindow());
+        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.isMarkUnlinked());
-        tp.showBootstrap(tree.isShowBootstrap());
-        tp.showDistances(tree.isShowDistances());
+        tp.showPlaceholders(safeBoolean(tree.isMarkUnlinked()));
+        tp.showBootstrap(safeBoolean(tree.isShowBootstrap()));
+        tp.showDistances(safeBoolean(tree.isShowDistances()));
 
-        tp.getTreeCanvas().setThreshold(tree.getThreshold());
+        tp.getTreeCanvas().setThreshold(safeFloat(tree.getThreshold()));
 
-        if (tree.isCurrentTree())
+        if (safeBoolean(tree.isCurrentTree()))
         {
           af.getViewport().setCurrentTree(tp.getTree());
         }
@@ -4003,10 +4035,10 @@ public class Jalview2XML
                     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);
@@ -4569,17 +4601,28 @@ public class Jalview2XML
           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) 
+//    {
+//     
+//     @Override
+//     protected void processKeyEvent(java.awt.event.KeyEvent e) {
+//             System.out.println("Jalview2XML   AF " + e);
+//             super.processKeyEvent(e);
+//             
+//     }
+//     
+//    }
+    ;
 
     af.setFileName(file, FileFormat.Jalview);
 
     final AlignViewport viewport = af.getViewport();
     for (int i = 0; i < JSEQ.size(); i++)
     {
-      viewport.setSequenceColour(
-              viewport.getAlignment().getSequenceAt(i),
-              new java.awt.Color(JSEQ.get(i).getColour()));
+      int colour = safeInt(JSEQ.get(i).getColour());
+      viewport.setSequenceColour(viewport.getAlignment().getSequenceAt(i),
+              new Color(colour));
     }
 
     if (al.hasSeqrep())
@@ -4588,7 +4631,7 @@ public class Jalview2XML
       viewport.setDisplayReferenceSeq(true);
     }
 
-    viewport.setGatherViewsHere(view.isGatheredViews());
+    viewport.setGatherViewsHere(safeBoolean(view.isGatheredViews()));
 
     if (view.getSequenceSetId() != null)
     {
@@ -4640,49 +4683,48 @@ public class Jalview2XML
     }
     // recover view properties and display parameters
 
-    viewport.setShowAnnotation(view.isShowAnnotation());
-    viewport.setAbovePIDThreshold(view.isPidSelected());
-    final int pidThreshold = view.getPidThreshold() == null ? 0
-            : view.getPidThreshold().intValue();
+    viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
+    viewport.setAbovePIDThreshold(safeBoolean(view.isPidSelected()));
+    final int pidThreshold = safeInt(view.getPidThreshold());
     viewport.setThreshold(pidThreshold);
 
-    viewport.setColourText(view.isShowColourText());
+    viewport.setColourText(safeBoolean(view.isShowColourText()));
 
     viewport
-            .setConservationSelected(view.isConservationSelected());
-    viewport.setIncrement(view.getConsThreshold() == null ? 0
-            : view.getConsThreshold().intValue());
-    viewport.setShowJVSuffix(view.isShowFullId());
-    viewport.setRightAlignIds(view.isRightAlignIds());
-    viewport.setFont(new java.awt.Font(view.getFontName(),
-            view.getFontStyle(), view.getFontSize()), true);
+            .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());
     viewport.setViewStyle(vs);
     // TODO: allow custom charWidth/Heights to be restored by updating them
     // after setting font - which means set above to false
-    viewport.setRenderGaps(view.isRenderGaps());
-    viewport.setWrapAlignment(view.isWrapAlignment());
-    viewport.setShowAnnotation(view.isShowAnnotation());
+    viewport.setRenderGaps(safeBoolean(view.isRenderGaps()));
+    viewport.setWrapAlignment(safeBoolean(view.isWrapAlignment()));
+    viewport.setShowAnnotation(safeBoolean(view.isShowAnnotation()));
 
-    viewport.setShowBoxes(view.isShowBoxes());
+    viewport.setShowBoxes(safeBoolean(view.isShowBoxes()));
 
-    viewport.setShowText(view.isShowText());
+    viewport.setShowText(safeBoolean(view.isShowText()));
 
-    viewport.setTextColour(new java.awt.Color(view.getTextCol1()));
-    viewport.setTextColour2(new java.awt.Color(view.getTextCol2()));
-    viewport.setThresholdTextColour(view.getTextColThreshold());
-    viewport.setShowUnconserved(
-            view.isShowUnconserved() ? view.isShowUnconserved() : false);
-    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)
     {
       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;
@@ -4714,10 +4756,10 @@ public class Jalview2XML
             .setConsensus(viewport.getSequenceConsensusHash());
     viewport.setColourAppliesToAllGroups(false);
 
-    if (view.isConservationSelected() && cs != null)
+    if (safeBoolean(view.isConservationSelected()) && cs != null)
     {
       viewport.getResidueShading()
-              .setConservationInc(view.getConsThreshold());
+              .setConservationInc(safeInt(view.getConsThreshold()));
     }
 
     af.changeColour(cs);
@@ -4725,69 +4767,20 @@ public class Jalview2XML
     viewport.setColourAppliesToAllGroups(true);
 
     viewport
-            .setShowSequenceFeatures(view.isShowSequenceFeatures());
+            .setShowSequenceFeatures(
+                    safeBoolean(view.isShowSequenceFeatures()));
 
-    // if (view.hasCentreColumnLabels())
-    // {
     viewport.setCentreColumnLabels(view.isCentreColumnLabels());
-    // }
-    // if (view.hasIgnoreGapsinConsensus())
-    // {
     viewport.setIgnoreGapsConsensus(view.isIgnoreGapsinConsensus(), null);
-    // }
-    // if (view.hasFollowHighlight())
-    // {
-
     viewport.setFollowHighlight(view.isFollowHighlight());
-    // }
-    // if (view.hasFollowSelection())
-    // {
     viewport.followSelection = view.isFollowSelection();
-    // }
-    // if (view.hasShowConsensusHistogram())
-    // {
     viewport.setShowConsensusHistogram(view.isShowConsensusHistogram());
-    // }
-    // else
-    // {
-    // viewport.setShowConsensusHistogram(true);
-    // }
-    // if (view.hasShowSequenceLogo())
-    // {
     viewport.setShowSequenceLogo(view.isShowSequenceLogo());
-    // }
-    // else
-    // {
-    // viewport.setShowSequenceLogo(false);
-    // }
-    // if (view.hasNormaliseSequenceLogo())
-    // {
     viewport.setNormaliseSequenceLogo(view.isNormaliseSequenceLogo());
-    // }
-    if (view.isShowDbRefTooltip() != null)
-    {
-      viewport.setShowDBRefs(view.isShowDbRefTooltip());
-    }
-    if (view.isShowNPfeatureTooltip() != null)
-    {
-      viewport.setShowNPFeats(view.isShowNPfeatureTooltip());
-    }
-    // if (view.hasShowGroupConsensus())
-    // {
+    viewport.setShowDBRefs(safeBoolean(view.isShowDbRefTooltip()));
+    viewport.setShowNPFeats(safeBoolean(view.isShowNPfeatureTooltip()));
     viewport.setShowGroupConsensus(view.isShowGroupConsensus());
-    // }
-    // else
-    // {
-    // viewport.setShowGroupConsensus(false);
-    // }
-    // if (view.hasShowGroupConservation())
-    // {
     viewport.setShowGroupConservation(view.isShowGroupConservation());
-    // }
-    // else
-    // {
-    // viewport.setShowGroupConservation(false);
-    // }
 
     // recover feature settings
     if (jm.getFeatureSettings() != null)
@@ -4843,12 +4836,9 @@ public class Jalview2XML
           {
             noValueColour = maxColour;
           }
-          float min = setting.getMin() != null
-                  ? setting.getMin().floatValue()
-                  : 0f;
-          float max = setting.getMin() != null
-                  ? setting.getMax().floatValue()
-                  : 1f;
+          float min = safeFloat(safeFloat(setting.getMin()));
+          float max = setting.getMax() == null ? 1f
+                  : setting.getMax().floatValue();
           FeatureColourI gc = new FeatureColour(minColour, maxColour,
                   noValueColour, min, max);
           if (setting.getAttributeName().size() > 0)
@@ -4859,7 +4849,7 @@ public class Jalview2XML
           if (setting.getThreshold() != null)
           {
             gc.setThreshold(setting.getThreshold().floatValue());
-            int threshstate = setting.getThreshstate().intValue();
+            int threshstate = safeInt(setting.getThreshstate());
             // -1 = None, 0 = Below, 1 = Above threshold
             if (threshstate == 0)
             {
@@ -4897,7 +4887,7 @@ public class Jalview2XML
           featureOrder.put(featureType, new Float(
                   fs / jm.getFeatureSettings().getSetting().size()));
         }
-        if (setting.isDisplay())
+        if (safeBoolean(setting.isDisplay()))
         {
           fdi.setVisible(featureType);
         }
@@ -4920,9 +4910,9 @@ public class Jalview2XML
     {
       for (int c = 0; c < view.getHiddenColumns().size(); c++)
       {
-        viewport.hideColumns(view.getHiddenColumns().get(c).getStart(),
-                view.getHiddenColumns().get(c).getEnd() // +1
-        );
+        final HiddenColumns hc = view.getHiddenColumns().get(c);
+        viewport.hideColumns(safeInt(hc.getStart()),
+                safeInt(hc.getEnd()) /* +1 */);
       }
     }
     if (view.getCalcIdParam() != null)
@@ -4953,8 +4943,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);
@@ -5029,34 +5019,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(model, viewAnnColour.getColourScheme()),
-              viewAnnColour.getAboveThreshold());
+              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);
 
@@ -5073,7 +5065,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);
@@ -6130,8 +6122,8 @@ public class Jalview2XML
       }
   
       colour = new FeatureColour(mincol, maxcol, noValueColour,
-              colourModel.getMin(),
-              colourModel.getMax());
+              safeFloat(colourModel.getMin()),
+              safeFloat(colourModel.getMax()));
       final List<String> attributeName = colourModel.getAttributeName();
       String[] attributes = attributeName
               .toArray(new String[attributeName.size()]);