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