Merge branch 'releases/Release_2_10_0_Branch'
authorJim Procter <jprocter@issues.jalview.org>
Mon, 24 Oct 2016 20:27:52 +0000 (21:27 +0100)
committerJim Procter <jprocter@issues.jalview.org>
Mon, 24 Oct 2016 20:27:52 +0000 (21:27 +0100)
32 files changed:
1  2 
help/html/editing/index.html
help/html/features/structurechooser.html
help/html/features/viewingpdbs.html
help/html/releases.html
resources/embl_mapping.xml
resources/uniprot_mapping.xml
src/MCview/PDBChain.java
src/MCview/PDBViewer.java
src/jalview/appletgui/AlignFrame.java
src/jalview/appletgui/AppletJmol.java
src/jalview/datamodel/PDBEntry.java
src/jalview/datamodel/xdb/embl/EmblFile.java
src/jalview/ext/jmol/JalviewJmolBinding.java
src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/AppJmol.java
src/jalview/gui/ChimeraViewFrame.java
src/jalview/gui/Desktop.java
src/jalview/gui/Jalview2XML.java
src/jalview/gui/SeqPanel.java
src/jalview/gui/StructureChooser.java
src/jalview/gui/StructureViewer.java
src/jalview/structure/StructureSelectionManager.java
src/jalview/structures/models/AAStructureBindingModel.java
src/jalview/util/DBRefUtils.java
src/jalview/viewmodel/AlignmentViewport.java
src/jalview/ws/dbsources/EmblXmlSource.java
src/jalview/ws/dbsources/Uniprot.java
test/jalview/gui/AlignViewportTest.java
test/jalview/gui/StructureChooserTest.java
test/jalview/structures/models/AAStructureBindingModelTest.java
test/jalview/ws/dbsources/UniprotTest.java

@@@ -1,7 -1,7 +1,7 @@@
  <html>
  <!--
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -49,9 -49,8 +49,8 @@@
      right to insert gaps and remove gaps.<br> If the current
      selection is a group over all sequences in the alignment, or a group
      over some sequences or all columns in the alignment, then hold down
-     either &quot;Control&quot; key (or the &quot;Alt;&quot; on OSX if
-     &quot;Control&quot; does not work) and drag the residue left or
-     right to edit all sequences in the defined group at once.
+     &quot;Control&quot; key (&quot;Cmd&quot; key on OSX) and drag the residue 
+     left or right to edit all sequences in the defined group at once.
    </p>
    <p>
      <em>Copy/paste/cut/delete</em> - any sequences which are in the
@@@ -1,7 -1,7 +1,7 @@@
  <html>
  <!--
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -31,7 -31,7 +31,7 @@@
    <p>
      The Structure Chooser interface allows you to interactively select
      which PDB structures to view for the currently selected set of
-     sequences. It's opened by selecting the <strong>"3D
+     sequences. It is opened by selecting the <strong>"3D
        Structure Data.."</strong> option from the Sequence ID panel's <a
        href="../menus/popupMenu.html">pop-up menu</a>. The dialog
      provides:
      <li>Association of structure data from a local file (in mmCIF
        or PDB format)</li>
    </ul>
+   <p>
+     <strong>Selecting and Viewing Structures</strong>
+   </p>
+   <p>
+     Once one or more structures have been selected, pressing the <strong>View</strong>
+     button will import them into <a
+       href="viewingpdbs.html#afterviewbutton">a new or existing
+       structure view</a>.
+   </p>
    <p>
      <strong>Automated discovery of structure data</strong>
    </p>
-   <p>After selecting "3D Structure Data ..", Jalview queries the PDB
-     via the PDBe SOLR Rest API provided by EMBL-EBI to discover PDB ids
+   <p>
+     After selecting "3D Structure Data ..", Jalview queries the PDB via
+     the PDBe SOLR Rest API provided by EMBL-EBI to discover PDB IDs
      associated with the sequence. It does this based on the sequence's
-     ID string, and any other associated database IDs.</p>
+     ID string, and any other associated database IDs. <br />
+     <br />
    <p>
-     <strong>Exploration of meta-data for available structures</strong>
+     <strong><a name="cachedstructview">Viewing existing
+         structures for your sequences</a></strong>
+   </p>
+   <p>
+     If you have already loaded 3D structure data for the selected
+     sequences, the structure chooser will first open with the <strong>Cached
+       Structures View</strong>. This view shows associations between each
+     sequence, and chains for 3D structure files already in memory. If
+     you want to download additional structures, select one of the other
+     options from the drop down menu.
    </p>
-   <p>Information on each structure available is displayed in columns
-     in the dialog box. By default, only the title, resolution and PDB
-     identifier are shown, but many more are provided by the PDBe. To
-     configure which ones are displayed, select the 'Configure Displayed
-     Columns' tab and tick the columns which you want to see.</p>
    <p>
      <strong>Selection of the best structure for each sequence</strong>
    </p>
    <p>Jalview can automatically select the best structures according
-     to meta-data provided by the PDB. By default, the 'Best Quality'
-     structure for each sequence will be selected, but clicking on the
-     drop down menu allows other criteria to be chosen, including
-     Resolution (only defined for X-Ray structures), Highest Protein
-     Chain etc. When 'Invert' is selected, structures are selected in
-     reverse order for the current criteria (e.g. worst quality rather
-     than best).</p>
+     to meta-data provided by the PDB. For alignments with no existing
+     structure data, the 'Best Quality' structure for each sequence will
+     by default be selected, but clicking on the drop down menu allows
+     other criteria to be chosen, including Resolution (only defined for
+     X-Ray structures), Highest Protein Chain etc. When 'Invert' is
+     selected, structures are selected in reverse order for the current
+     criteria (e.g. worst quality rather than best).</p>
    <p>
  
      <img src="schooser_main.png" style="width: 464px; height: 369px;">
        <p><img src="schooser_cached.png"> -->
      <br>The screenshot above shows the Structure Chooser interface
      along with the meta-data of auto-discovered structures for the
-     sample alignment. Note however that if no structures were
-     auto-discovered, a different interface for manual association will
-     be invoked as seen in the screenshot below.
+     sample alignment. If no structures were
+     auto-discovered, options for manually associating PDB records will be shown (see below).
+   <p>
+     <strong>Exploration of meta-data for available structures</strong>
+   </p>
+   <p>Information on each structure available is displayed in columns
+     in the dialog box. By default, only the title, resolution and PDB
+     identifier are shown, but many more are provided by the PDBe. To
+     configure which ones are displayed, select the 'Configure Displayed
+     Columns' tab and tick the columns which you want to see.</p>
    <p>
      <img src="schooser_enter-id.png"
        style="width: 464px; height: 369px;">
-   <p>
+       <br/>
      <strong>Manual selection/association of PDB files with
        Sequences</strong>
    </p>
        for your sequence. The PDB Rest API, provided by EMBL-EBI, is used
        to validate and fetch structure data.<br></li>
    </ul>
-   <p>
-     <strong>Viewing existing structures for your sequences</strong>
-   </p>
-   <p>
-     If you have previously associated structure data on the alignment,
-     selecting <strong>Cached PDB Entries</strong> from the drop down
-     menu allows you to select these structures for display.
-   </p>
  
    <p>
      <em>The Structure Chooser interface was introduced in Jalview
@@@ -1,7 -1,7 +1,7 @@@
  <html>
  <!--
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
        'highest resolution', simply choose another to pick structures in
        a different way.<br />
        <ul>
-         <li><strong>Viewing Cached Structures</strong><br />If you
-           have previously downloaded structures for your sequences, they
-           can be viewed by selecting the <strong>Cached PDB
-             Entries</strong> option from the drop down menu at the top of the
-           dialog box.</li>
+         <li><strong>Viewing Cached Structures</strong><br />If
+           previously downloaded structures are available for your
+           sequences, the structure chooser will automatically offer them
+           via the <strong>Cached PDB Entries</strong> view. If you wish
+           to download new structures, select one of the PDBe selection
+           criteria from the drop-down menu.</li>
        </ul></li>
      <li><strong>To view selected structures, click the <strong>"View"</strong>
          button.
          <li><a href="siftsmapping.html">SIFTS</a> records will also
            be downloaded for mapping UniProt protein sequence data to PDB
            coordinates.</li>
+         <li>A new structure viewer will open, or you will be
+           prompted to add structures to existing viewers (see <a
+           href="#afterviewbutton">below</a> for details).
+         </li>
        </ul></li>
    </ol>
+   <p>
+   <strong>Structure Viewers in the Jalview Desktop</strong><br/>
    The
    <a href="jmol.html">Jmol viewer</a> has been included since Jalview
    2.3. Jalview 2.8.2 included support for
      the <a href="xsspannotation.html">Annotation from Structure</a> page
      for more information.
    </p>
    <p>
-     If a <strong>single</strong> PDB structure is selected, one of the
-     following will happen:
+     <strong><a name="afterviewbutton">After pressing the
+         'View' button in the Structure Chooser</a></strong><br /> The behaviour of
+     the 'View' button depends on the number of structures selected, and
+     whether structure views already exist for the selected structures or
+     aligned sequences.
+   </p>
+   <p>
+     If multiple structures are selected, then Jalview will always create
+     a new structure view. The selected structures will be imported into
+     this view, and superposed with the matched positions from the
+     aligned sequences.<br /> If a <strong>single</strong> PDB structure
+     is selected, one of the following will happen:
    </p>
  
    <ul>
  
      <li>If another structure is already shown for the current
        alignment, then you will be asked if you want to add and <a
-       href="jmol.html#align">align this structure</a> to the structure
-       in the existing view. (<em>new feature in Jalview 2.6</em>).
-     </li>
+       href="jmol.html#align"></a> to
+     the structure in the existing view. (<em>new feature in Jalview
+       2.6</em>).
+   </li>
  
      <li>If the structure is already shown, then you will be
        prompted to associate the sequence with an existing view of the
diff --combined help/html/releases.html
@@@ -1,7 -1,7 +1,7 @@@
  <html>
  <!--
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
      <tr>
        <td width="60" nowrap>
          <div align="center">
+           <strong><a name="Jalview.2.10.0b1">2.10.0b1</a><br />
+             <em>25/10/2016</em></strong>
+         </div>
+       </td>
+       <td><em>Application</em>
+         <ul>
+           <li>3D Structure chooser opens with 'Cached structures'
+             view if structures already loaded</li>
+           <li>Progress bar reports models as they are loaded to
+             structure views</li>
+         </ul></td>
+       <td>
+         <div align="left">
+           <em>General</em>
+           <ul>
+             <li>Colour by conservation always enabled and no tick
+               shown in menu when BLOSUM or PID shading applied</li>
+             <li>FER1_ARATH and FER2_ARATH labels were switched in
+               example sequences/projects/trees</li>
+           </ul>
+           <em>Application</em>
+           <ul>
+             <li>Jalview projects with views of local PDB structure
+               files saved on Windows cannot be opened on OSX</li>
+             <li>Multiple structure views can be opened and
+               superposed without timeout for structures with multiple
+               models or multiple sequences in alignment</li>
+             <li>Cannot import or associated local PDB files without
+               a PDB ID HEADER line</li>
+             <li>RMSD is not output in Jmol console when
+               superposition is performed</li>
+             <li>Drag and drop of URL from Browser fails for Linux
+               and OSX versions earlier than El Capitan</li>
+             <li>ENA client ignores invalid content from ENA server</li>
+             <li>Exceptions are not raised in console when ENA
+               client attempts to fetch non-existent IDs via Fetch DB
+               Refs UI option</li>
+             <li>Exceptions are not raised in console when a new
+               view is created on the alignment</li>
+             <li>OSX right-click fixed for group selections:
+               CMD-click to insert/remove gaps in groups and CTRL-click
+               to open group pop-up menu</li>
+           </ul>
+           <em>Build and deployment</em>
+           <ul>
+             <li>URL link checker now copes with multi-line anchor
+               tags</li>
+           </ul>
+           <em>New Known Issues</em>
+           <ul>
+             <li>Drag and drop from URL links in browsers do not
+               work on Windows</li>
+           </ul>
+         </div>
+       </td>
+     </tr>
+     <tr>
+       <td width="60" nowrap>
+         <div align="center">
            <strong><a name="Jalview.2.10.0">2.10.0</a><br /> <em>06/10/2016</em></strong>
          </div>
        </td>
@@@ -1,7 -1,7 +1,7 @@@
  <?xml version="1.0"?>
  <!--
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -28,6 -28,9 +28,9 @@@
        -->
        <class name="jalview.datamodel.xdb.embl.EmblFile">
                <map-to xml="ROOT"/>
+               <field name="text" type="string">
+                       <bind-xml node="text"/>
+               </field>
                <field name="entries" type="jalview.datamodel.xdb.embl.EmblEntry" collection="vector">
                        <bind-xml name="entry"/>
                </field>
@@@ -1,7 -1,7 +1,7 @@@
  <?xml version="1.0"?>
  <!--
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -80,7 -80,7 +80,7 @@@
         <class name="jalview.datamodel.PDBEntry">
                <field name="type"><bind-xml node="attribute"/></field>
                <field name="id"><bind-xml node="attribute"/></field>
-               <field name="property" collection="hashtable">
+               <field name="props" collection="hashtable">
                        <bind-xml name="property">
                           <class name="org.exolab.castor.mapping.MapItem">
                              <field name="key">
diff --combined src/MCview/PDBChain.java
@@@ -1,6 -1,6 +1,6 @@@
  /*
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -199,7 -199,8 +199,8 @@@ public class PDBChai
      }
      for (int i = 0; i < features.length; i++)
      {
-       if (features[i].getFeatureGroup().equals(pdbid))
+       if (features[i].getFeatureGroup() != null
+               && features[i].getFeatureGroup().equals(pdbid))
        {
          SequenceFeature tx = new SequenceFeature(features[i]);
          tx.setBegin(1 + residues.elementAt(tx.getBegin() - offset).atoms
@@@ -1,6 -1,6 +1,6 @@@
  /*
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -128,18 -128,17 +128,17 @@@ public class PDBViewer extends JInterna
        worker.start();
      }
  
-     if (pdbentry.getProperty() != null)
+     String method = (String) pdbentry.getProperty("method");
+     if (method != null)
      {
-       if (pdbentry.getProperty().get("method") != null)
-       {
-         title.append(" Method: ");
-         title.append(pdbentry.getProperty().get("method"));
-       }
-       if (pdbentry.getProperty().get("chains") != null)
-       {
-         title.append(" Chain:");
-         title.append(pdbentry.getProperty().get("chains"));
-       }
+       title.append(" Method: ");
+       title.append(method);
+     }
+     String ch = (String) pdbentry.getProperty("chains");
+     if (ch != null)
+     {
+       title.append(" Chain:");
+       title.append(ch);
      }
      Desktop.addInternalFrame(this, title.toString(), 400, 400);
    }
@@@ -1,6 -1,6 +1,6 @@@
  /*
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -102,7 -102,6 +102,6 @@@ import java.net.URLEncoder
  import java.util.Arrays;
  import java.util.Deque;
  import java.util.HashMap;
- import java.util.Hashtable;
  import java.util.List;
  import java.util.Map;
  import java.util.StringTokenizer;
@@@ -4024,12 -4023,7 +4023,7 @@@ public class AlignFrame extends Embmenu
        }
        if (needtoadd)
        {
-         // make a note of the access mode and add
-         if (pdbentry.getProperty() == null)
-         {
-           pdbentry.setProperty(new Hashtable());
-         }
-         pdbentry.getProperty().put("protocol", protocol);
+         pdbentry.setProperty("protocol", protocol);
          toaddpdb.addPDBId(pdbentry);
          alignPanel.getStructureSelectionManager()
                  .registerPDBEntry(pdbentry);
      if (protocol == null || protocol.trim().length() == 0
              || protocol.equals("null"))
      {
-       protocol = (String) pdb.getProperty().get("protocol");
+       protocol = (String) pdb.getProperty("protocol");
        if (protocol == null)
        {
          System.err.println("Couldn't work out protocol to open structure: "
@@@ -1,6 -1,6 +1,6 @@@
  /*
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -60,12 -60,9 +60,9 @@@ import java.awt.event.KeyListener
  import java.awt.event.WindowAdapter;
  import java.awt.event.WindowEvent;
  import java.util.ArrayList;
  import java.util.List;
  import java.util.Vector;
  
- import org.jmol.util.Logger;
  public class AppletJmol extends EmbmenuFrame implements
  // StructureListener,
          KeyListener, ActionListener, ItemListener
        jmb.allocateViewer(renderPanel, true, ap.av.applet.getName()
                + "_jmol_", ap.av.applet.getDocumentBase(),
                ap.av.applet.getCodeBase(), "-applet", scriptWindow, null);
-       Logger.setLogLevel(Logger.LEVEL_WARN);
      } catch (Exception e)
      {
        System.err
          closeViewer();
        }
      });
-     if (pdbentry.getProperty() == null)
-     {
-       pdbentry.setProperty(new Hashtable());
-       pdbentry.getProperty().put("protocol", protocol);
-     }
+     pdbentry.setProperty("protocol", protocol);
      if (pdbentry.getFile() != null)
      {
        // import structure data from pdbentry.getFile based on given protocol
@@@ -1,6 -1,6 +1,6 @@@
  /*
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -22,10 -22,20 +22,20 @@@ package jalview.datamodel
  
  import jalview.util.CaseInsensitiveString;
  
+ import java.util.Collections;
+ import java.util.Enumeration;
  import java.util.Hashtable;
  
  public class PDBEntry
  {
+   /**
+    * constant for storing chain code in properties table
+    */
+   private static final String CHAIN_ID = "chain_code";
+   private Hashtable<String, Object> properties;
    private static final int PDB_ID_LENGTH = 4;
  
    private String file;
      }
    }
  
-   /**
-    * constant for storing chain code in properties table
-    */
-   private static final String CHAIN_ID = "chain_code";
-   Hashtable properties;
  
    /**
     * Answers true if obj is a PDBEntry with the same id and chain code (both
    /**
     * @param pdbId
     * @param chain
-    * @param type
+    * @param entryType
     * @param filePath
     */
-   void init(String pdbId, String chain, PDBEntry.Type type, String filePath)
+   void init(String pdbId, String chain, PDBEntry.Type entryType, String filePath)
    {
      this.id = pdbId;
-     this.type = type == null ? null : type.toString();
+     this.type = entryType == null ? null : entryType.toString();
      this.file = filePath;
      setChainCode(chain);
    }
      id = entry.id;
      if (entry.properties != null)
      {
-       properties = (Hashtable) entry.properties.clone();
+       properties = (Hashtable<String, Object>) entry.properties.clone();
      }
    }
  
      init(pdbId, chainCode, null, null);
    }
  
-   public void setFile(String file)
+   public void setFile(String f)
    {
-     this.file = file;
+     this.file = f;
    }
  
    public String getFile()
      return id;
    }
  
-   public void setProperty(Hashtable property)
+   public void setProperty(String key, Object value)
    {
-     this.properties = property;
+     if (this.properties == null)
+     {
+       this.properties = new Hashtable<String, Object>();
+     }
+     properties.put(key, value);
    }
  
-   public Hashtable getProperty()
+   public Object getProperty(String key)
    {
-     return properties;
+     return properties == null ? null : properties.get(key);
+   }
+   /**
+    * Returns an enumeration of the keys of this object's properties (or an empty
+    * enumeration if it has no properties)
+    * 
+    * @return
+    */
+   public Enumeration<String> getProperties()
+   {
+     if (properties == null)
+     {
+       return Collections.emptyEnumeration();
+     }
+     return properties.keys();
    }
  
    /**
              : properties.get(CHAIN_ID).toString();
    }
  
+   /**
+    * Sets a non-case-sensitive property for the given chain code. Two PDBEntry
+    * objects which differ only in the case of their chain code are considered
+    * equal. This avoids duplication of objects in lists of PDB ids.
+    * 
+    * @param chainCode
+    */
    public void setChainCode(String chainCode)
    {
-     if (properties == null)
+     if (chainCode == null)
      {
-       if (chainCode == null)
-       {
-         // nothing to do.
-         return;
-       }
-       properties = new Hashtable();
+       deleteProperty(CHAIN_ID);
      }
-     if (chainCode == null)
+     else
+     {
+       setProperty(CHAIN_ID, new CaseInsensitiveString(chainCode));
+     }
+   }
+   /**
+    * Deletes the property with the given key, and returns the deleted value (or
+    * null)
+    */
+   Object deleteProperty(String key)
+   {
+     Object result = null;
+     if (properties != null)
      {
-       properties.remove(CHAIN_ID);
-       return;
+       result = properties.remove(key);
      }
-     // update property for non-null chainCode
-     properties.put(CHAIN_ID, new CaseInsensitiveString(chainCode));
+     return result;
    }
  
    @Override
    }
  
    /**
+    * Getter provided for Castor binding only. Application code should call
+    * getProperty() or getProperties() instead.
+    * 
+    * @deprecated
+    * @see #getProperty(String)
+    * @see #getProperties()
+    * @see jalview.ws.dbsources.Uniprot#getUniprotEntries
+    * @return
+    */
+   @Deprecated
+   public Hashtable<String, Object> getProps()
+   {
+     return properties;
+   }
+   /**
+    * Setter provided for Castor binding only. Application code should call
+    * setProperty() instead.
+    * 
+    * @deprecated
+    * @return
+    */
+   @Deprecated
+   public void setProps(Hashtable<String, Object> props)
+   {
+     properties = props;
+   }
+   /**
     * Answers true if this object is either equivalent to, or can be 'improved'
     * by, the given entry.
     * <p>
     * @param newEntry
     * @return true if modifications were made
     */
-   protected boolean updateFrom(PDBEntry newEntry)
+   public boolean updateFrom(PDBEntry newEntry)
    {
      if (this.equals(newEntry))
      {
      }
  
      /*
-      * id (less any chain code) has to match (ignoring case)
+      * id has to match (ignoring case)
       */
      if (!getId().equalsIgnoreCase(newId))
      {
      }
  
      /*
-      * copy any new properties; notice this may include chain_code,
-      * but we excluded differing chain codes earlier
+      * copy any new or modified properties
       */
-     if (newEntry.getProperty() != null)
+     Enumeration<String> newProps = newEntry.getProperties();
+     while (newProps.hasMoreElements())
      {
-       if (properties == null)
+       /*
+        * copy properties unless value matches; this defends against changing
+        * the case of chain_code which is wrapped in a CaseInsensitiveString
+        */
+       String key = newProps.nextElement();
+       Object value = newEntry.getProperty(key);
+       if (!value.equals(getProperty(key)))
        {
-         properties = new Hashtable();
-       }
-       for (Object p : newEntry.getProperty().keySet())
-       {
-         /*
-          * copy properties unless value matches; this defends against changing
-          * the case of chain_code which is wrapped in a CaseInsensitiveString
-          */
-         Object value = newEntry.getProperty().get(p);
-         if (!value.equals(properties.get(p)))
-         {
-           properties.put(p, newEntry.getProperty().get(p));
-         }
+         setProperty(key, value);
        }
      }
      return true;
@@@ -1,6 -1,6 +1,6 @@@
  /*
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -46,6 -46,8 +46,8 @@@ public class EmblFil
  
    Vector<EmblError> errors;
  
+   String text;
    /**
     * @return the entries
     */
     */
    static void canonicaliseDbRefs(EmblFile record)
    {
+     if (record.getEntries() == null)
+     {
+       return;
+     }
      for (EmblEntry entry : record.getEntries())
      {
        if (entry.getDbRefs() != null)
        }
      }
    }
+   public String getText()
+   {
+     return text;
+   }
+   public void setText(String text)
+   {
+     this.text = text;
+   }
  }
@@@ -1,6 -1,6 +1,6 @@@
  /*
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -43,6 -43,7 +43,7 @@@ import java.awt.event.ComponentListener
  import java.io.File;
  import java.net.URL;
  import java.security.AccessControlException;
+ import java.util.ArrayList;
  import java.util.Hashtable;
  import java.util.List;
  import java.util.Map;
@@@ -93,11 -94,6 +94,6 @@@ public abstract class JalviewJmolBindin
  
    boolean loadedInline;
  
-   /**
-    * current set of model filenames loaded in the Jmol instance
-    */
-   String[] modelFileNames = null;
    StringBuffer resetLastRes = new StringBuffer();
  
    public Viewer viewer;
        } catch (InterruptedException i)
        {
        }
-       ;
      }
+     /*
+      * get the distinct structure files modelled
+      * (a file with multiple chains may map to multiple sequences)
+      */
      String[] files = getPdbFile();
      if (!waitForFileLoad(files))
      {
         * 'matched' array will hold 'true' for visible alignment columns where
         * all sequences have a residue with a mapping to the PDB structure
         */
+       // TODO could use a BitSet for matched
        boolean matched[] = new boolean[alignment.getWidth()];
        for (int m = 0; m < matched.length; m++)
        {
         * generate select statements to select regions to superimpose structures
         */
        {
+         // TODO extract method to construct selection statements
          for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
          {
            String chainCd = ":" + structures[pdbfnum].chain;
          }
        }
        StringBuilder command = new StringBuilder(256);
+       // command.append("set spinFps 10;\n");
        for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
        {
          if (pdbfnum == refStructure || selcom[pdbfnum] == null
        }
        if (selectioncom.length() > 0)
        {
+         // TODO is performing selectioncom redundant here? is done later on
          // System.out.println("Select regions:\n" + selectioncom.toString());
          evalStateCommand("select *; cartoons off; backbone; select ("
                  + selectioncom.toString() + "); cartoons; ");
      }
      if (modelFileNames == null)
      {
-       String mset[] = new String[viewer.ms.mc];
-       _modelFileNameMap = new int[mset.length];
+       List<String> mset = new ArrayList<String>();
+       _modelFileNameMap = new int[viewer.ms.mc];
        String m = viewer.ms.getModelFileName(0);
        if (m != null)
        {
-         mset[0] = m;
+         String filePath = m;
          try
          {
-           mset[0] = new File(m).getAbsolutePath();
+           filePath = new File(m).getAbsolutePath();
          } catch (AccessControlException x)
          {
            // usually not allowed to do this in applet
                    .println("jmolBinding: Using local file string from Jmol: "
                            + m);
          }
-         if (mset[0].indexOf("/file:") != -1)
+         if (filePath.indexOf("/file:") != -1)
          {
            // applet path with docroot - discard as format won't match pdbfile
-           mset[0] = m;
+           filePath = m;
          }
+         mset.add(filePath);
          _modelFileNameMap[0] = 0; // filename index for first model is always 0.
        }
        int j = 1;
-       for (int i = 1; i < mset.length; i++)
+       for (int i = 1; i < viewer.ms.mc; i++)
        {
          m = viewer.ms.getModelFileName(i);
-         mset[j] = m;
+         String filePath = m;
          if (m != null)
          {
            try
            {
-             mset[j] = new File(m).getAbsolutePath();
+             filePath = new File(m).getAbsolutePath();
            } catch (AccessControlException x)
            {
              // usually not allowed to do this in applet, so keep raw handle
              // System.err.println("jmolBinding: Using local file string from Jmol: "+m);
            }
          }
-         _modelFileNameMap[j] = i; // record the model index for the filename
-         // skip any additional models in the same file (NMR structures)
-         if ((mset[j] == null ? mset[j] != mset[j - 1]
-                 : (mset[j - 1] == null || !mset[j].equals(mset[j - 1]))))
+         /*
+          * add this model unless it is read from a structure file we have
+          * already seen (example: 2MJW is an NMR structure with 10 models)
+          */
+         if (!mset.contains(filePath))
          {
+           mset.add(filePath);
+           _modelFileNameMap[j] = i; // record the model index for the filename
            j++;
          }
        }
-       modelFileNames = new String[j];
-       System.arraycopy(mset, 0, modelFileNames, 0, j);
+       modelFileNames = mset.toArray(new String[mset.size()]);
      }
      return modelFileNames;
    }
@@@ -1,6 -1,6 +1,6 @@@
  /*
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -101,11 -101,6 +101,6 @@@ public abstract class JalviewChimeraBin
  
    private String lastCommand;
  
-   /*
-    * current set of model filenames loaded
-    */
-   String[] modelFileNames = null;
    String lastHighlightCommand;
  
    /*
@@@ -1,6 -1,6 +1,6 @@@
  /*
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -108,6 -108,7 +108,7 @@@ import java.awt.datatransfer.Clipboard
  import java.awt.datatransfer.DataFlavor;
  import java.awt.datatransfer.StringSelection;
  import java.awt.datatransfer.Transferable;
+ import java.awt.dnd.DnDConstants;
  import java.awt.dnd.DropTargetDragEvent;
  import java.awt.dnd.DropTargetDropEvent;
  import java.awt.dnd.DropTargetEvent;
@@@ -4814,6 -4815,9 +4815,9 @@@ public class AlignFrame extends GAlignF
    @Override
    public void drop(DropTargetDropEvent evt)
    {
+     // JAL-1552 - acceptDrop required before getTransferable call for
+     // Java's Transferable for native dnd
+     evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
      Transferable t = evt.getTransferable();
      java.util.List<String> files = new ArrayList<String>(), protocols = new ArrayList<String>();
  
@@@ -1,6 -1,6 +1,6 @@@
  /*
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -79,6 -79,9 +79,9 @@@ import javax.swing.event.MenuListener
  
  public class AppJmol extends StructureViewerBase
  {
+   // ms to wait for Jmol to load files
+   private static final int JMOL_LOAD_TIMEOUT = 20000;
    private static final String SPACE = " ";
  
    private static final String BACKSLASH = "\"";
      jmb.setColourBySequence(true);
      setSize(400, 400); // probably should be a configurable/dynamic default here
      initMenus();
-     worker = null;
-     {
-       addingStructures = false;
-       worker = new Thread(this);
-       worker.start();
-     }
+     addingStructures = false;
+     worker = new Thread(this);
+     worker.start();
      this.addInternalFrameListener(new InternalFrameAdapter()
      {
        @Override
        scriptWindow.setVisible(false);
      }
  
-     /*
-      * -i for no info logging (less verbose)
-      */
-     jmb.allocateViewer(renderPanel, true, "", null, null, "-i",
+     jmb.allocateViewer(renderPanel, true, "", null, null, "",
              scriptWindow, null);
      // jmb.newJmolPopup("Jmol");
      if (command == null)
      }
  
      // need to wait around until script has finished
-     int waitMax = 5000; // give up after 5 seconds
+     int waitMax = JMOL_LOAD_TIMEOUT;
      int waitFor = 35;
      int waitTotal = 0;
      while (addingStructures ? lastnotify >= jmb.getLoadNotifiesHandled()
        }
        if (waitTotal > waitMax)
        {
-         System.err.println("Timed out waiting for Jmol to load files");
+         System.err
+                 .println("Timed out waiting for Jmol to load files after "
+                         + waitTotal + "ms");
+ //        System.err.println("finished: " + jmb.isFinishedInit()
+ //                + "; loaded: " + Arrays.toString(jmb.getPdbFile())
+ //                + "; files: " + files.toString());
+         jmb.getPdbFile();
          break;
        }
      }
@@@ -1,6 -1,6 +1,6 @@@
  /*
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -660,7 -660,8 +660,8 @@@ public class ChimeraViewFrame extends S
            {
              int pos = filePDBpos.get(num).intValue();
              long startTime = startProgressBar("Chimera "
-                     + MessageManager.getString("status.opening_file"));
+                     + MessageManager.getString("status.opening_file_for")
+                     + " " + pe.getId());
              jmb.openFile(pe);
              jmb.addSequence(pos, jmb.getSequence()[pos]);
              File fl = new File(pe.getFile());
@@@ -1,6 -1,6 +1,6 @@@
  /*
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -941,6 -941,9 +941,9 @@@ public class Desktop extends jalview.jb
    public void drop(DropTargetDropEvent evt)
    {
      boolean success = true;
+     // JAL-1552 - acceptDrop required before getTransferable call for
+     // Java's Transferable for native dnd
+     evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
      Transferable t = evt.getTransferable();
      java.util.List<String> files = new ArrayList<String>();
      java.util.List<String> protocols = new ArrayList<String>();
      {
        // Works on Windows and MacOSX
        Cache.log.debug("Drop handled as javaFileListFlavor");
-       evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
        for (Object file : (List) t
                .getTransferData(DataFlavor.javaFileListFlavor))
        {
        {
          Cache.log.debug("Drop handled as uriListFlavor");
          // This is used by Unix drag system
-         evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
          data = (String) t.getTransferData(uriListFlavor);
        }
        if (data == null)
            {
              Cache.log.debug("Supported transfer dataflavor: "
                      + fl.toString());
-             evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
              Object df = t.getTransferData(fl);
              if (df != null)
              {
@@@ -1,6 -1,6 +1,6 @@@
  /*
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -992,17 -992,16 +992,16 @@@ public class Jalview2XM
              }
            }
  
-           if (entry.getProperty() != null && !entry.getProperty().isEmpty())
+           Enumeration<String> props = entry.getProperties();
+           if (props.hasMoreElements())
            {
              PdbentryItem item = new PdbentryItem();
-             Hashtable properties = entry.getProperty();
-             Enumeration en2 = properties.keys();
-             while (en2.hasMoreElements())
+             while (props.hasMoreElements())
              {
                Property prop = new Property();
-               String key = en2.nextElement().toString();
+               String key = props.nextElement();
                prop.setName(key);
-               prop.setValue(properties.get(key).toString());
+               prop.setValue(entry.getProperty(key).toString());
                item.addProperty(prop);
              }
              pdb.addPdbentryItem(item);
                  entry.setType(PDBEntry.Type.FILE);
                }
              }
-             if (ids[p].getFile() != null)
+             // jprovider is null when executing 'New View'
+             if (ids[p].getFile() != null && jprovider != null)
              {
                if (!pdbloaded.containsKey(ids[p].getFile()))
                {
              }
              if (ids[p].getPdbentryItem() != null)
              {
-               entry.setProperty(new Hashtable());
                for (PdbentryItem item : ids[p].getPdbentryItem())
                {
                  for (Property pr : item.getProperty())
                  {
-                   entry.getProperty().put(pr.getName(), pr.getValue());
+                   entry.setProperty(pr.getName(), pr.getValue());
                  }
                }
              }
@@@ -1,6 -1,6 +1,6 @@@
  /*
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -616,13 -616,14 +616,14 @@@ public class SeqPanel extends JPanel im
        return;
      }
  
-     if (evt.isShiftDown() || evt.isAltDown() || evt.isControlDown())
+     boolean isControlDown = Platform.isControlDown(evt);
+     if (evt.isShiftDown() || isControlDown)
      {
-       if (evt.isAltDown() || evt.isControlDown())
+       editingSeqs = true;
+       if (isControlDown)
        {
          groupEditing = true;
        }
-       editingSeqs = true;
      }
      else
      {
@@@ -1,6 -1,6 +1,6 @@@
  /*
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (2.9.0b1)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -81,6 -81,8 +81,8 @@@ public class StructureChooser extends G
  
    private boolean isValidPBDEntry;
  
+   private boolean cachedPDBExists;
    public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
            AlignmentPanel ap)
    {
      }
  
      // ensure a filter option is in force for search
-     populateFilterComboBox(true);
+     populateFilterComboBox(true, cachedPDBExists);
      Thread discoverPDBStructuresThread = new Thread(new Runnable()
      {
        @Override
                  startTime);
          fetchStructuresMetaData();
          // revise filter options if no results were found
-         populateFilterComboBox(isStructuresDiscovered());
+         populateFilterComboBox(isStructuresDiscovered(), cachedPDBExists);
          updateProgressIndicator(null, startTime);
          mainFrame.setVisible(true);
          updateCurrentView();
          }
        }
      }
+     cachedPDBExists = !entries.isEmpty();
      PDBEntryTableModel tableModelx = new PDBEntryTableModel(entries);
      tbl_local_pdb.setModel(tableModelx);
    }
     * Populates the filter combo-box options dynamically depending on discovered
     * structures
     */
-   protected void populateFilterComboBox(boolean haveData)
+   protected void populateFilterComboBox(boolean haveData,
+           boolean cachedPDBExists)
    {
      /*
       * temporarily suspend the change listener behaviour
              VIEWS_ENTER_ID));
      cmb_filterOption.addItem(new FilterOption("From File", "-",
              VIEWS_FROM_FILE));
-     cmb_filterOption.addItem(new FilterOption("Cached PDB Entries", "-",
-             VIEWS_LOCAL_PDB));
+     FilterOption cachedOption = new FilterOption("Cached PDB Entries", "-",
+             VIEWS_LOCAL_PDB);
+     cmb_filterOption.addItem(cachedOption);
+     if (/*!haveData &&*/cachedPDBExists)
+     {
+       cmb_filterOption.setSelectedItem(cachedOption);
+     }
  
      cmb_filterOption.addItemListener(this);
    }
@@@ -1,6 -1,6 +1,6 @@@
  /*
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -136,14 -136,16 +136,16 @@@ public class StructureViewe
    protected JalviewStructureDisplayI viewStructures(ViewerType viewerType,
            PDBEntry[] pdbs, SequenceI[][] seqsForPdbs, AlignmentPanel ap)
    {
+     PDBEntry[] pdbsForFile = getUniquePdbFiles(pdbs);
      JalviewStructureDisplayI sview = null;
      if (viewerType.equals(ViewerType.JMOL))
      {
-       sview = new AppJmol(ap, pdbs, ap.av.collateForPDB(pdbs));
+       sview = new AppJmol(ap, pdbsForFile, ap.av.collateForPDB(pdbsForFile));
      }
      else if (viewerType.equals(ViewerType.CHIMERA))
      {
-       sview = new ChimeraViewFrame(pdbs, ap.av.collateForPDB(pdbs), ap);
+       sview = new ChimeraViewFrame(pdbsForFile,
+               ap.av.collateForPDB(pdbsForFile), ap);
      }
      else
      {
      return sview;
    }
  
+   /**
+    * Convert the array of PDBEntry into an array with no filename repeated
+    * 
+    * @param pdbs
+    * @return
+    */
+   static PDBEntry[] getUniquePdbFiles(PDBEntry[] pdbs)
+   {
+     if (pdbs == null)
+     {
+       return null;
+     }
+     List<PDBEntry> uniques = new ArrayList<PDBEntry>();
+     List<String> filesSeen = new ArrayList<String>();
+     for (PDBEntry entry : pdbs)
+     {
+       String file = entry.getFile();
+       if (file == null)
+       {
+         uniques.add(entry);
+       }
+       else if (!filesSeen.contains(file))
+       {
+         uniques.add(entry);
+         filesSeen.add(file);
+       }
+     }
+     return uniques.toArray(new PDBEntry[uniques.size()]);
+   }
    protected JalviewStructureDisplayI viewStructures(ViewerType viewerType,
            PDBEntry pdb, SequenceI[] seqsForPdb, AlignmentPanel ap)
    {
@@@ -1,6 -1,6 +1,6 @@@
  /*
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -390,6 -390,9 +390,9 @@@ public class StructureSelectionManage
        {
          registerPDBFile(pdb.getId().trim(), pdbFile);
        }
+       // if PDBId is unavailable then skip SIFTS mapping execution path
+       isMapUsingSIFTs = pdb.isPPDBIdAvailable();
      } catch (Exception ex)
      {
        ex.printStackTrace();
@@@ -1,6 -1,6 +1,6 @@@
  /*
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -51,6 -51,10 +51,10 @@@ public abstract class AAStructureBindin
  
    private StructureSelectionManager ssm;
  
+   /*
+    * distinct PDB entries (pdb files) associated
+    * with sequences
+    */
    private PDBEntry[] pdbEntry;
  
    /*
    private boolean finishedInit = false;
  
    /**
+    * current set of model filenames loaded in the Jmol instance
+    */
+   protected String[] modelFileNames = null;
+   /**
     * Data bean class to simplify parameterisation in superposeStructures
     */
    protected class SuperposeData
      // TODO: give a more informative title when multiple structures are
      // displayed.
      StringBuilder title = new StringBuilder(64);
-     final PDBEntry pdbEntry = getPdbEntry(0);
+     final PDBEntry pdbe = getPdbEntry(0);
      title.append(viewerName + " view for " + getSequence()[0][0].getName()
-             + ":" + pdbEntry.getId());
+             + ":" + pdbe.getId());
  
      if (verbose)
      {
-       if (pdbEntry.getProperty() != null)
+       String method = (String) pdbe.getProperty("method");
+       if (method != null)
        {
-         if (pdbEntry.getProperty().get("method") != null)
-         {
-           title.append(" Method: ");
-           title.append(pdbEntry.getProperty().get("method"));
-         }
-         if (pdbEntry.getProperty().get("chains") != null)
-         {
-           title.append(" Chain:");
-           title.append(pdbEntry.getProperty().get("chains"));
-         }
+         title.append(" Method: ").append(method);
+       }
+       String chain = (String) pdbe.getProperty("chains");
+       if (chain != null)
+       {
+         title.append(" Chain:").append(chain);
        }
      }
      return title.toString();
    {
      int refStructure = -1;
      String[] files = getPdbFile();
+     if (files == null)
+     {
+       return -1;
+     }
      for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
      {
        StructureMapping[] mappings = getSsm().getMapping(files[pdbfnum]);
              }
              structures[pdbfnum].pdbId = mapping.getPdbId();
              structures[pdbfnum].isRna = theSequence.getRNA() != null;
-             // move on to next pdb file
+             /*
+              * move on to next pdb file (ignore sequences for other chains
+              * for the same structure)
+              */
              s = seqCountForPdbFile;
              break;
            }
@@@ -1,6 -1,6 +1,6 @@@
  /*
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -29,7 -29,6 +29,6 @@@ import java.util.ArrayList
  import java.util.Arrays;
  import java.util.HashMap;
  import java.util.HashSet;
- import java.util.Hashtable;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
@@@ -508,9 -507,7 +507,7 @@@ public class DBRefUtil
            PDBEntry pdbr = new PDBEntry();
            pdbr.setId(pdbid);
            pdbr.setType(PDBEntry.Type.PDB);
-           pdbr.setProperty(new Hashtable());
            pdbr.setChainCode(chaincode);
-           // pdbr.getProperty().put("CHAIN", chaincode);
            seq.addPDBId(pdbr);
          }
          else
@@@ -1,6 -1,6 +1,6 @@@
  /*
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -612,7 -612,7 +612,7 @@@ public abstract class AlignmentViewpor
      boolean recalc = false;
      if (cs != null)
      {
-       cs.setConservationApplied(recalc = getConservationSelected());
+       recalc = getConservationSelected();
        if (getAbovePIDThreshold() || cs instanceof PIDColourScheme
                || cs instanceof Blosum62ColourScheme)
        {
          cs.setConsensus(hconsensus);
          cs.setConservation(hconservation);
        }
+       cs.setConservationApplied(getConservationSelected());
        cs.alignmentChanged(alignment, hiddenRepSequences);
      }
      if (getColourAppliesToAllGroups())
@@@ -1,6 -1,6 +1,6 @@@
  /*
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -102,8 -102,13 +102,13 @@@ public abstract class EmblXmlSource ext
        }
      }
  
+     /*
+      * invalid accession gets a reply with no <entry> elements, text content of
+      * EmbFile reads something like (e.g.) this ungrammatical phrase
+      * Entry: <acc> display type is either not supported or entry is not found.
+      */
      List<SequenceI> peptides = new ArrayList<SequenceI>();
-     if (efile != null)
+     if (efile != null && efile.getEntries() != null)
      {
        for (EmblEntry entry : efile.getEntries())
        {
@@@ -1,6 -1,6 +1,6 @@@
  /*
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -226,8 -226,7 +226,7 @@@ public class Uniprot extends DbSourcePr
        if ("EMBL".equals(pdb.getType()))
        {
          // look for a CDS reference and add it, too.
-         String cdsId = (String) pdb.getProperty()
-                 .get("protein sequence ID");
+         String cdsId = (String) pdb.getProperty("protein sequence ID");
          if (cdsId != null && cdsId.trim().length() > 0)
          {
            // remove version
          * <property type="gene ID" value="ENSG00000158828"/>
          * </dbReference> 
           */
-         String cdsId = (String) pdb.getProperty()
-                 .get("protein sequence ID");
+         String cdsId = (String) pdb.getProperty("protein sequence ID");
          if (cdsId != null && cdsId.trim().length() > 0)
          {
            dbr = new DBRefEntry(DBRefSource.ENSEMBL, DBRefSource.UNIPROT
@@@ -1,6 -1,6 +1,6 @@@
  /*
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -39,6 -39,8 +39,8 @@@ import jalview.datamodel.Sequence
  import jalview.datamodel.SequenceI;
  import jalview.io.FileLoader;
  import jalview.io.FormatAdapter;
+ import jalview.schemes.ColourSchemeI;
+ import jalview.schemes.PIDColourScheme;
  import jalview.structure.StructureSelectionManager;
  import jalview.util.MapList;
  
@@@ -329,4 -331,20 +331,20 @@@ public class AlignViewportTes
      assertNotNull("Quality in column 1 is null", annotations[0]);
      assertTrue("No quality value in column 1", annotations[0].value > 10f);
    }
+   @Test(groups = { "Functional" })
+   public void testSetGlobalColourScheme()
+   {
+     /*
+      * test for JAL-2283 don't inadvertently turn on colour by conservation
+      */
+     Cache.applicationProperties.setProperty("DEFAULT_COLOUR_PROT", "NONE");
+     Cache.applicationProperties.setProperty("SHOW_CONSERVATION",
+             Boolean.TRUE.toString());
+     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
+             "examples/uniref50.fa", FormatAdapter.FILE);
+     ColourSchemeI cs = new PIDColourScheme();
+     af.getViewport().setGlobalColourScheme(cs);
+     assertFalse(cs.conservationApplied());
+   }
  }
@@@ -1,6 -1,6 +1,6 @@@
  /*
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -28,6 -28,7 +28,7 @@@ import jalview.datamodel.DBRefSource
  import jalview.datamodel.PDBEntry;
  import jalview.datamodel.Sequence;
  import jalview.datamodel.SequenceI;
+ import jalview.jbgui.GStructureChooser.FilterOption;
  
  import java.util.Vector;
  
@@@ -109,15 -110,21 +110,21 @@@ public class StructureChooserTes
    {
      SequenceI[] selectedSeqs = new SequenceI[] { seq };
      StructureChooser sc = new StructureChooser(selectedSeqs, seq, null);
-     sc.populateFilterComboBox(false);
+     sc.populateFilterComboBox(false, false);
      int optionsSize = sc.getCmbFilterOption().getItemCount();
      assertEquals(3, optionsSize); // if structures are not discovered then don't
                                    // populate filter options
  
-     sc.populateFilterComboBox(true);
+     sc.populateFilterComboBox(true, false);
      optionsSize = sc.getCmbFilterOption().getItemCount();
      assertTrue(optionsSize > 3); // if structures are found, filter options
                                   // should be populated
+     sc.populateFilterComboBox(true, true);
+     assertTrue(sc.getCmbFilterOption().getSelectedItem() != null);
+     FilterOption filterOpt = (FilterOption) sc.getCmbFilterOption()
+             .getSelectedItem();
+     assertEquals("Cached PDB Entries", filterOpt.getName());
    }
  
    @Test(groups = { "Functional" })
@@@ -1,6 -1,6 +1,6 @@@
  /*
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -49,26 -49,36 +49,36 @@@ import org.testng.annotations.Test
   */
  public class AAStructureBindingModelTest
  {
+   /*
+    * Scenario: Jalview has 4 sequences, corresponding to 1YCS (chains A and B), 3A6S|B, 1OOT|A
+    */
    private static final String PDB_1 = "HEADER    COMPLEX (ANTI-ONCOGENE/ANKYRIN REPEATS) 30-SEP-96   1YCS              \n"
            + "ATOM      2  CA  VAL A  97      24.134   4.926  45.821  1.00 47.43           C  \n"
            + "ATOM      9  CA  PRO A  98      25.135   8.584  46.217  1.00 41.60           C  \n"
            + "ATOM     16  CA  SER A  99      28.243   9.596  44.271  1.00 39.63           C  \n"
            + "ATOM     22  CA  GLN A 100      31.488  10.133  46.156  1.00 35.60           C  \n"
-           + "ATOM     31  CA  LYS A 101      33.323  11.587  43.115  1.00 41.69           C  \n";
+           // artificial jump in residue numbering to prove it is correctly
+           // mapped:
+           + "ATOM     31  CA  LYS A 102      33.323  11.587  43.115  1.00 41.69           C  \n"
+           + "ATOM   1857  CA  GLU B 374       9.193 -16.005  95.870  1.00 54.22           C  \n"
+           + "ATOM   1866  CA  ILE B 375       7.101 -14.921  92.847  1.00 46.82           C  \n"
+           + "ATOM   1874  CA  VAL B 376      10.251 -13.625  91.155  1.00 47.80           C  \n"
+           + "ATOM   1881  CA  LYS B 377      11.767 -17.068  91.763  1.00 50.21           C  \n"
+           + "ATOM   1890  CA  PHE B 378       8.665 -18.948  90.632  1.00 44.85           C  \n";
  
    private static final String PDB_2 = "HEADER    HYDROLASE                               09-SEP-09   3A6S              \n"
-           + "ATOM      2  CA  MET A   1      15.366 -11.648  24.854  1.00 32.05           C  \n"
-           + "ATOM     10  CA  LYS A   2      16.846  -9.215  22.340  1.00 25.68           C  \n"
-           + "ATOM     19  CA  LYS A   3      15.412  -6.335  20.343  1.00 19.42           C  \n"
-           + "ATOM     28  CA  LEU A   4      15.629  -5.719  16.616  1.00 15.49           C  \n"
-           + "ATOM     36  CA  GLN A   5      14.412  -2.295  15.567  1.00 12.19           C  \n";
+           + "ATOM      2  CA  MET B   1      15.366 -11.648  24.854  1.00 32.05           C  \n"
+           + "ATOM     10  CA  LYS B   2      16.846  -9.215  22.340  1.00 25.68           C  \n"
+           + "ATOM     19  CA  LYS B   3      15.412  -6.335  20.343  1.00 19.42           C  \n"
+           + "ATOM     28  CA  LEU B   4      15.629  -5.719  16.616  1.00 15.49           C  \n"
+           + "ATOM     36  CA  GLN B   5      14.412  -2.295  15.567  1.00 12.19           C  \n";
  
    private static final String PDB_3 = "HEADER    STRUCTURAL GENOMICS                     04-MAR-03   1OOT              \n"
-           + "ATOM      2  CA  SER A   1      29.427   3.330  -6.578  1.00 32.50           C  \n"
-           + "ATOM      8  CA  PRO A   2      29.975   3.340  -2.797  1.00 17.62           C  \n"
-           + "ATOM     16  CA ALYS A   3      26.958   3.024  -0.410  0.50  8.78           C  \n"
-           + "ATOM     33  CA  ALA A   4      26.790   4.320   3.172  1.00 11.98           C  \n"
-           + "ATOM     39  CA AVAL A   5      24.424   3.853   6.106  0.50 13.83           C  \n";
+           + "ATOM      2  CA  SER A   7      29.427   3.330  -6.578  1.00 32.50           C  \n"
+           + "ATOM      8  CA  PRO A   8      29.975   3.340  -2.797  1.00 17.62           C  \n"
+           + "ATOM     16  CA ALYS A   9      26.958   3.024  -0.410  0.50  8.78           C  \n"
+           + "ATOM     33  CA  ALA A  10      26.790   4.320   3.172  1.00 11.98           C  \n"
+           + "ATOM     39  CA AVAL A  12      24.424   3.853   6.106  0.50 13.83           C  \n";
  
    AAStructureBindingModel testee;
  
    @BeforeMethod(alwaysRun = true)
    public void setUp()
    {
-     SequenceI seq1 = new Sequence("1YCS", "-VPSQK");
+     SequenceI seq1a = new Sequence("1YCS|A", "-VPSQK");
+     SequenceI seq1b = new Sequence("1YCS|B", "EIVKF-");
      SequenceI seq2 = new Sequence("3A6S", "MK-KLQ");
      SequenceI seq3 = new Sequence("1OOT", "SPK-AV");
-     al = new Alignment(new SequenceI[] { seq1, seq2, seq3 });
+     al = new Alignment(new SequenceI[] { seq1a, seq1b, seq2, seq3 });
      al.setDataset(null);
  
+     /*
+      * give pdb files the name generated by Jalview for PASTE source
+      */
      PDBEntry[] pdbFiles = new PDBEntry[3];
-     pdbFiles[0] = new PDBEntry("1YCS", "A", Type.PDB, "1YCS.pdb");
-     pdbFiles[1] = new PDBEntry("3A6S", "B", Type.PDB, "3A6S.pdb");
-     pdbFiles[2] = new PDBEntry("1OOT", "A", Type.PDB, "1OOT.pdb");
+     pdbFiles[0] = new PDBEntry("1YCS", "A", Type.PDB, "INLINE1YCS");
+     pdbFiles[1] = new PDBEntry("3A6S", "B", Type.PDB, "INLINE3A6S");
+     pdbFiles[2] = new PDBEntry("1OOT", "A", Type.PDB, "INLINE1OOT");
      String[][] chains = new String[3][];
      SequenceI[][] seqs = new SequenceI[3][];
-     seqs[0] = new SequenceI[] { seq1 };
+     seqs[0] = new SequenceI[] { seq1a, seq1b };
      seqs[1] = new SequenceI[] { seq2 };
      seqs[2] = new SequenceI[] { seq3 };
      StructureSelectionManager ssm = new StructureSelectionManager();
  
-     ssm.setMapping(new SequenceI[] { seq1 }, null, PDB_1,
+     ssm.setMapping(new SequenceI[] { seq1a, seq1b }, null, PDB_1,
              AppletFormatAdapter.PASTE);
      ssm.setMapping(new SequenceI[] { seq2 }, null, PDB_2,
              AppletFormatAdapter.PASTE);
        @Override
        public String[] getPdbFile()
        {
-         /*
-          * fudge 'filenames' to match those generated when PDBFile parses PASTE
-          * data
-          */
          return new String[] { "INLINE1YCS", "INLINE3A6S", "INLINE1OOT" };
        }
  
    @Test(groups = { "Functional" })
    public void testFindSuperposableResidues()
    {
-     SuperposeData[] structs = new SuperposeData[al.getHeight()];
+     /*
+      * create a data bean to hold data per structure file
+      */
+     SuperposeData[] structs = new SuperposeData[testee.getPdbFile().length];
      for (int i = 0; i < structs.length; i++)
      {
        structs[i] = testee.new SuperposeData(al.getWidth());
       */
      assertFalse(matched[0]); // gap in first sequence
      assertTrue(matched[1]);
-     assertFalse(matched[2]); // gap in second sequence
-     assertFalse(matched[3]); // gap in third sequence
+     assertFalse(matched[2]); // gap in third sequence
+     assertFalse(matched[3]); // gap in fourth sequence
      assertTrue(matched[4]);
-     assertTrue(matched[5]);
+     assertTrue(matched[5]); // gap in second sequence
+     assertEquals("1YCS", structs[0].pdbId);
+     assertEquals("3A6S", structs[1].pdbId);
+     assertEquals("1OOT", structs[2].pdbId);
+     assertEquals("A", structs[0].chain); // ? struct has chains A _and_ B
+     assertEquals("B", structs[1].chain);
+     assertEquals("A", structs[2].chain);
+     // the 0's for unsuperposable positions propagate down the columns:
+     assertEquals("[0, 97, 98, 99, 100, 102]",
+             Arrays.toString(structs[0].pdbResNo));
+     assertEquals("[0, 2, 0, 3, 4, 5]", Arrays.toString(structs[1].pdbResNo));
+     assertEquals("[0, 8, 0, 0, 10, 12]",
+             Arrays.toString(structs[2].pdbResNo));
    }
  
    @Test(groups = { "Functional" })
@@@ -1,6 -1,6 +1,6 @@@
  /*
 - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 - * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
 + * Copyright (C) 2015 The Jalview Authors
   * 
   * This file is part of Jalview.
   * 
@@@ -21,6 -21,7 +21,7 @@@
  package jalview.ws.dbsources;
  
  import static org.testng.AssertJUnit.assertEquals;
+ import static org.testng.AssertJUnit.assertFalse;
  import static org.testng.AssertJUnit.assertNotNull;
  import static org.testng.AssertJUnit.assertNull;
  
@@@ -117,25 -118,21 +118,21 @@@ public class UniprotTes
      PDBEntry xref = xrefs.get(0);
      assertEquals("2FSQ", xref.getId());
      assertEquals("PDB", xref.getType());
-     assertEquals(2, xref.getProperty().size());
-     assertEquals("X-ray", xref.getProperty().get("method"));
-     assertEquals("1.40", xref.getProperty().get("resolution"));
+     assertEquals("X-ray", xref.getProperty("method"));
+     assertEquals("1.40", xref.getProperty("resolution"));
  
      xref = xrefs.get(1);
      assertEquals("2FSR", xref.getId());
      assertEquals("PDBsum", xref.getType());
-     assertNull(xref.getProperty());
+     assertFalse(xref.getProperties().hasMoreElements());
  
      xref = xrefs.get(2);
      assertEquals("AE007869", xref.getId());
      assertEquals("EMBL", xref.getType());
-     assertNotNull(xref.getProperty());
      assertEquals("AAK85932.1",
-             (String) xref.getProperty().get("protein sequence ID"));
+  xref.getProperty("protein sequence ID"));
      assertEquals("Genomic_DNA",
-             (String) xref.getProperty().get("molecule type"));
-     assertEquals(2, xref.getProperty().size());
+  xref.getProperty("molecule type"));
    }
  
    @Test(groups = { "Functional" })