Merge branch 'features/JAL-2465_No-mapping_Jmol-structures-loaded-via-url' into develop
authorJim Procter <jprocter@issues.jalview.org>
Mon, 29 May 2017 13:19:41 +0000 (14:19 +0100)
committerJim Procter <jprocter@issues.jalview.org>
Mon, 29 May 2017 13:19:41 +0000 (14:19 +0100)
19 files changed:
src/MCview/AppletPDBCanvas.java
src/MCview/PDBCanvas.java
src/jalview/ext/jmol/JalviewJmolBinding.java
src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java
src/jalview/gui/AppJmol.java
src/jalview/gui/AppVarnaBinding.java
src/jalview/gui/ChimeraViewFrame.java
src/jalview/gui/StructureViewerBase.java
src/jalview/io/FileLoader.java
src/jalview/io/StructureFile.java
src/jalview/javascript/MouseOverStructureListener.java
src/jalview/structure/StructureListener.java
src/jalview/structure/StructureSelectionManager.java
src/jalview/structures/models/AAStructureBindingModel.java
src/jalview/ws/utils/UrlDownloadClient.java
test/jalview/ext/jmol/JmolViewerTest.java
test/jalview/ext/rbvi/chimera/JalviewChimeraView.java
test/jalview/io/FileLoaderTest.java [new file with mode: 0644]
test/jalview/structures/models/AAStructureBindingModelTest.java

index c454203..39111c3 100644 (file)
@@ -1119,7 +1119,7 @@ public class AppletPDBCanvas extends Panel implements MouseListener,
   // ////////////////////////////////
   // /StructureListener
   @Override
-  public String[] getPdbFile()
+  public String[] getStructureFiles()
   {
     return new String[] { pdbentry.getFile() };
   }
index ff1211a..83642cc 100644 (file)
@@ -1075,7 +1075,7 @@ public class PDBCanvas extends JPanel implements MouseListener,
   // ////////////////////////////////
   // /StructureListener
   @Override
-  public String[] getPdbFile()
+  public String[] getStructureFiles()
   {
     return new String[] { pdbentry.getFile() };
   }
index 00fd679..5de554b 100644 (file)
@@ -164,7 +164,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
   public void closeViewer()
   {
     // remove listeners for all structures in viewer
-    getSsm().removeStructureViewerListener(this, this.getPdbFile());
+    getSsm().removeStructureViewerListener(this, this.getStructureFiles());
     viewer.dispose();
     lastCommand = null;
     viewer = null;
@@ -250,7 +250,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
      * get the distinct structure files modelled
      * (a file with multiple chains may map to multiple sequences)
      */
-    String[] files = getPdbFile();
+    String[] files = getStructureFiles();
     if (!waitForFileLoad(files))
     {
       return null;
@@ -577,7 +577,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
 
   private int getModelNum(String modelFileName)
   {
-    String[] mfn = getPdbFile();
+    String[] mfn = getStructureFiles();
     if (mfn == null)
     {
       return -1;
@@ -601,8 +601,8 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
 
   // ////////////////////////////////
   // /StructureListener
-  @Override
-  public synchronized String[] getPdbFile()
+  // @Override
+  public synchronized String[] getPdbFilex()
   {
     if (viewer == null)
     {
@@ -667,6 +667,32 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     return modelFileNames;
   }
 
+  @Override
+  public synchronized String[] getStructureFiles()
+  {
+    List<String> mset = new ArrayList<String>();
+    if (viewer == null)
+    {
+      return new String[0];
+    }
+
+    if (modelFileNames == null)
+    {
+      int modelCount = viewer.ms.mc;
+      String filePath = null;
+      for (int i = 0; i < modelCount; ++i)
+      {
+        filePath = viewer.ms.getModelFileName(i);
+        if (!mset.contains(filePath))
+        {
+          mset.add(filePath);
+        }
+      }
+      modelFileNames = mset.toArray(new String[mset.size()]);
+    }
+
+    return modelFileNames;
+  }
   /**
    * map from string to applet
    */
@@ -1035,7 +1061,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     chainNames = new ArrayList<String>();
     chainFile = new Hashtable<String, String>();
     boolean notifyLoaded = false;
-    String[] modelfilenames = getPdbFile();
+    String[] modelfilenames = getStructureFiles();
     // first check if we've lost any structures
     if (oldmodels != null && oldmodels.length > 0)
     {
index 870c4fe..b954677 100644 (file)
@@ -289,7 +289,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
    */
   public void closeViewer(boolean closeChimera)
   {
-    getSsm().removeStructureViewerListener(this, this.getPdbFile());
+    getSsm().removeStructureViewerListener(this, this.getStructureFiles());
     if (closeChimera)
     {
       viewer.exitChimera();
@@ -340,7 +340,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
           int[] _refStructure, HiddenColumns[] _hiddenCols)
   {
     StringBuilder allComs = new StringBuilder(128);
-    String[] files = getPdbFile();
+    String[] files = getStructureFiles();
 
     if (!waitForFileLoad(files))
     {
@@ -577,7 +577,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
      * to the Chimera command 'list models type molecule', see
      * ChimeraManager.getModelList().
      */
-    List<ChimeraModel> maps = chimeraMaps.get(getPdbFile()[pdbfnum]);
+    List<ChimeraModel> maps = chimeraMaps.get(getStructureFiles()[pdbfnum]);
     boolean hasSubModels = maps != null && maps.size() > 1;
     return "#" + String.valueOf(pdbfnum) + (hasSubModels ? ".1" : "");
   }
@@ -745,7 +745,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
   // ////////////////////////////////
   // /StructureListener
   @Override
-  public synchronized String[] getPdbFile()
+  public synchronized String[] getStructureFiles()
   {
     if (viewer == null)
     {
@@ -1100,7 +1100,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
     // TODO refactor as required to pull up to an interface
     AlignmentI alignment = avp.getAlignment();
 
-    String[] files = getPdbFile();
+    String[] files = getStructureFiles();
     if (files == null)
     {
       return 0;
index 5d23f49..68a847e 100644 (file)
@@ -410,8 +410,8 @@ public class AppJmol extends StructureViewerBase
     int waitFor = 35;
     int waitTotal = 0;
     while (addingStructures ? lastnotify >= jmb.getLoadNotifiesHandled()
-            : !(jmb.isFinishedInit() && jmb.getPdbFile() != null && jmb
-                    .getPdbFile().length == files.size()))
+            : !(jmb.isFinishedInit() && jmb.getStructureFiles() != null && jmb
+                    .getStructureFiles().length == files.size()))
     {
       try
       {
@@ -429,7 +429,7 @@ public class AppJmol extends StructureViewerBase
 //        System.err.println("finished: " + jmb.isFinishedInit()
 //                + "; loaded: " + Arrays.toString(jmb.getPdbFile())
 //                + "; files: " + files.toString());
-        jmb.getPdbFile();
+        jmb.getStructureFiles();
         break;
       }
     }
@@ -494,7 +494,7 @@ public class AppJmol extends StructureViewerBase
     String pdbid = "";
     try
     {
-      String[] filesInViewer = jmb.getPdbFile();
+      String[] filesInViewer = jmb.getStructureFiles();
       // TODO: replace with reference fetching/transfer code (validate PDBentry
       // as a DBRef?)
       Pdb pdbclient = new Pdb();
index 8ab1e61..829fc3e 100644 (file)
@@ -384,7 +384,7 @@ public class AppVarnaBinding extends JalviewVarnaBinding
   }
 
   @Override
-  public String[] getPdbFile()
+  public String[] getStructureFiles()
   {
     return null;
   }
index ab6f6c8..eadc2ad 100644 (file)
@@ -490,7 +490,7 @@ public class ChimeraViewFrame extends StructureViewerBase
     StructureFile pdb = null;
     try
     {
-      String[] curfiles = jmb.getPdbFile(); // files currently in viewer
+      String[] curfiles = jmb.getStructureFiles(); // files currently in viewer
       // TODO: replace with reference fetching/transfer code (validate PDBentry
       // as a DBRef?)
       for (int pi = 0; pi < jmb.getPdbCount(); pi++)
index e37627d..e73ce07 100644 (file)
@@ -919,7 +919,7 @@ public abstract class StructureViewerBase extends GStructureViewer
       {
         // TODO: cope with multiple PDB files in view
         in = new BufferedReader(
-                new FileReader(getBinding().getPdbFile()[0]));
+                new FileReader(getBinding().getStructureFiles()[0]));
         File outFile = chooser.getSelectedFile();
   
         PrintWriter out = new PrintWriter(new FileOutputStream(outFile));
@@ -991,7 +991,7 @@ public abstract class StructureViewerBase extends GStructureViewer
      * enable 'Superpose with' if more than one mapped structure
      */
     viewSelectionMenu.setEnabled(false);
-    if (getBinding().getPdbFile().length > 1
+    if (getBinding().getStructureFiles().length > 1
             && getBinding().getSequence().length > 1)
     {
       viewSelectionMenu.setEnabled(true);
index 7c6d181..9d5fd93 100755 (executable)
@@ -39,7 +39,10 @@ import jalview.json.binding.biojson.v1.ColourSchemeMapper;
 import jalview.schemes.ColourSchemeI;
 import jalview.structure.StructureSelectionManager;
 import jalview.util.MessageManager;
+import jalview.ws.utils.UrlDownloadClient;
 
+import java.io.File;
+import java.io.IOException;
 import java.util.StringTokenizer;
 import java.util.Vector;
 
@@ -205,6 +208,12 @@ public class FileLoader implements Runnable
       // refer to it as.
       return;
     }
+    if (file != null
+            && file.indexOf(System.getProperty("java.io.tmpdir")) > -1)
+    {
+      // ignore files loaded from the system's temporary directory
+      return;
+    }
     String type = protocol == DataSourceType.FILE ? "RECENT_FILE"
             : "RECENT_URL";
 
@@ -325,9 +334,27 @@ public class FileLoader implements Runnable
 
             // open a new source and read from it
             FormatAdapter fa = new FormatAdapter();
-            al = fa.readFile(file, protocol, format);
-            source = fa.getAlignFile(); // keep reference for later if
-                                        // necessary.
+            boolean downloadStructureFile = format.isStructureFile()
+                    && protocol.equals(DataSourceType.URL);
+            if (downloadStructureFile)
+            {
+              String structExt = format.getExtensions().split(",")[0];
+              String urlLeafName = file.substring(file.lastIndexOf(System
+                      .getProperty("file.separator")), file
+                      .lastIndexOf("."));
+              String tempStructureFileStr = createNamedJvTempFile(
+                      urlLeafName, structExt);
+              UrlDownloadClient.download(file, tempStructureFileStr);
+              al = fa.readFile(tempStructureFileStr, DataSourceType.FILE,
+                      format);
+              source = fa.getAlignFile();
+            }
+            else
+            {
+              al = fa.readFile(file, protocol, format);
+              source = fa.getAlignFile(); // keep reference for later if
+                                          // necessary.
+            }
           }
         } catch (java.io.IOException ex)
         {
@@ -556,6 +583,29 @@ public class FileLoader implements Runnable
 
   }
 
+  /**
+   * This method creates the file -
+   * {tmpdir}/jalview/{current_timestamp}/fileName.exetnsion using the supplied
+   * file name and extension
+   * 
+   * @param fileName
+   *          the name of the temp file to be created
+   * @param extension
+   *          the extension of the temp file to be created
+   * @return
+   */
+  private static String createNamedJvTempFile(String fileName,
+          String extension) throws IOException
+  {
+    String seprator = System.getProperty("file.separator");
+    String jvTempDir = System.getProperty("java.io.tmpdir") + "jalview"
+            + seprator + System.currentTimeMillis();
+    File tempStructFile = new File(jvTempDir + seprator + fileName + "."
+            + extension);
+    tempStructFile.mkdirs();
+    return tempStructFile.toString();
+  }
+
   /*
    * (non-Javadoc)
    * 
index 7fe17c8..ab220f0 100644 (file)
@@ -406,7 +406,8 @@ public abstract class StructureFile extends AlignFile
    * make a friendly ID string.
    * 
    * @param dataName
-   * @return truncated dataName to after last '/'
+   * @return truncated dataName to after last '/' and pruned .extension if
+   *         present
    */
   protected String safeName(String dataName)
   {
@@ -415,6 +416,9 @@ public abstract class StructureFile extends AlignFile
     {
       dataName = dataName.substring(p + 1);
     }
+    if(dataName.indexOf(".") > -1){
+      dataName = dataName.substring(0, dataName.lastIndexOf("."));
+    }
     return dataName;
   }
 
index 7580222..c390b17 100644 (file)
@@ -126,7 +126,7 @@ public class MouseOverStructureListener extends JSFunctionExec implements
   }
 
   @Override
-  public String[] getPdbFile()
+  public String[] getStructureFiles()
   {
     return modelSet;
   }
index e5c5d04..9fde3f1 100644 (file)
@@ -31,7 +31,7 @@ public interface StructureListener
    * handles messages for, or null if generic listener (only used by
    * removeListener method)
    */
-  public String[] getPdbFile();
+  public String[] getStructureFiles();
 
   /**
    * Called by StructureSelectionManager to inform viewer to highlight given
index 72da7ae..db0b47e 100644 (file)
@@ -36,6 +36,7 @@ import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.SequenceI;
 import jalview.ext.jmol.JmolParser;
 import jalview.gui.IProgressIndicator;
+import jalview.io.AppletFormatAdapter;
 import jalview.io.DataSourceType;
 import jalview.io.StructureFile;
 import jalview.util.MappingUtils;
@@ -385,6 +386,7 @@ public class StructureSelectionManager
     boolean isMapUsingSIFTs = SiftsSettings.isMapWithSifts();
     try
     {
+      sourceType = AppletFormatAdapter.checkProtocol(pdbFile);
       pdb = new JmolParser(pdbFile, sourceType);
 
       if (pdb.getId() != null && pdb.getId().trim().length() > 0
@@ -740,7 +742,7 @@ public class StructureSelectionManager
       if (listeners.elementAt(i) instanceof StructureListener)
       {
         sl = (StructureListener) listeners.elementAt(i);
-        for (String pdbfile : sl.getPdbFile())
+        for (String pdbfile : sl.getStructureFiles())
         {
           pdbs.remove(pdbfile);
         }
index b336e45..1637631 100644 (file)
@@ -532,7 +532,7 @@ public abstract class AAStructureBindingModel extends
           BitSet matched, SuperposeData[] structures)
   {
     int refStructure = -1;
-    String[] files = getPdbFile();
+    String[] files = getStructureFiles();
     if (files == null)
     {
       return -1;
@@ -756,7 +756,7 @@ public abstract class AAStructureBindingModel extends
     {
       return;
     }
-    String[] files = getPdbFile();
+    String[] files = getStructureFiles();
   
     SequenceRenderer sr = getSequenceRenderer(alignmentv);
   
index 86e3f76..dcd861a 100644 (file)
@@ -47,7 +47,8 @@ public class UrlDownloadClient
    *          the name of file to save the URLs to
    * @throws IOException
    */
-  public void download(String urlstring, String outfile) throws IOException
+  public static void download(String urlstring, String outfile)
+          throws IOException
   {
     FileOutputStream fos = null;
     ReadableByteChannel rbc = null;
index 995b099..4a59044 100644 (file)
@@ -33,6 +33,7 @@ import jalview.gui.StructureViewer;
 import jalview.gui.StructureViewer.ViewerType;
 import jalview.io.DataSourceType;
 
+import org.testng.Assert;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
@@ -115,4 +116,57 @@ public class JmolViewerTest
       }
     }
   }
+
+  @Test(groups = { "Functional", "Network" })
+  public void testStructureLoadingViaURL()
+  {
+    Cache.setProperty(Preferences.STRUCTURE_DISPLAY, ViewerType.JMOL.name());
+    String inFile = "http://www.jalview.org/builds/develop/examples/3W5V.pdb";
+    AlignFrame af = new jalview.io.FileLoader().LoadFileWaitTillLoaded(
+            inFile, DataSourceType.URL);
+    assertTrue("Didn't read input file " + inFile, af != null);
+    for (SequenceI sq : af.getViewport().getAlignment().getSequences())
+    {
+      SequenceI dsq = sq.getDatasetSequence();
+      while (dsq.getDatasetSequence() != null)
+      {
+        dsq = dsq.getDatasetSequence();
+      }
+      if (dsq.getAllPDBEntries() != null
+              && dsq.getAllPDBEntries().size() > 0)
+      {
+        for (int q = 0; q < dsq.getAllPDBEntries().size(); q++)
+        {
+          final StructureViewer structureViewer = new StructureViewer(af
+                  .getViewport().getStructureSelectionManager());
+          structureViewer.setViewerType(ViewerType.JMOL);
+          JalviewStructureDisplayI jmolViewer = structureViewer
+                  .viewStructures(dsq.getAllPDBEntries().elementAt(q),
+                          new SequenceI[] { sq }, af.getCurrentView()
+                                  .getAlignPanel());
+          /*
+          * Wait for viewer load thread to complete
+          */
+          try
+          {
+            while (!jmolViewer.getBinding().isFinishedInit())
+            {
+              Thread.sleep(500);
+            }
+          } catch (InterruptedException e)
+          {
+          }
+          // System.out.println(">>>>>>>>>>>>>>>>> "
+          // + jmolViewer.getBinding().getPdbFile());
+          String[] expectedModelFiles = new String[] { "http://www.jalview.org/builds/develop/examples/3W5V.pdb" };
+          String[] actualModelFiles = jmolViewer.getBinding().getStructureFiles();
+          Assert.assertEqualsNoOrder(actualModelFiles, expectedModelFiles);
+          jmolViewer.closeViewer(true);
+          // todo: break here means only once through this loop?
+          break;
+        }
+        break;
+      }
+    }
+  }
 }
index d85bb10..29fd092 100644 (file)
@@ -217,7 +217,7 @@ public class JalviewChimeraView
      * (or possibly 52-145 to 1-94 - see JAL-2319)
      */
     StructureSelectionManager ssm = binding.getSsm();
-    String pdbFile = binding.getPdbFile()[0];
+    String pdbFile = binding.getStructureFiles()[0];
     StructureMapping[] mappings = ssm.getMapping(pdbFile);
     assertTrue(mappings[0].getMappingDetailsOutput().contains("SIFTS"),
             "Failed to perform SIFTS mapping");
diff --git a/test/jalview/io/FileLoaderTest.java b/test/jalview/io/FileLoaderTest.java
new file mode 100644 (file)
index 0000000..0e21f6e
--- /dev/null
@@ -0,0 +1,24 @@
+package jalview.io;
+
+import org.junit.Assert;
+import org.testng.annotations.Test;
+
+public class FileLoaderTest
+{
+
+  @Test(groups = { "Network" })
+  public void testDownloadStructuresIfInputFromURL()
+  {
+    String urlFile = "http://www.jalview.org/builds/develop/examples/3W5V.pdb";
+    FileLoader fileLoader = new FileLoader();
+    fileLoader.LoadFileWaitTillLoaded(urlFile, DataSourceType.URL,
+            FileFormat.PDB);
+    Assert.assertNotNull(fileLoader.file);
+    // The FileLoader's file is expected to a temporary file different from the
+    // original URL.
+    Assert.assertNotEquals(urlFile, fileLoader.file);
+    // Data source type expected to be updated from DataSourceType.URL to
+    // DataSourceType.FILE
+    Assert.assertEquals(DataSourceType.FILE, fileLoader.protocol);
+  }
+}
index a7e483e..c125ef6 100644 (file)
@@ -138,7 +138,7 @@ public class AAStructureBindingModelTest
     testee = new AAStructureBindingModel(ssm, pdbFiles, seqs, null)
     {
       @Override
-      public String[] getPdbFile()
+      public String[] getStructureFiles()
       {
         return new String[] { "INLINE1YCS", "INLINE3A6S", "INLINE1OOT" };
       }
@@ -230,7 +230,7 @@ public class AAStructureBindingModelTest
     /*
      * create a data bean to hold data per structure file
      */
-    SuperposeData[] structs = new SuperposeData[testee.getPdbFile().length];
+    SuperposeData[] structs = new SuperposeData[testee.getStructureFiles().length];
     for (int i = 0; i < structs.length; i++)
     {
       structs[i] = testee.new SuperposeData(al.getWidth());