JAL-2154 testNG like assertAlignmentDatasetRefs static wrappers and allow a message...
[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.assertAlignmentDatasetRefs(af.getViewport()
103                   .getAlignment(), "Pass (" + pass1 + "," + pass2 + ","
104                   + pass3 + "): Fetch " + first + ":");
105
106           // store project to recover on next pass
107           stringify(dbtoviewBit, savedProjects, first, af.alignPanel);
108         }
109         else
110         {
111           Desktop.instance.closeAll_actionPerformed(null);
112           // recover stored project
113           af = new FileLoader(false).LoadFileWaitTillLoaded(savedProjects
114                   .get(first).toString(), FormatAdapter.FILE);
115
116           // verify references for recovered data
117           AlignmentTest.assertAlignmentDatasetRefs(af.getViewport()
118                   .getAlignment(), "Pass (" + pass1 + "," + pass2 + ","
119                   + pass3 + "): Recover " + first + ":");
120
121         }
122
123         boolean dna = af.getViewport().getAlignment().isNucleotide();
124         AlignmentI retral = af.getViewport().getAlignment();
125         AlignmentI dataset = retral.getDataset();
126         SequenceI[] seqs = retral.getSequencesArray();
127         List<String> ptypes = (seqs == null || seqs.length == 0) ? null
128                 : new CrossRef(seqs, dataset)
129                         .findXrefSourcesForSequences(dna);
130
131         /*
132          * map between a view, and views generated after retrieving xrefs
133          */
134         IdentityHashMap<AlignmentViewPanel, List<AlignmentViewPanel>> viewxrefview = new IdentityHashMap<AlignmentViewPanel, List<AlignmentViewPanel>>();
135         /*
136          * map between a particular view and it's originating dbref path
137          */
138         IdentityHashMap<AlignmentViewPanel, String> viewsourcedb = new IdentityHashMap<AlignmentViewPanel, String>();
139
140         viewsourcedb.put(af.alignPanel, first);
141         for (String db : ptypes)
142         {
143           pass2 = 0;
144           do // second cross ref and recover crossref loop
145           {
146             // counter for splitframe views retrieved via crossref
147             int p = 0;
148             // build next key so we an retrieve all views
149             String nextxref = first + " -> " + db + "{" + p + "}";
150             // perform crossref action, or retrieve stored project
151             List<AlignmentViewPanel> cra_views = new ArrayList<AlignmentViewPanel>();
152             CrossRefAction cra = null;
153             if (pass2 == 0)
154             { // retrieve and show cross-refs in this thread
155               cra = new CrossRefAction(af, seqs, dna, db);
156               cra.run();
157               Assert.assertTrue(cra.getXrefViews().size() > 0,
158                       "No crossrefs retrieved for " + db);
159               cra_views = cra.getXrefViews();
160               viewxrefview.put(af.alignPanel, cra.getXrefViews());
161             }
162             else
163             {
164               Desktop.instance.closeAll_actionPerformed(null);
165               // recover stored project
166               AlignFrame af2 = new FileLoader(false)
167                       .LoadFileWaitTillLoaded(savedProjects.get(nextxref)
168                               .toString(), FormatAdapter.FILE);
169               // gymnastics to recover the alignPanel/Complementary alignPanel
170               if (af2.getViewport().isNucleotide())
171               {
172                 // top view, then bottom
173                 cra_views.add(af2.getViewport().getAlignPanel());
174                 cra_views.add(((jalview.gui.AlignViewport) af2
175                         .getViewport().getCodingComplement())
176                         .getAlignPanel());
177
178               }
179               else
180               {
181                 // bottom view, then top
182                 cra_views.add(((jalview.gui.AlignViewport) af2
183                         .getViewport().getCodingComplement())
184                         .getAlignPanel());
185                 cra_views.add(af2.getViewport().getAlignPanel());
186
187               }
188             }
189             for (AlignmentViewPanel avp : cra_views)
190             {
191               nextxref = first + " -> " + db + "{" + p++ + "}";
192
193               // verify references for this panel
194               AlignmentTest.assertAlignmentDatasetRefs(avp.getAlignment(),
195                       "" + "Pass (" + pass1 + "," + pass2 + "): For "
196                               + nextxref + ":");
197
198               SequenceI[] xrseqs = avp.getAlignment().getSequencesArray();
199
200               viewsourcedb.put(avp, nextxref);
201               stringify(dbtoviewBit, savedProjects, nextxref, avp);
202               keyseq.add(nextxref);
203
204               List<String> xrptypes = (seqs == null || seqs.length == 0) ? null
205                       : new CrossRef(xrseqs, dataset)
206                               .findXrefSourcesForSequences(avp
207                                       .getAlignViewport().isNucleotide());
208               for (String xrefdb : xrptypes)
209               {
210                 pass3 = 0;
211                 do // 3rd cross ref and recover crossref loop
212                 {
213                   List<AlignmentViewPanel> cra_views2 = new ArrayList<AlignmentViewPanel>();
214                   int q = 0;
215                   String nextnextxref = "{" + p + "}" + nextxref + " -> "
216                           + xrefdb + "{" + q + "}";
217
218                   AlignFrame nextaf = Desktop.getAlignFrameFor(avp
219                           .getAlignViewport());
220                   if (pass3 == 0)
221                   {
222
223                     cra = new CrossRefAction(nextaf, xrseqs, avp
224                             .getAlignViewport().isNucleotide(), xrefdb);
225                     cra.run();
226                     Assert.assertTrue(cra.getXrefViews().size() > 0,
227                             "No crossrefs found for '" + nextxref + "' to "
228                                     + xrefdb + " via '" + nextaf.getTitle()
229                                     + "'");
230                     cra_views2 = cra.getXrefViews();
231                   }
232                   else
233                   {
234                     Desktop.instance.closeAll_actionPerformed(null);
235                     // recover stored project
236                     AlignFrame af2 = new FileLoader(false)
237                             .LoadFileWaitTillLoaded(
238                                     savedProjects.get(nextnextxref)
239                                             .toString(), FormatAdapter.FILE);
240                     // gymnastics to recover the alignPanel/Complementary
241                     // alignPanel
242                     if (af2.getViewport().isNucleotide())
243                     {
244                       // top view, then bottom
245                       cra_views2.add(af2.getViewport().getAlignPanel());
246                       cra_views2.add(((jalview.gui.AlignViewport) af2
247                               .getViewport().getCodingComplement())
248                               .getAlignPanel());
249
250                     }
251                     else
252                     {
253                       // bottom view, then top
254                       cra_views2.add(((jalview.gui.AlignViewport) af2
255                               .getViewport().getCodingComplement())
256                               .getAlignPanel());
257                       cra_views2.add(af2.getViewport().getAlignPanel());
258                     }
259                     Assert.assertEquals(cra_views2.size(), 2);
260                     Assert.assertNotNull(cra_views2.get(0));
261                     Assert.assertNotNull(cra_views2.get(1));
262                   }
263
264                   for (AlignmentViewPanel nextavp : cra_views2)
265                   {
266                     nextnextxref = "{" + p + "}" + nextxref + " -> "
267                             + xrefdb + "{" + q++ + "}";
268
269                     // verify references for this panel
270                     AlignmentTest.assertAlignmentDatasetRefs(
271                             nextavp.getAlignment(), "" + "Pass (" + pass1
272                                     + "," + pass2 + "): For "
273                                     + nextnextxref + ":");
274
275                     viewsourcedb.put(nextavp, nextnextxref);
276                     stringify(dbtoviewBit, savedProjects, nextnextxref,
277                             nextavp);
278                     keyseq.add(nextnextxref);
279                   }
280                 } while (pass3++ < 2 && pass2 < 1);
281               }
282             }
283           } while (pass2++ < 2 && pass1 < 1);
284         }
285       } while (++pass1 < 2);
286     }
287   }
288
289   /**
290    * first time called, record strings derived from alignment and
291    * alignedcodonframes, and save view to a project file. Second time called,
292    * compare strings to existing ones. org.testng.Assert.assertTrue on
293    * stringmatch
294    * 
295    * @param dbtoviewBit
296    *          map between xrefpath and view string
297    * @param savedProjects
298    *          - map from xrefpath to saved project filename (createTempFile)
299    * @param xrefpath
300    *          - xrefpath - unique ID for this context (composed of sequence of
301    *          db-fetch/cross-ref actions preceeding state)
302    * @param avp
303    *          - viewpanel to store (for viewpanels in splitframe, the same
304    *          project should be written for both panels, only one needs
305    *          recovering for comparison on the next stringify call, but each
306    *          viewpanel needs to be called with a distinct xrefpath to ensure
307    *          each one's strings are compared)
308    */
309   private void stringify(HashMap<String, String> dbtoviewBit,
310           HashMap<String, File> savedProjects, String xrefpath,
311           AlignmentViewPanel avp)
312   {
313     if (savedProjects != null)
314     {
315       if (savedProjects.get(xrefpath) == null)
316     {
317       // write a project file for this view. On the second pass, this will be
318       // recovered and cross-references verified
319       try
320       {
321         File prfile = File.createTempFile("crossRefTest", ".jvp");
322         AlignFrame af = Desktop.getAlignFrameFor(avp.getAlignViewport());
323         new Jalview2XML(false).saveAlignment(af, prfile.toString(),
324                 af.getTitle());
325         System.out.println("Written view from '" + xrefpath + "' as '"
326                 + prfile.getAbsolutePath() + "'");
327         savedProjects.put(xrefpath, prfile);
328       } catch (IOException q)
329       {
330         Assert.fail("Unexpected IO Exception", q);
331       }
332       }
333       else
334       {
335         System.out.println("Stringify check on view from '" + xrefpath
336                 + "' [ possibly retrieved from '"
337                 + savedProjects.get(xrefpath).getAbsolutePath() + "' ]");
338
339       }
340     }
341
342     StringBuilder sbr = new StringBuilder();
343     sbr.append(avp.getAlignment().toString());
344     sbr.append("\n");
345     sbr.append("<End of alignment>");
346     sbr.append("\n");
347     sbr.append(avp.getAlignment().getDataset());
348     sbr.append("\n");
349     sbr.append("<End of dataset>");
350     sbr.append("\n");
351     int p = 0;
352     if (avp.getAlignment().getCodonFrames() != null)
353     {
354       for (AlignedCodonFrame ac : avp.getAlignment().getCodonFrames())
355       {
356         sbr.append("<AlignedCodonFrame " + p++ + ">");
357         sbr.append("\n");
358         sbr.append(ac.toString());
359         sbr.append("\n");
360       }
361     }
362     String dbt = dbtoviewBit.get(xrefpath);
363     if (dbt == null)
364     {
365       dbtoviewBit.put(xrefpath, sbr.toString());
366     }
367     else
368     {
369       Assert.assertEquals(sbr.toString(), dbt, "stringify mismatch for "
370               + xrefpath);
371     }
372   }
373 }