JAL-2154 use right reference string for recovering saved project
[jalview.git] / test / jalview / io / CrossRef2xmlTests.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.io;
22
23 import static org.testng.AssertJUnit.assertTrue;
24
25 import jalview.analysis.CrossRef;
26 import jalview.api.AlignmentViewPanel;
27 import jalview.datamodel.AlignedCodonFrame;
28 import jalview.datamodel.AlignmentI;
29 import jalview.datamodel.AlignmentTest;
30 import jalview.datamodel.SequenceI;
31 import jalview.gui.AlignFrame;
32 import jalview.gui.CrossRefAction;
33 import jalview.gui.Desktop;
34 import jalview.gui.Jalview2XML;
35
36 import java.io.File;
37 import java.io.IOException;
38 import java.util.ArrayList;
39 import java.util.HashMap;
40 import java.util.IdentityHashMap;
41 import java.util.List;
42
43 import org.testng.Assert;
44 import org.testng.annotations.Test;
45
46 @Test(singleThreaded = true)
47 public class CrossRef2xmlTests extends Jalview2xmlBase
48 {
49
50   /**
51    * test store and recovery of expanded views
52    * 
53    * @throws Exception
54    */
55   @Test(groups = { "Operational" }, enabled = true)
56   public void testRetrieveAndShowCrossref() throws Exception
57   {
58     // for every set of db queries
59     // retrieve db query
60     // verify presence of expected xrefs
61     // show xrefs - verify expected type of frame is shown for each xref
62     // show xrefs again
63     // - verify original -> xref -> xref(original) recovers frame containing at
64     // least the first retrieved sequence
65     // store
66     // 1. whole project
67     // 2. individual frames
68     // 3. load each one back and verify
69     // . aligned sequences (.toString() )
70     // . xrefs (.toString() )
71     // . codonframes
72     //
73     //
74     HashMap<String, String> dbtoviewBit = new HashMap<String, String>();
75     List<String> keyseq = new ArrayList<String>();
76     HashMap<String, File> savedProjects = new HashMap<String, File>();
77
78     for (String[] did : new String[][] { { "UNIPROT", "P01731" } })
79     {
80       // pass counters - 0 - first pass, 1 means retrieve project rather than
81       // perform action
82       int pass1 = 0, pass2 = 0, pass3 = 0;
83       // each do loop performs two iterations in the first outer loop pass, but
84       // only performs one iteration on the second outer loop
85       // ie. pass 1 = 0 {pass 2= 0 { pass 3 = 0,1 }, pass 2=1 { pass 3 = 0 }}, 1
86       // { pass 2 = 0 { pass 3 = 0 } }
87       do
88       {
89         String first = did[0] + " " + did[1];
90         AlignFrame af = null;
91         if (pass1 == 0)
92         {
93           // retrieve dbref
94
95           keyseq.add(first);
96
97           af = jalview.gui.SequenceFetcher.fetchAndShow(did[0], did[1])
98                   .get(0);
99           assertTrue("Didn't retrieve " + first, af != null);
100
101           // verify references for retrieved data
102           AlignmentTest.verifyAlignmentDatasetRefs(af.getViewport()
103                   .getAlignment(), true);
104
105           // store project to recover on next pass
106           stringify(dbtoviewBit, savedProjects, first, af.alignPanel);
107         }
108         else
109         {
110           Desktop.instance.closeAll_actionPerformed(null);
111           // recover stored project
112           af = new FileLoader(false).LoadFileWaitTillLoaded(savedProjects
113                   .get(first).toString(), FormatAdapter.FILE);
114
115           // verify references for recovered data
116           AlignmentTest.verifyAlignmentDatasetRefs(af.getViewport()
117                   .getAlignment(), true);
118
119         }
120
121         boolean dna = af.getViewport().getAlignment().isNucleotide();
122         AlignmentI retral = af.getViewport().getAlignment();
123         AlignmentI dataset = retral.getDataset();
124         SequenceI[] seqs = retral.getSequencesArray();
125         List<String> ptypes = (seqs == null || seqs.length == 0) ? null
126                 : new CrossRef(seqs, dataset)
127                         .findXrefSourcesForSequences(dna);
128
129         /*
130          * map between a view, and views generated after retrieving xrefs
131          */
132         IdentityHashMap<AlignmentViewPanel, List<AlignmentViewPanel>> viewxrefview = new IdentityHashMap<AlignmentViewPanel, List<AlignmentViewPanel>>();
133         /*
134          * map between a particular view and it's originating dbref path
135          */
136         IdentityHashMap<AlignmentViewPanel, String> viewsourcedb = new IdentityHashMap<AlignmentViewPanel, String>();
137
138         viewsourcedb.put(af.alignPanel, first);
139         for (String db : ptypes)
140         {
141           pass2 = 0;
142           do // second cross ref and recover crossref loop
143           {
144             // counter for splitframe views retrieved via crossref
145             int p = 0;
146             // build next key so we an retrieve all views
147             String nextxref = first + " -> " + db + "{" + p + "}";
148             // perform crossref action, or retrieve stored project
149             List<AlignmentViewPanel> cra_views = new ArrayList<AlignmentViewPanel>();
150             CrossRefAction cra = null;
151             if (pass2 == 0)
152             { // retrieve and show cross-refs in this thread
153               cra = new CrossRefAction(af, seqs, dna, db);
154               cra.run();
155               Assert.assertTrue(cra.getXrefViews().size() > 0,
156                       "No crossrefs retrieved for " + db);
157               cra_views = cra.getXrefViews();
158               viewxrefview.put(af.alignPanel, cra.getXrefViews());
159             }
160             else
161             {
162               Desktop.instance.closeAll_actionPerformed(null);
163               // recover stored project
164               AlignFrame af2 = new FileLoader(false)
165                       .LoadFileWaitTillLoaded(savedProjects.get(nextxref)
166                               .toString(), FormatAdapter.FILE);
167               // gymnastics to recover the alignPanel/Complementary alignPanel
168               if (af2.getViewport().isNucleotide())
169               {
170                 // top view, then bottom
171                 cra_views.add(af2.getViewport().getAlignPanel());
172                 cra_views.add(((jalview.gui.AlignViewport) af2
173                         .getViewport().getCodingComplement())
174                         .getAlignPanel());
175
176               }
177               else
178               {
179                 // bottom view, then top
180                 cra_views.add(((jalview.gui.AlignViewport) af2
181                         .getViewport().getCodingComplement())
182                         .getAlignPanel());
183                 cra_views.add(af2.getViewport().getAlignPanel());
184
185               }
186             }
187             for (AlignmentViewPanel avp : cra_views)
188             {
189               // verify references for this panel
190               AlignmentTest.verifyAlignmentDatasetRefs(avp.getAlignment(),
191                       true);
192
193               SequenceI[] xrseqs = avp.getAlignment().getSequencesArray();
194               nextxref = first + " -> " + db + "{" + p++ + "}";
195
196               viewsourcedb.put(avp, nextxref);
197               stringify(dbtoviewBit, savedProjects, nextxref, avp);
198               keyseq.add(nextxref);
199
200               List<String> xrptypes = (seqs == null || seqs.length == 0) ? null
201                       : new CrossRef(xrseqs, dataset)
202                               .findXrefSourcesForSequences(avp
203                                       .getAlignViewport().isNucleotide());
204               for (String xrefdb : xrptypes)
205               {
206                 pass3 = 0;
207                 do // 3rd cross ref and recover crossref loop
208                 {
209                   List<AlignmentViewPanel> cra_views2 = new ArrayList<AlignmentViewPanel>();
210                   int q = 0;
211                   String nextnextxref = "{" + p + "}" + nextxref + " -> "
212                           + xrefdb + "{" + q + "}";
213
214                   AlignFrame nextaf = Desktop.getAlignFrameFor(avp
215                           .getAlignViewport());
216                   if (pass3 == 0)
217                   {
218
219                     cra = new CrossRefAction(nextaf, xrseqs, avp
220                             .getAlignViewport().isNucleotide(), xrefdb);
221                     cra.run();
222                     Assert.assertTrue(cra.getXrefViews().size() > 0,
223                             "No crossrefs found for '" + nextxref + "' to "
224                                     + xrefdb + " via '" + nextaf.getTitle()
225                                     + "'");
226                     cra_views2 = cra.getXrefViews();
227                   }
228                   else
229                   {
230                     Desktop.instance.closeAll_actionPerformed(null);
231                     // recover stored project
232                     AlignFrame af2 = new FileLoader(false)
233                             .LoadFileWaitTillLoaded(
234                                     savedProjects.get(nextnextxref)
235                                             .toString(), FormatAdapter.FILE);
236                     // gymnastics to recover the alignPanel/Complementary
237                     // alignPanel
238                     if (af2.getViewport().isNucleotide())
239                     {
240                       // top view, then bottom
241                       cra_views2.add(af2.getViewport().getAlignPanel());
242                       cra_views2.add(((jalview.gui.AlignViewport) af2
243                               .getViewport().getCodingComplement())
244                               .getAlignPanel());
245
246                     }
247                     else
248                     {
249                       // bottom view, then top
250                       cra_views2.add(((jalview.gui.AlignViewport) af2
251                               .getViewport().getCodingComplement())
252                               .getAlignPanel());
253                       cra_views2.add(af2.getViewport().getAlignPanel());
254                     }
255                     Assert.assertEquals(cra_views2.size(), 2);
256                     Assert.assertNotNull(cra_views2.get(0));
257                     Assert.assertNotNull(cra_views2.get(1));
258                   }
259
260                   for (AlignmentViewPanel nextavp : cra_views2)
261                   {
262                     nextnextxref = "{" + p + "}" + nextxref + " -> "
263                             + xrefdb + "{" + q++ + "}";
264
265                     // verify references for this panel
266                     AlignmentTest.verifyAlignmentDatasetRefs(
267                             nextavp.getAlignment(), true);
268
269                     viewsourcedb.put(nextavp, nextnextxref);
270                     stringify(dbtoviewBit, savedProjects, nextnextxref,
271                             nextavp);
272                     keyseq.add(nextnextxref);
273                   }
274                 } while (pass3++ < 2 && pass2 < 1);
275               }
276             }
277           } while (pass2++ < 2 && pass1 < 1);
278         }
279       } while (++pass1 < 2);
280     }
281   }
282
283   /**
284    * first time called, record strings derived from alignment and
285    * alignedcodonframes, and save view to a project file. Second time called,
286    * compare strings to existing ones. org.testng.Assert.assertTrue on
287    * stringmatch
288    * 
289    * @param dbtoviewBit
290    *          map between xrefpath and view string
291    * @param savedProjects
292    *          - map from xrefpath to saved project filename (createTempFile)
293    * @param xrefpath
294    *          - xrefpath - unique ID for this context (composed of sequence of
295    *          db-fetch/cross-ref actions preceeding state)
296    * @param avp
297    *          - viewpanel to store (for viewpanels in splitframe, the same
298    *          project should be written for both panels, only one needs
299    *          recovering for comparison on the next stringify call, but each
300    *          viewpanel needs to be called with a distinct xrefpath to ensure
301    *          each one's strings are compared)
302    */
303   private void stringify(HashMap<String, String> dbtoviewBit,
304           HashMap<String, File> savedProjects, String xrefpath,
305           AlignmentViewPanel avp)
306   {
307     if (savedProjects != null)
308     {
309       if (savedProjects.get(xrefpath) == null)
310     {
311       // write a project file for this view. On the second pass, this will be
312       // recovered and cross-references verified
313       try
314       {
315         File prfile = File.createTempFile("crossRefTest", ".jvp");
316         AlignFrame af = Desktop.getAlignFrameFor(avp.getAlignViewport());
317         new Jalview2XML(false).saveAlignment(af, prfile.toString(),
318                 af.getTitle());
319         System.out.println("Written view from '" + xrefpath + "' as '"
320                 + prfile.getAbsolutePath() + "'");
321         savedProjects.put(xrefpath, prfile);
322       } catch (IOException q)
323       {
324         Assert.fail("Unexpected IO Exception", q);
325       }
326       }
327       else
328       {
329         System.out.println("Stringify check on view from '" + xrefpath
330                 + "' [ possibly retrieved from '"
331                 + savedProjects.get(xrefpath).getAbsolutePath() + "' ]");
332
333       }
334     }
335
336     StringBuilder sbr = new StringBuilder();
337     sbr.append(avp.getAlignment().toString());
338     sbr.append("\n");
339     sbr.append("<End of alignment>");
340     sbr.append("\n");
341     sbr.append(avp.getAlignment().getDataset());
342     sbr.append("\n");
343     sbr.append("<End of dataset>");
344     sbr.append("\n");
345     int p = 0;
346     if (avp.getAlignment().getCodonFrames() != null)
347     {
348       for (AlignedCodonFrame ac : avp.getAlignment().getCodonFrames())
349       {
350         sbr.append("<AlignedCodonFrame " + p++ + ">");
351         sbr.append("\n");
352         sbr.append(ac.toString());
353         sbr.append("\n");
354       }
355     }
356     String dbt = dbtoviewBit.get(xrefpath);
357     if (dbt == null)
358     {
359       dbtoviewBit.put(xrefpath, sbr.toString());
360     }
361     else
362     {
363       Assert.assertEquals(sbr.toString(), dbt, "stringify mismatch for "
364               + xrefpath);
365     }
366   }
367 }