JAL-1705 refactored code for dbsource reggae validator and added further refactoring...
[jalview.git] / src / jalview / gui / SequenceFetcher.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.gui;
22
23 import jalview.datamodel.AlignmentI;
24 import jalview.datamodel.DBRefEntry;
25 import jalview.datamodel.DBRefSource;
26 import jalview.datamodel.SequenceFeature;
27 import jalview.datamodel.SequenceI;
28 import jalview.io.FormatAdapter;
29 import jalview.io.IdentifyFile;
30 import jalview.util.DBRefUtils;
31 import jalview.util.MessageManager;
32 import jalview.ws.dbsources.das.api.DasSourceRegistryI;
33 import jalview.ws.seqfetcher.DbSourceProxy;
34
35 import java.awt.BorderLayout;
36 import java.awt.Font;
37 import java.awt.event.ActionEvent;
38 import java.awt.event.ActionListener;
39 import java.awt.event.KeyAdapter;
40 import java.awt.event.KeyEvent;
41 import java.util.ArrayList;
42 import java.util.Arrays;
43 import java.util.Iterator;
44 import java.util.List;
45
46 import javax.swing.JButton;
47 import javax.swing.JCheckBox;
48 import javax.swing.JInternalFrame;
49 import javax.swing.JLabel;
50 import javax.swing.JOptionPane;
51 import javax.swing.JPanel;
52 import javax.swing.JScrollPane;
53 import javax.swing.JTextArea;
54 import javax.swing.SwingConstants;
55 import javax.swing.tree.DefaultMutableTreeNode;
56
57 public class SequenceFetcher extends JPanel implements Runnable
58 {
59   JLabel dbeg = new JLabel();
60
61   JDatabaseTree database;
62
63   JButton databaseButt;
64
65   JLabel jLabel1 = new JLabel();
66
67   JCheckBox replacePunctuation = new JCheckBox();
68
69   JButton ok = new JButton();
70
71   JButton clear = new JButton();
72
73   JButton example = new JButton();
74
75   JButton close = new JButton();
76
77   JPanel jPanel1 = new JPanel();
78
79   JTextArea textArea = new JTextArea();
80
81   JScrollPane jScrollPane1 = new JScrollPane();
82
83   JPanel jPanel2 = new JPanel();
84
85   JPanel jPanel3 = new JPanel();
86
87   JPanel jPanel4 = new JPanel();
88
89   BorderLayout borderLayout1 = new BorderLayout();
90
91   BorderLayout borderLayout2 = new BorderLayout();
92
93   BorderLayout borderLayout3 = new BorderLayout();
94
95   JInternalFrame frame;
96
97   IProgressIndicator guiWindow;
98
99   AlignFrame alignFrame;
100
101   StringBuffer result;
102
103   final String noDbSelected = "-- Select Database --";
104
105   private static jalview.ws.SequenceFetcher sfetch = null;
106
107   private static long lastDasSourceRegistry = -3;
108
109   private static DasSourceRegistryI dasRegistry = null;
110
111   private static boolean _initingFetcher = false;
112
113   private static Thread initingThread = null;
114
115   int debounceTrap = 0;
116   /**
117    * Blocking method that initialises and returns the shared instance of the
118    * SequenceFetcher client
119    * 
120    * @param guiWindow
121    *          - where the initialisation delay message should be shown
122    * @return the singleton instance of the sequence fetcher client
123    */
124   public static jalview.ws.SequenceFetcher getSequenceFetcherSingleton(
125           final IProgressIndicator guiWindow)
126   {
127     if (_initingFetcher && initingThread != null && initingThread.isAlive())
128     {
129       if (guiWindow != null)
130       {
131         guiWindow.setProgressBar(
132                 MessageManager.getString("status.waiting_sequence_database_fetchers_init"),
133                 Thread.currentThread().hashCode());
134       }
135       // initting happening on another thread - so wait around to see if it
136       // finishes.
137       while (_initingFetcher && initingThread != null
138               && initingThread.isAlive())
139       {
140         try
141         {
142           Thread.sleep(10);
143         } catch (Exception e)
144         {
145         }
146         ;
147       }
148       if (guiWindow != null)
149       {
150         guiWindow.setProgressBar(
151                         MessageManager.getString("status.waiting_sequence_database_fetchers_init"),
152                 Thread.currentThread().hashCode());
153       }
154     }
155     if (sfetch == null
156             || dasRegistry != jalview.bin.Cache.getDasSourceRegistry()
157             || lastDasSourceRegistry != (jalview.bin.Cache
158                     .getDasSourceRegistry().getDasRegistryURL() + jalview.bin.Cache
159                     .getDasSourceRegistry().getLocalSourceString())
160                     .hashCode())
161     {
162       _initingFetcher = true;
163       initingThread = Thread.currentThread();
164       /**
165        * give a visual indication that sequence fetcher construction is occuring
166        */
167       if (guiWindow != null)
168       {
169         guiWindow.setProgressBar(MessageManager.getString("status.init_sequence_database_fetchers"),
170                 Thread.currentThread().hashCode());
171       }
172       dasRegistry = jalview.bin.Cache.getDasSourceRegistry();
173       dasRegistry.refreshSources();
174
175       jalview.ws.SequenceFetcher sf = new jalview.ws.SequenceFetcher();
176       if (guiWindow != null)
177       {
178         guiWindow.setProgressBar(null, Thread.currentThread().hashCode());
179       }
180       lastDasSourceRegistry = (dasRegistry.getDasRegistryURL() + dasRegistry
181               .getLocalSourceString()).hashCode();
182       sfetch = sf;
183       _initingFetcher = false;
184       initingThread = null;
185     }
186     return sfetch;
187   }
188
189   private IProgressIndicator progressIndicator;
190   public SequenceFetcher(IProgressIndicator guiIndic)
191   {
192     this.progressIndicator = guiIndic;
193     final SequenceFetcher us = this;
194     // launch initialiser thread
195     Thread sf = new Thread(new Runnable()
196     {
197
198       @Override
199       public void run()
200       {
201         if (getSequenceFetcherSingleton(progressIndicator) != null)
202         {
203           us.initGui(progressIndicator);
204         }
205         else
206         {
207           javax.swing.SwingUtilities.invokeLater(new Runnable()
208           {
209             @Override
210             public void run()
211             {
212               JOptionPane
213                       .showInternalMessageDialog(
214                               Desktop.desktop,
215                               MessageManager.getString("warn.couldnt_create_sequence_fetcher_client"),
216                               MessageManager.getString("label.couldnt_create_sequence_fetcher"),
217                               JOptionPane.ERROR_MESSAGE);
218             }
219           });
220
221           // raise warning dialog
222         }
223       }
224     });
225     sf.start();
226   }
227
228   private class DatabaseAuthority extends DefaultMutableTreeNode
229   {
230
231   };
232
233   private class DatabaseSource extends DefaultMutableTreeNode
234   {
235
236   };
237
238   /**
239    * called by thread spawned by constructor
240    * 
241    * @param guiWindow
242    */
243   private void initGui(IProgressIndicator guiWindow)
244   {
245     this.guiWindow = guiWindow;
246     if (guiWindow instanceof AlignFrame)
247     {
248       alignFrame = (AlignFrame) guiWindow;
249     }
250     database = new JDatabaseTree(sfetch);
251     try
252     {
253       jbInit();
254     } catch (Exception ex)
255     {
256       ex.printStackTrace();
257     }
258
259     frame = new JInternalFrame();
260     frame.setContentPane(this);
261     if (new jalview.util.Platform().isAMac())
262     {
263       Desktop.addInternalFrame(frame, getFrameTitle(), 400, 240);
264     }
265     else
266     {
267       Desktop.addInternalFrame(frame, getFrameTitle(), 400, 180);
268     }
269   }
270
271   private String getFrameTitle()
272   {
273     return ((alignFrame == null) ? MessageManager.getString("label.new_sequence_fetcher") : MessageManager.getString("label.additional_sequence_fetcher"));
274   }
275
276   private void jbInit() throws Exception
277   {
278     this.setLayout(borderLayout2);
279
280     database.setFont(JvSwingUtils.getLabelFont());
281     dbeg.setFont(new java.awt.Font("Verdana", Font.BOLD, 11));
282     jLabel1.setFont(new java.awt.Font("Verdana", Font.ITALIC, 11));
283     jLabel1.setHorizontalAlignment(SwingConstants.CENTER);
284     jLabel1.setText(MessageManager
285             .getString("label.separate_multiple_accession_ids"));
286
287     replacePunctuation.setHorizontalAlignment(SwingConstants.CENTER);
288     replacePunctuation
289             .setFont(new java.awt.Font("Verdana", Font.ITALIC, 11));
290     replacePunctuation.setText(MessageManager
291             .getString("label.replace_commas_semicolons"));
292     ok.setText(MessageManager.getString("action.ok"));
293     ok.addActionListener(new ActionListener()
294     {
295       @Override
296       public void actionPerformed(ActionEvent e)
297       {
298         ok_actionPerformed();
299       }
300     });
301     clear.setText(MessageManager.getString("action.clear"));
302     clear.addActionListener(new ActionListener()
303     {
304       @Override
305       public void actionPerformed(ActionEvent e)
306       {
307         clear_actionPerformed();
308       }
309     });
310
311     example.setText(MessageManager.getString("label.example"));
312     example.addActionListener(new ActionListener()
313     {
314       @Override
315       public void actionPerformed(ActionEvent e)
316       {
317         example_actionPerformed();
318       }
319     });
320     close.setText(MessageManager.getString("action.close"));
321     close.addActionListener(new ActionListener()
322     {
323       @Override
324       public void actionPerformed(ActionEvent e)
325       {
326         close_actionPerformed(e);
327       }
328     });
329     textArea.setFont(JvSwingUtils.getLabelFont());
330     textArea.setLineWrap(true);
331     textArea.addKeyListener(new KeyAdapter()
332     {
333       @Override
334       public void keyPressed(KeyEvent e)
335       {
336         if (e.getKeyCode() == KeyEvent.VK_ENTER)
337         {
338           ok_actionPerformed();
339         }
340       }
341     });
342     jPanel3.setLayout(borderLayout1);
343     borderLayout1.setVgap(5);
344     jPanel1.add(ok);
345     jPanel1.add(example);
346     jPanel1.add(clear);
347     jPanel1.add(close);
348     jPanel3.add(jPanel2, java.awt.BorderLayout.CENTER);
349     jPanel2.setLayout(borderLayout3);
350     databaseButt = database.getDatabaseSelectorButton();
351     databaseButt.setFont(JvSwingUtils.getLabelFont());
352     database.addActionListener(new ActionListener()
353     {
354       @Override
355       public void actionPerformed(ActionEvent e)
356       {
357         debounceTrap++;
358         String currentSelection = database.getSelectedItem();
359
360         if (!currentSelection.equalsIgnoreCase("pdb"))
361         {
362             otherSourceAction();
363         }
364         if (currentSelection.equalsIgnoreCase("pdb") && ((debounceTrap % 2) == 0))
365         {
366           pdbSourceAction();
367         }
368
369       }
370     });
371     dbeg.setText("");
372     jPanel2.add(databaseButt, java.awt.BorderLayout.NORTH);
373     jPanel2.add(dbeg, java.awt.BorderLayout.CENTER);
374     JPanel jPanel2a = new JPanel(new BorderLayout());
375     jPanel2a.add(jLabel1, java.awt.BorderLayout.NORTH);
376     jPanel2a.add(replacePunctuation, java.awt.BorderLayout.SOUTH);
377     jPanel2.add(jPanel2a, java.awt.BorderLayout.SOUTH);
378     // jPanel2.setPreferredSize(new Dimension())
379     jPanel3.add(jScrollPane1, java.awt.BorderLayout.CENTER);
380     this.add(jPanel1, java.awt.BorderLayout.SOUTH);
381     this.add(jPanel3, java.awt.BorderLayout.CENTER);
382     this.add(jPanel2, java.awt.BorderLayout.NORTH);
383     jScrollPane1.getViewport().add(textArea);
384
385   }
386
387   private void pdbSourceAction()
388   {
389     databaseButt.setText(database.getSelectedItem());
390     new PDBSearchPanel(this);
391     frame.dispose();
392   }
393
394   private void otherSourceAction()
395   {
396     try
397     {
398       databaseButt.setText(database.getSelectedItem()
399               + (database.getSelectedSources().size() > 1 ? " (and "
400                       + database.getSelectedSources().size() + " others)"
401                       : ""));
402       String eq = database.getExampleQueries();
403       dbeg.setText(MessageManager.formatMessage(
404               "label.example_query_param", new String[]
405               { eq }));
406       boolean enablePunct = !(eq != null && eq.indexOf(",") > -1);
407       for (DbSourceProxy dbs : database.getSelectedSources())
408       {
409         if (dbs instanceof jalview.ws.dbsources.das.datamodel.DasSequenceSource)
410         {
411           enablePunct = false;
412           break;
413         }
414       }
415       replacePunctuation.setEnabled(enablePunct);
416
417     } catch (Exception ex)
418     {
419       dbeg.setText("");
420       replacePunctuation.setEnabled(true);
421     }
422     jPanel2.repaint();
423   }
424
425   protected void example_actionPerformed()
426   {
427     DbSourceProxy db = null;
428     try
429     {
430       textArea.setText(database.getExampleQueries());
431     } catch (Exception ex)
432     {
433     }
434     jPanel3.repaint();
435   }
436
437   protected void clear_actionPerformed()
438   {
439     textArea.setText("");
440     jPanel3.repaint();
441   }
442
443
444
445   public void close_actionPerformed(ActionEvent e)
446   {
447     try
448     {
449       frame.setClosed(true);
450     } catch (Exception ex)
451     {
452     }
453   }
454
455   public void ok_actionPerformed()
456   {
457     databaseButt.setEnabled(false);
458     example.setEnabled(false);
459     textArea.setEnabled(false);
460     ok.setEnabled(false);
461     close.setEnabled(false);
462
463     Thread worker = new Thread(this);
464     worker.start();
465   }
466
467   private void resetDialog()
468   {
469     databaseButt.setEnabled(true);
470     example.setEnabled(true);
471     textArea.setEnabled(true);
472     ok.setEnabled(true);
473     close.setEnabled(true);
474   }
475
476   @Override
477   public void run()
478   {
479     String error = "";
480     if (!database.hasSelection())
481     {
482       error += "Please select the source database\n";
483     }
484     // TODO: make this transformation more configurable
485     com.stevesoft.pat.Regex empty;
486     if (replacePunctuation.isEnabled() && replacePunctuation.isSelected())
487     {
488       empty = new com.stevesoft.pat.Regex(
489       // replace commas and spaces with a semicolon
490               "(\\s|[,; ])+", ";");
491     }
492     else
493     {
494       // just turn spaces and semicolons into single semicolons
495       empty = new com.stevesoft.pat.Regex("(\\s|[; ])+", ";");
496     }
497     textArea.setText(empty.replaceAll(textArea.getText()));
498     // see if there's anthing to search with
499     if (!new com.stevesoft.pat.Regex("[A-Za-z0-9_.]").search(textArea
500             .getText()))
501     {
502       error += "Please enter a (semi-colon separated list of) database id(s)";
503     }
504     if (error.length() > 0)
505     {
506       showErrorMessage(error);
507       resetDialog();
508       return;
509     }
510     // TODO: Refactor to GUI independent code and write tests.
511     // indicate if successive sources should be merged into one alignment.
512     boolean addToLast = false;
513     ArrayList<String> aresultq = new ArrayList<String>(), presultTitle = new ArrayList<String>();
514     ArrayList<AlignmentI> presult = new ArrayList<AlignmentI>(), aresult = new ArrayList<AlignmentI>();
515     Iterator<DbSourceProxy> proxies = database.getSelectedSources()
516             .iterator();
517     String[] qries;
518     List<String> nextfetch = Arrays.asList(qries = textArea.getText()
519             .split(";"));
520     Iterator<String> en = Arrays.asList(new String[0]).iterator();
521     int nqueries = qries.length;
522     while (proxies.hasNext() && (en.hasNext() || nextfetch.size() > 0))
523     {
524       if (!en.hasNext() && nextfetch.size() > 0)
525       {
526         en = nextfetch.iterator();
527         nqueries = nextfetch.size();
528         // save the remaining queries in the original array
529         qries = nextfetch.toArray(new String[nqueries]);
530         nextfetch = new ArrayList<String>();
531       }
532
533       DbSourceProxy proxy = proxies.next();
534       boolean isAliSource = false;
535       try
536       {
537         // update status
538         guiWindow.setProgressBar(MessageManager.formatMessage("status.fetching_sequence_queries_from", new String[]{Integer.valueOf(nqueries).toString(),proxy.getDbName()}), Thread
539                 .currentThread().hashCode());
540         isAliSource = proxy.isA(DBRefSource.ALIGNMENTDB);
541         if (proxy.getAccessionSeparator() == null)
542         {
543           while (en.hasNext())
544           {
545             String item = en.next();
546             try
547             {
548               if (aresult != null)
549               {
550                 try
551                 {
552                   // give the server a chance to breathe
553                   Thread.sleep(5);
554                 } catch (Exception e)
555                 {
556                   //
557                 }
558
559               }
560
561               AlignmentI indres = null;
562               try
563               {
564                 indres = proxy.getSequenceRecords(item);
565               } catch (OutOfMemoryError oome)
566               {
567                 new OOMWarning("fetching " + item + " from "
568                         + proxy.getDbName(), oome, this);
569               }
570               if (indres != null)
571               {
572                 aresultq.add(item);
573                 aresult.add(indres);
574               }
575               else
576               {
577                 nextfetch.add(item);
578               }
579             } catch (Exception e)
580             {
581               jalview.bin.Cache.log.info("Error retrieving " + item
582                       + " from " + proxy.getDbName(), e);
583               nextfetch.add(item);
584             }
585           }
586         }
587         else
588         {
589           StringBuffer multiacc = new StringBuffer();
590           ArrayList<String> tosend = new ArrayList<String>();
591           while (en.hasNext())
592           {
593             String nel = en.next();
594             tosend.add(nel);
595             multiacc.append(nel);
596             if (en.hasNext())
597             {
598               multiacc.append(proxy.getAccessionSeparator());
599             }
600           }
601           try
602           {
603             AlignmentI rslt;
604             SequenceI[] rs;
605             List<String> nores = new ArrayList<String>();
606             rslt = proxy.getSequenceRecords(multiacc.toString());
607             if (rslt == null || rslt.getHeight() == 0)
608             {
609               // no results - pass on all queries to next source
610               nextfetch.addAll(tosend);
611             }
612             else
613             {
614               aresultq.add(multiacc.toString());
615               aresult.add(rslt);
616
617               rs = rslt.getSequencesArray();
618               // search for each query in the dbrefs associated with each
619               // sequence
620               // returned.
621               // ones we do not find will be used to query next source (if any)
622               for (String q : tosend)
623               {
624                 DBRefEntry dbr = new DBRefEntry(), found[] = null;
625                 dbr.setSource(proxy.getDbSource());
626                 dbr.setVersion(null);
627                 String accId = DBRefUtils.processQueryToAccessionFor(proxy,
628                         q);
629                 dbr.setAccessionId(accId);
630                 boolean rfound = false;
631                 for (int r = 0; r < rs.length; r++)
632                 {
633                   if (rs[r] != null
634                           && (found = DBRefUtils.searchRefs(
635                                   rs[r].getDBRef(), dbr)) != null
636                           && found.length > 0)
637                   {
638                     rfound = true;
639                     rs[r] = null;
640                     continue;
641                   }
642                 }
643                 if (!rfound)
644                 {
645                   nextfetch.add(q);
646                 }
647               }
648             }
649           } catch (OutOfMemoryError oome)
650           {
651             new OOMWarning("fetching " + multiacc + " from "
652                     + database.getSelectedItem(), oome, this);
653           }
654         }
655
656       } catch (Exception e)
657       {
658         showErrorMessage("Error retrieving " + textArea.getText()
659                 + " from " + database.getSelectedItem());
660         // error
661         // +="Couldn't retrieve sequences from "+database.getSelectedItem();
662         System.err.println("Retrieval failed for source ='"
663                 + database.getSelectedItem() + "' and query\n'"
664                 + textArea.getText() + "'\n");
665         e.printStackTrace();
666       } catch (OutOfMemoryError e)
667       {
668         // resets dialog box - so we don't use OOMwarning here.
669         showErrorMessage("Out of Memory when retrieving "
670                 + textArea.getText()
671                 + " from "
672                 + database.getSelectedItem()
673                 + "\nPlease see the Jalview FAQ for instructions for increasing the memory available to Jalview.\n");
674         e.printStackTrace();
675       } catch (Error e)
676       {
677         showErrorMessage("Serious Error retrieving " + textArea.getText()
678                 + " from " + database.getSelectedItem());
679         e.printStackTrace();
680       }
681       // Stack results ready for opening in alignment windows
682       if (aresult != null && aresult.size() > 0)
683       {
684         AlignmentI ar = null;
685         if (isAliSource)
686         {
687           addToLast = false;
688           // new window for each result
689           while (aresult.size() > 0)
690           {
691             presult.add(aresult.remove(0));
692             presultTitle.add(aresultq.remove(0) + " "
693                     + getDefaultRetrievalTitle());
694           }
695         }
696         else
697         {
698           String titl = null;
699           if (addToLast && presult.size() > 0)
700           {
701             ar = presult.remove(presult.size() - 1);
702             titl = presultTitle.remove(presultTitle.size() - 1);
703           }
704           // concatenate all results in one window
705           while (aresult.size() > 0)
706           {
707             if (ar == null)
708             {
709               ar = aresult.remove(0);
710             }
711             else
712             {
713               ar.append(aresult.remove(0));
714             }
715             ;
716           }
717           addToLast = true;
718           presult.add(ar);
719           presultTitle.add(titl);
720         }
721       }
722       guiWindow.setProgressBar(MessageManager.getString("status.finshed_querying"), Thread.currentThread()
723               .hashCode());
724     }
725     guiWindow.setProgressBar((presult.size() > 0) ? MessageManager.getString("status.parsing_results")
726             : MessageManager.getString("status.processing"), Thread.currentThread().hashCode());
727     // process results
728     while (presult.size() > 0)
729     {
730       parseResult(presult.remove(0), presultTitle.remove(0), null);
731     }
732     // only remove visual delay after we finished parsing.
733     guiWindow.setProgressBar(null, Thread.currentThread().hashCode());
734     if (nextfetch.size() > 0)
735     {
736       StringBuffer sb = new StringBuffer();
737       sb.append("Didn't retrieve the following "
738               + (nextfetch.size() == 1 ? "query" : nextfetch.size()
739                       + " queries") + ": \n");
740       int l = sb.length(), lr = 0;
741       for (String s : nextfetch)
742       {
743         if (l != sb.length())
744         {
745           sb.append("; ");
746         }
747         if (lr - sb.length() > 40)
748         {
749           sb.append("\n");
750         }
751         sb.append(s);
752       }
753       showErrorMessage(sb.toString());
754     }
755     resetDialog();
756   }
757
758   AlignmentI parseResult(String result, String title)
759   {
760     String format = new IdentifyFile().Identify(result, "Paste");
761     AlignmentI sequences = null;
762     if (FormatAdapter.isValidFormat(format))
763     {
764       sequences = null;
765       try
766       {
767         sequences = new FormatAdapter().readFile(result.toString(),
768                 "Paste", format);
769       } catch (Exception ex)
770       {
771       }
772
773       if (sequences != null)
774       {
775         return parseResult(sequences, title, format);
776       }
777     }
778     else
779     {
780       showErrorMessage("Error retrieving " + textArea.getText() + " from "
781               + database.getSelectedItem());
782     }
783
784     return null;
785   }
786
787   /**
788    * 
789    * @return a standard title for any results retrieved using the currently
790    *         selected source and settings
791    */
792   public String getDefaultRetrievalTitle()
793   {
794     return "Retrieved from " + database.getSelectedItem();
795   }
796
797   AlignmentI parseResult(AlignmentI al, String title,
798           String currentFileFormat)
799   {
800
801     if (al != null && al.getHeight() > 0)
802     {
803       if (title == null)
804       {
805         title = getDefaultRetrievalTitle();
806       }
807       if (alignFrame == null)
808       {
809         AlignFrame af = new AlignFrame(al, AlignFrame.DEFAULT_WIDTH,
810                 AlignFrame.DEFAULT_HEIGHT);
811         if (currentFileFormat != null)
812         {
813           af.currentFileFormat = currentFileFormat; // WHAT IS THE DEFAULT
814           // FORMAT FOR
815           // NON-FormatAdapter Sourced
816           // Alignments?
817         }
818
819         SequenceFeature[] sfs = null;
820         List<SequenceI> alsqs;
821         synchronized (alsqs = al.getSequences())
822         {
823           for (SequenceI sq : alsqs)
824           {
825             if ((sfs = sq.getSequenceFeatures()) != null)
826             {
827               if (sfs.length > 0)
828               {
829                 af.setShowSeqFeatures(true);
830                 break;
831               }
832             }
833
834           }
835         }
836         Desktop.addInternalFrame(af, title, AlignFrame.DEFAULT_WIDTH,
837                 AlignFrame.DEFAULT_HEIGHT);
838
839         af.statusBar.setText(MessageManager
840                 .getString("label.successfully_pasted_alignment_file"));
841
842         try
843         {
844           af.setMaximum(jalview.bin.Cache.getDefault("SHOW_FULLSCREEN",
845                   false));
846         } catch (Exception ex)
847         {
848         }
849       }
850       else
851       {
852         alignFrame.viewport.addAlignment(al, title);
853       }
854     }
855     return al;
856   }
857
858   void showErrorMessage(final String error)
859   {
860     resetDialog();
861     javax.swing.SwingUtilities.invokeLater(new Runnable()
862     {
863       @Override
864       public void run()
865       {
866         JOptionPane.showInternalMessageDialog(Desktop.desktop, error,
867                 MessageManager.getString("label.error_retrieving_data"),
868                 JOptionPane.WARNING_MESSAGE);
869       }
870     });
871   }
872
873   public IProgressIndicator getProgressIndicator()
874   {
875     return progressIndicator;
876   }
877
878   public void setProgressIndicator(IProgressIndicator progressIndicator)
879   {
880     this.progressIndicator = progressIndicator;
881   }
882 }