Clover icon

Coverage Report

  1. Project Clover database Tue Nov 18 2025 10:51:49 GMT
  2. Package jalview.gui

File SequenceFetcher.java

 

Coverage histogram

../../img/srcFileCovDistChart1.png
57% of files have more coverage

Code metrics

108
334
41
2
1,039
777
115
0.34
8.15
20.5
2.8

Classes

Class Line # Actions
SequenceFetcher 69 327 109
0.042553194.3%
SequenceFetcher.StringPair 71 7 6
0.00%
 

Contributing tests

This file is covered by 205 tests. .

Source view

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 java.awt.BorderLayout;
24    import java.awt.Font;
25    import java.awt.event.ActionEvent;
26    import java.awt.event.ActionListener;
27    import java.awt.event.KeyAdapter;
28    import java.awt.event.KeyEvent;
29    import java.util.ArrayList;
30    import java.util.Arrays;
31    import java.util.HashSet;
32    import java.util.Iterator;
33    import java.util.List;
34   
35    import javax.swing.JButton;
36    import javax.swing.JCheckBox;
37    import javax.swing.JComboBox;
38    import javax.swing.JInternalFrame;
39    import javax.swing.JLabel;
40    import javax.swing.JPanel;
41    import javax.swing.JScrollPane;
42    import javax.swing.JTextArea;
43    import javax.swing.SwingConstants;
44   
45    import jalview.api.FeatureSettingsModelI;
46    import jalview.bin.Cache;
47    import jalview.bin.Console;
48    import jalview.datamodel.AlignmentI;
49    import jalview.datamodel.DBRefEntry;
50    import jalview.datamodel.SequenceI;
51    import jalview.fts.core.GFTSPanel;
52    import jalview.fts.service.pdb.PDBFTSPanel;
53    import jalview.fts.service.threedbeacons.TDBeaconsFTSPanel;
54    import jalview.fts.service.uniprot.UniprotFTSPanel;
55    import jalview.io.FileFormatI;
56    import jalview.io.gff.SequenceOntologyI;
57    import jalview.util.DBRefUtils;
58    import jalview.util.MessageManager;
59    import jalview.util.Platform;
60    import jalview.ws.seqfetcher.DbSourceProxy;
61   
62    /**
63    * A panel where the use may choose a database source, and enter one or more
64    * accessions, to retrieve entries from the database.
65    * <p>
66    * If the selected source is Uniprot or PDB, a free text search panel is opened
67    * instead to perform the search and selection.
68    */
 
69    public class SequenceFetcher extends JPanel implements Runnable
70    {
 
71    private class StringPair
72    {
73    private String key;
74   
75    private String display;
76   
 
77  0 toggle public StringPair(String s1, String s2)
78    {
79  0 key = s1;
80  0 display = s2;
81    }
82   
 
83  0 toggle public StringPair(String s)
84    {
85  0 this(s, s);
86    }
87   
 
88  0 toggle public String getKey()
89    {
90  0 return key;
91    }
92   
 
93  0 toggle public String getDisplay()
94    {
95  0 return display;
96    }
97   
 
98  0 toggle @Override
99    public String toString()
100    {
101  0 return display;
102    }
103   
 
104  0 toggle public boolean equals(StringPair other)
105    {
106  0 return other.key == this.key;
107    }
108    }
109   
110    private static jalview.ws.SequenceFetcher sfetch = null;
111   
112    JLabel exampleAccession;
113   
114    JComboBox<StringPair> database;
115   
116    JCheckBox removeVersions = null;
117   
118    JCheckBox replacePunctuation;
119   
120    JButton okBtn;
121   
122    JButton exampleBtn;
123   
124    JButton closeBtn;
125   
126    JButton backBtn;
127   
128    JTextArea textArea;
129   
130    JInternalFrame frame;
131   
132    IProgressIndicator guiWindow;
133   
134    AlignFrame alignFrame;
135   
136    GFTSPanel parentSearchPanel;
137   
138    IProgressIndicator progressIndicator;
139   
140    volatile boolean _isConstructing = false;
141   
142    /**
143    * Returns the shared instance of the SequenceFetcher client
144    *
145    * @return
146    */
 
147  1775 toggle public static jalview.ws.SequenceFetcher getSequenceFetcherSingleton()
148    {
149  1775 if (sfetch == null)
150    {
151  6 sfetch = new jalview.ws.SequenceFetcher();
152    }
153  1775 return sfetch;
154    }
155   
156    /**
157    * Constructor given a client to receive any status or progress messages
158    * (currently either the Desktop, or an AlignFrame panel)
159    *
160    * @param guiIndic
161    */
 
162  0 toggle public SequenceFetcher(IProgressIndicator guiIndic)
163    {
164  0 this(guiIndic, null, null);
165    }
166   
167    /**
168    * Constructor with specified database and accession(s) to retrieve
169    *
170    * @param guiIndic
171    * @param selectedDb
172    * @param queryString
173    */
 
174  0 toggle public SequenceFetcher(IProgressIndicator guiIndic,
175    final String selectedDb, final String queryString)
176    {
177  0 this.progressIndicator = guiIndic;
178  0 getSequenceFetcherSingleton();
179  0 this.guiWindow = progressIndicator;
180   
181  0 if (progressIndicator instanceof AlignFrame)
182    {
183  0 alignFrame = (AlignFrame) progressIndicator;
184    }
185   
186  0 jbInit(selectedDb);
187  0 textArea.setText(queryString);
188   
189  0 frame = new JInternalFrame();
190  0 frame.setContentPane(this);
191  0 frame.setFrameIcon(null);
192  0 Desktop.addInternalFrame(frame, getFrameTitle(), true, 400,
193  0 Platform.isAMacAndNotJS() ? 240 : 180);
194    }
195   
 
196  0 toggle private String getFrameTitle()
197    {
198  0 return ((alignFrame == null)
199    ? MessageManager.getString("label.new_sequence_fetcher")
200    : MessageManager
201    .getString("label.additional_sequence_fetcher"));
202    }
203   
 
204  0 toggle private void jbInit(String selectedDb)
205    {
206  0 this.setLayout(new BorderLayout());
207   
208  0 removeVersions = new JCheckBox(MessageManager
209    .getString("label.remove_version_numbers_from_ids"));
210  0 removeVersions.setHorizontalAlignment(SwingConstants.LEFT);
211  0 removeVersions.setFont(new Font("Verdana", Font.ITALIC, 11));
212  0 boolean removeVersionsDefault = Cache
213    .getDefault("REMOVE_VERSION_FROM_IDENTIFIERS_DEFAULT", true);
214  0 removeVersions.setSelected(removeVersionsDefault);
215  0 removeVersions.setEnabled(false);
216  0 removeVersions.setVisible(false);
217   
218  0 database = new JComboBox<>();
219  0 database.setFont(JvSwingUtils.getLabelFont());
220  0 StringPair instructionItem = new StringPair(
221    MessageManager.getString("action.select_ddbb"));
222  0 database.setPrototypeDisplayValue(instructionItem);
223  0 String[] sources = new jalview.ws.SequenceFetcher().getSupportedDb();
224  0 Arrays.sort(sources, String.CASE_INSENSITIVE_ORDER);
225  0 database.addItem(instructionItem);
226  0 for (String source : sources)
227    {
228  0 List<DbSourceProxy> slist = sfetch.getSourceProxy(source);
229  0 if (slist.size() == 1 && slist.get(0) != null)
230    {
231  0 database.addItem(new StringPair(source, slist.get(0).getDbName()));
232    }
233    else
234    {
235  0 database.addItem(new StringPair(source));
236    }
237    }
238  0 setDatabaseSelectedItem(selectedDb);
239  0 if (database.getSelectedIndex() == -1)
240    {
241  0 database.setSelectedIndex(0);
242    }
243  0 database.setMaximumRowCount(database.getItemCount());
244  0 database.addActionListener(new ActionListener()
245    {
 
246  0 toggle @Override
247    public void actionPerformed(ActionEvent e)
248    {
249  0 String currentSelection = ((StringPair) database.getSelectedItem())
250    .getKey();
251  0 updateExampleQuery(currentSelection);
252   
253  0 boolean showRemoveVersions = false;
254  0 if ("pdb".equalsIgnoreCase(currentSelection))
255    {
256  0 frame.dispose();
257  0 new PDBFTSPanel(SequenceFetcher.this);
258    }
259  0 else if ("uniprot".equalsIgnoreCase(currentSelection))
260    {
261  0 frame.dispose();
262  0 new UniprotFTSPanel(SequenceFetcher.this);
263  0 showRemoveVersions = true;
264    }
265  0 else if ("3d-beacons".equalsIgnoreCase(currentSelection))
266    {
267  0 frame.dispose();
268  0 new TDBeaconsFTSPanel(SequenceFetcher.this);
269    }
270    else
271    {
272  0 otherSourceAction();
273    }
274   
275  0 removeVersions.setEnabled(showRemoveVersions);
276  0 removeVersions.setVisible(showRemoveVersions);
277    }
278    });
279   
280  0 exampleAccession = new JLabel("");
281  0 exampleAccession.setFont(new Font("Verdana", Font.BOLD, 11));
282  0 JLabel jLabel1 = new JLabel(MessageManager
283    .getString("label.separate_multiple_accession_ids"));
284  0 jLabel1.setFont(new Font("Verdana", Font.ITALIC, 11));
285  0 jLabel1.setHorizontalAlignment(SwingConstants.LEFT);
286   
287  0 replacePunctuation = new JCheckBox(
288    MessageManager.getString("label.replace_commas_semicolons"));
289  0 replacePunctuation.setHorizontalAlignment(SwingConstants.LEFT);
290  0 replacePunctuation.setFont(new Font("Verdana", Font.ITALIC, 11));
291  0 okBtn = new JButton(MessageManager.getString("action.ok"));
292  0 okBtn.addActionListener(new ActionListener()
293    {
 
294  0 toggle @Override
295    public void actionPerformed(ActionEvent e)
296    {
297  0 ok_actionPerformed();
298    }
299    });
300  0 JButton clear = new JButton(MessageManager.getString("action.clear"));
301  0 clear.addActionListener(new ActionListener()
302    {
 
303  0 toggle @Override
304    public void actionPerformed(ActionEvent e)
305    {
306  0 clear_actionPerformed();
307    }
308    });
309   
310  0 exampleBtn = new JButton(MessageManager.getString("label.example"));
311  0 exampleBtn.addActionListener(new ActionListener()
312    {
 
313  0 toggle @Override
314    public void actionPerformed(ActionEvent e)
315    {
316  0 example_actionPerformed();
317    }
318    });
319  0 closeBtn = new JButton(MessageManager.getString("action.cancel"));
320  0 closeBtn.addActionListener(new ActionListener()
321    {
 
322  0 toggle @Override
323    public void actionPerformed(ActionEvent e)
324    {
325  0 close_actionPerformed(e);
326    }
327    });
328  0 backBtn = new JButton(MessageManager.getString("action.back"));
329  0 backBtn.addActionListener(new ActionListener()
330    {
 
331  0 toggle @Override
332    public void actionPerformed(ActionEvent e)
333    {
334  0 parentSearchPanel.btn_back_ActionPerformed();
335    }
336    });
337    // back not visible unless embedded
338  0 backBtn.setVisible(false);
339   
340  0 textArea = new JTextArea();
341  0 textArea.setFont(JvSwingUtils.getLabelFont());
342  0 textArea.setLineWrap(true);
343  0 textArea.addKeyListener(new KeyAdapter()
344    {
 
345  0 toggle @Override
346    public void keyPressed(KeyEvent e)
347    {
348  0 if (e.getKeyCode() == KeyEvent.VK_ENTER)
349    {
350  0 ok_actionPerformed();
351    }
352    }
353    });
354   
355  0 JPanel actionPanel = new JPanel();
356  0 actionPanel.add(backBtn);
357  0 actionPanel.add(exampleBtn);
358  0 actionPanel.add(clear);
359  0 actionPanel.add(okBtn);
360  0 actionPanel.add(closeBtn);
361   
362  0 JPanel databasePanel = new JPanel();
363  0 databasePanel.setLayout(new BorderLayout());
364  0 databasePanel.add(database, BorderLayout.NORTH);
365  0 databasePanel.add(exampleAccession, BorderLayout.CENTER);
366  0 JPanel jPanel2a = new JPanel(new BorderLayout());
367  0 jPanel2a.add(jLabel1, BorderLayout.NORTH);
368  0 jPanel2a.add(removeVersions, BorderLayout.CENTER);
369  0 jPanel2a.add(replacePunctuation, BorderLayout.SOUTH);
370  0 databasePanel.add(jPanel2a, BorderLayout.SOUTH);
371   
372  0 JPanel idsPanel = new JPanel();
373  0 idsPanel.setLayout(new BorderLayout(0, 5));
374  0 JScrollPane jScrollPane1 = new JScrollPane();
375  0 jScrollPane1.getViewport().add(textArea);
376  0 idsPanel.add(jScrollPane1, BorderLayout.CENTER);
377   
378  0 this.add(actionPanel, BorderLayout.SOUTH);
379  0 this.add(idsPanel, BorderLayout.CENTER);
380  0 this.add(databasePanel, BorderLayout.NORTH);
381    }
382   
 
383  0 toggle private void setDatabaseSelectedItem(String db)
384    {
385  0 for (int i = 0; i < database.getItemCount(); i++)
386    {
387  0 StringPair sp = database.getItemAt(i);
388  0 if (sp != null && db != null && db.equals(sp.getKey()))
389    {
390  0 database.setSelectedIndex(i);
391  0 return;
392    }
393    }
394    }
395   
396    /**
397    * Answers a semi-colon-delimited string with the example query or queries for
398    * the selected database
399    *
400    * @param db
401    * @return
402    */
 
403  0 toggle protected String getExampleQueries(String db)
404    {
405  0 StringBuilder sb = new StringBuilder();
406  0 HashSet<String> hs = new HashSet<>();
407  0 for (DbSourceProxy dbs : sfetch.getSourceProxy(db))
408    {
409  0 String tq = dbs.getTestQuery();
410  0 if (hs.add(tq)) // not a duplicate source
411    {
412  0 if (sb.length() > 0)
413    {
414  0 sb.append(";");
415    }
416  0 sb.append(tq);
417    }
418    }
419  0 return sb.toString();
420    }
421   
422    /**
423    * Action on selecting a database other than Uniprot or PDB is to enable or
424    * disable 'Replace commas', and await input in the query field
425    */
 
426  0 toggle protected void otherSourceAction()
427    {
428  0 try
429    {
430  0 String eq = exampleAccession.getText();
431    // TODO this should be a property of the SequenceFetcher whether commas
432    // are allowed in the IDs...
433   
434  0 boolean enablePunct = !(eq != null && eq.indexOf(",") > -1);
435  0 replacePunctuation.setEnabled(enablePunct);
436   
437    } catch (Exception ex)
438    {
439  0 exampleAccession.setText("");
440  0 replacePunctuation.setEnabled(true);
441    }
442  0 repaint();
443    }
444   
445    /**
446    * Sets the text of the example query to incorporate the example accession
447    * provided by the selected database source
448    *
449    * @param selectedDatabase
450    * @return
451    */
 
452  0 toggle protected String updateExampleQuery(String selectedDatabase)
453    {
454  0 String eq = getExampleQueries(selectedDatabase);
455  0 exampleAccession.setText(MessageManager
456    .formatMessage("label.example_query_param", new String[]
457    { eq }));
458  0 return eq;
459    }
460   
461    /**
462    * Action on clicking the 'Example' button is to write the example accession
463    * as the query text field value
464    */
 
465  0 toggle protected void example_actionPerformed()
466    {
467  0 String eq = getExampleQueries(
468    ((StringPair) database.getSelectedItem()).getKey());
469  0 textArea.setText(eq);
470  0 repaint();
471    }
472   
473    /**
474    * Clears the query input field
475    */
 
476  0 toggle protected void clear_actionPerformed()
477    {
478  0 textArea.setText("");
479  0 repaint();
480    }
481   
482    /**
483    * Action on Close button is to close this frame, and also (if it is embedded
484    * in a search panel) to close the search panel
485    *
486    * @param e
487    */
 
488  0 toggle protected void close_actionPerformed(ActionEvent e)
489    {
490  0 try
491    {
492  0 frame.setClosed(true);
493  0 if (parentSearchPanel != null)
494    {
495  0 parentSearchPanel.btn_cancel_ActionPerformed();
496    }
497    } catch (Exception ex)
498    {
499    }
500    }
501   
502    /**
503    * Action on OK is to start the fetch for entered accession(s)
504    */
 
505  0 toggle public void ok_actionPerformed()
506    {
507    /*
508    * tidy inputs and check there is something to search for
509    */
510  0 String t0 = textArea.getText();
511  0 String text = replaceQueryText(t0,
512    replacePunctuation.isEnabled()
513    && replacePunctuation.isSelected(),
514    removeVersions.isEnabled() && removeVersions.isSelected());
515  0 if (!t0.equals(text))
516    {
517  0 textArea.setText(text);
518    }
519  0 if (text.isEmpty())
520    {
521    // todo i18n
522  0 showErrorMessage(
523    "Please enter a (semi-colon separated list of) database id(s)");
524  0 resetDialog();
525  0 return;
526    }
527  0 if (database.getSelectedIndex() == 0)
528    {
529    // todo i18n
530  0 showErrorMessage("Please choose a database");
531  0 resetDialog();
532  0 return;
533    }
534   
535  0 exampleBtn.setEnabled(false);
536  0 textArea.setEnabled(false);
537  0 okBtn.setEnabled(false);
538  0 closeBtn.setEnabled(false);
539  0 backBtn.setEnabled(false);
540   
541  0 Thread worker = new Thread(this);
542  0 worker.start();
543    }
544   
 
545  24 toggle protected static String replaceQueryText(String text0,
546    boolean replaceSemiColons, boolean removeVersions)
547    {
548  24 String text = text0.trim();
549  24 if (replaceSemiColons)
550    {
551  12 text = text.replace(",", ";");
552    }
553  24 text = text.replaceAll("(\\s|[; ])+", ";");
554  24 if (removeVersions)
555    {
556  12 Console.debug("search text was '" + text + "'");
557    // remove all *last* .123 from an ID. (ID is terminated just before a
558    // non-alphanumeric-or-dot [which is replaced] or end of string)
559  12 text = text.replaceAll("\\.[0-9]+([^0-9a-zA-Z\\.]|$)", "$1");
560    /* or do we want:
561    // remove everything after a first .123.45.6 in an ID
562    text = text.replaceAll("\\.[0-9\\.]+", "");
563    */
564  12 Console.debug("search text now '" + text + "'");
565    }
566  24 return text;
567    }
568   
 
569  0 toggle private void resetDialog()
570    {
571  0 exampleBtn.setEnabled(true);
572  0 textArea.setEnabled(true);
573  0 okBtn.setEnabled(true);
574  0 closeBtn.setEnabled(true);
575  0 backBtn.setEnabled(parentSearchPanel != null);
576    }
577   
 
578  0 toggle @Override
579    public void run()
580    {
581  0 boolean addToLast = false;
582  0 List<String> aresultq = new ArrayList<>();
583  0 List<String> presultTitle = new ArrayList<>();
584  0 List<AlignmentI> presult = new ArrayList<>();
585  0 List<AlignmentI> aresult = new ArrayList<>();
586  0 List<DbSourceProxy> sources = sfetch.getSourceProxy(
587    ((StringPair) database.getSelectedItem()).getKey());
588  0 Iterator<DbSourceProxy> proxies = sources.iterator();
589  0 String[] qries = textArea.getText().trim().split(";");
590  0 List<String> nextFetch = Arrays.asList(qries);
591  0 Iterator<String> en = Arrays.asList(new String[0]).iterator();
592  0 int nqueries = qries.length;
593   
594  0 FeatureSettingsModelI preferredFeatureColours = null;
595  0 while (proxies.hasNext() && (en.hasNext() || nextFetch.size() > 0))
596    {
597  0 if (!en.hasNext() && nextFetch.size() > 0)
598    {
599  0 en = nextFetch.iterator();
600  0 nqueries = nextFetch.size();
601    // save the remaining queries in the original array
602  0 qries = nextFetch.toArray(new String[nqueries]);
603  0 nextFetch = new ArrayList<>();
604    }
605   
606  0 DbSourceProxy proxy = proxies.next();
607  0 try
608    {
609    // update status
610  0 guiWindow.setProgressBar(MessageManager.formatMessage(
611    "status.fetching_sequence_queries_from", new String[]
612    { Integer.valueOf(nqueries).toString(),
613    proxy.getDbName() }),
614    Thread.currentThread().hashCode());
615  0 if (proxy.getMaximumQueryCount() == 1)
616    {
617    /*
618    * proxy only handles one accession id at a time
619    */
620  0 while (en.hasNext())
621    {
622  0 String acc = en.next();
623  0 if (!fetchSingleAccession(proxy, acc, aresultq, aresult))
624    {
625  0 nextFetch.add(acc);
626    }
627    }
628    }
629    else
630    {
631    /*
632    * proxy can fetch multiple accessions at one time
633    */
634  0 fetchMultipleAccessions(proxy, en, aresultq, aresult, nextFetch);
635    }
636    } catch (Exception e)
637    {
638  0 showErrorMessage("Error retrieving " + textArea.getText() + " from "
639    + ((StringPair) database.getSelectedItem()).getDisplay());
640    // error
641    // +="Couldn't retrieve sequences from "+database.getSelectedItem();
642  0 jalview.bin.Console.errPrintln("Retrieval failed for source ='"
643    + ((StringPair) database.getSelectedItem()).getDisplay()
644    + "' and query\n'" + textArea.getText() + "'\n");
645  0 e.printStackTrace();
646    } catch (OutOfMemoryError e)
647    {
648  0 showErrorMessage("Out of Memory when retrieving "
649    + textArea.getText() + " from "
650    + ((StringPair) database.getSelectedItem()).getDisplay()
651    + "\nPlease see the Jalview FAQ for instructions for increasing the memory available to Jalview.\n");
652  0 e.printStackTrace();
653    } catch (Error e)
654    {
655  0 showErrorMessage("Serious Error retrieving " + textArea.getText()
656    + " from "
657    + ((StringPair) database.getSelectedItem()).getDisplay());
658  0 e.printStackTrace();
659    }
660   
661    // Stack results ready for opening in alignment windows
662  0 if (aresult != null && aresult.size() > 0)
663    {
664  0 FeatureSettingsModelI proxyColourScheme = proxy
665    .getFeatureColourScheme();
666  0 if (proxyColourScheme != null)
667    {
668  0 preferredFeatureColours = proxyColourScheme;
669    }
670   
671  0 AlignmentI ar = null;
672  0 if (proxy.isAlignmentSource())
673    {
674  0 addToLast = false;
675    // new window for each result
676  0 while (aresult.size() > 0)
677    {
678  0 presult.add(aresult.remove(0));
679  0 presultTitle.add(
680    aresultq.remove(0) + " " + getDefaultRetrievalTitle());
681    }
682    }
683    else
684    {
685  0 String titl = null;
686  0 if (addToLast && presult.size() > 0)
687    {
688  0 ar = presult.remove(presult.size() - 1);
689  0 titl = presultTitle.remove(presultTitle.size() - 1);
690    }
691    // concatenate all results in one window
692  0 while (aresult.size() > 0)
693    {
694  0 if (ar == null)
695    {
696  0 ar = aresult.remove(0);
697    }
698    else
699    {
700  0 ar.append(aresult.remove(0));
701    }
702    }
703  0 addToLast = true;
704  0 presult.add(ar);
705  0 presultTitle.add(titl);
706    }
707    }
708  0 guiWindow.setProgressBar(
709    MessageManager.getString("status.finshed_querying"),
710    Thread.currentThread().hashCode());
711    }
712  0 guiWindow
713    .setProgressBar(
714  0 (presult.size() > 0)
715    ? MessageManager
716    .getString("status.parsing_results")
717    : MessageManager.getString("status.processing"),
718    Thread.currentThread().hashCode());
719    // process results
720  0 while (presult.size() > 0)
721    {
722  0 parseResult(presult.remove(0), presultTitle.remove(0), null,
723    preferredFeatureColours);
724    }
725    // only remove visual delay after we finished parsing.
726  0 guiWindow.setProgressBar(null, Thread.currentThread().hashCode());
727  0 if (nextFetch.size() > 0)
728    {
729  0 StringBuffer sb = new StringBuffer();
730  0 sb.append("Didn't retrieve the following "
731  0 + (nextFetch.size() == 1 ? "query"
732    : nextFetch.size() + " queries")
733    + ": \n");
734  0 int l = sb.length(), lr = 0;
735  0 for (String s : nextFetch)
736    {
737  0 if (l != sb.length())
738    {
739  0 sb.append("; ");
740    }
741  0 if (lr - sb.length() > 40)
742    {
743  0 sb.append("\n");
744    }
745  0 sb.append(s);
746    }
747  0 showErrorMessage(sb.toString());
748    }
749  0 resetDialog();
750    }
751   
752    /**
753    * Tries to fetch one or more accession ids from the database proxy
754    *
755    * @param proxy
756    * @param accessions
757    * the queries to fetch
758    * @param aresultq
759    * a successful queries list to add to
760    * @param aresult
761    * a list of retrieved alignments to add to
762    * @param nextFetch
763    * failed queries are added to this list
764    * @throws Exception
765    */
 
766  0 toggle void fetchMultipleAccessions(DbSourceProxy proxy,
767    Iterator<String> accessions, List<String> aresultq,
768    List<AlignmentI> aresult, List<String> nextFetch) throws Exception
769    {
770  0 StringBuilder multiacc = new StringBuilder();
771  0 List<String> tosend = new ArrayList<>();
772  0 while (accessions.hasNext())
773    {
774  0 String nel = accessions.next();
775  0 tosend.add(nel);
776  0 multiacc.append(nel);
777  0 if (accessions.hasNext())
778    {
779  0 multiacc.append(proxy.getAccessionSeparator());
780    }
781    }
782   
783  0 try
784    {
785  0 String query = multiacc.toString();
786  0 AlignmentI rslt = proxy.getSequenceRecords(query);
787  0 if (rslt == null || rslt.getHeight() == 0)
788    {
789    // no results - pass on all queries to next source
790  0 nextFetch.addAll(tosend);
791    }
792    else
793    {
794  0 aresultq.add(query);
795  0 aresult.add(rslt);
796  0 if (tosend.size() > 1)
797    {
798  0 checkResultForQueries(rslt, tosend, nextFetch, proxy);
799    }
800    }
801    } catch (OutOfMemoryError oome)
802    {
803  0 new OOMWarning("fetching " + multiacc + " from "
804    + ((StringPair) database.getSelectedItem()).getDisplay(),
805    oome, this);
806    }
807    }
808   
809    /**
810    * Query for a single accession id via the database proxy
811    *
812    * @param proxy
813    * @param accession
814    * @param aresultq
815    * a list of successful queries to add to
816    * @param aresult
817    * a list of retrieved alignments to add to
818    * @return true if the fetch was successful, else false
819    */
 
820  0 toggle boolean fetchSingleAccession(DbSourceProxy proxy, String accession,
821    List<String> aresultq, List<AlignmentI> aresult)
822    {
823  0 boolean success = false;
824  0 try
825    {
826  0 if (aresult != null)
827    {
828  0 try
829    {
830    // give the server a chance to breathe
831  0 Thread.sleep(5);
832    } catch (Exception e)
833    {
834    //
835    }
836    }
837   
838  0 AlignmentI indres = null;
839  0 try
840    {
841  0 indres = proxy.getSequenceRecords(accession);
842    } catch (OutOfMemoryError oome)
843    {
844  0 new OOMWarning(
845    "fetching " + accession + " from " + proxy.getDbName(),
846    oome, this);
847    }
848  0 if (indres != null)
849    {
850  0 aresultq.add(accession);
851  0 aresult.add(indres);
852  0 success = true;
853    }
854    } catch (Exception e)
855    {
856  0 Console.info("Error retrieving " + accession + " from "
857    + proxy.getDbName(), e);
858    }
859  0 return success;
860    }
861   
862    /**
863    * Checks which of the queries were successfully retrieved by searching the
864    * DBRefs of the retrieved sequences for a match. Any not found are added to
865    * the 'nextFetch' list.
866    *
867    * @param rslt
868    * @param queries
869    * @param nextFetch
870    * @param proxy
871    */
 
872  0 toggle void checkResultForQueries(AlignmentI rslt, List<String> queries,
873    List<String> nextFetch, DbSourceProxy proxy)
874    {
875  0 SequenceI[] rs = rslt.getSequencesArray();
876   
877  0 for (String q : queries)
878    {
879    // BH 2019.01.25 dbr is never used.
880    // DBRefEntry dbr = new DBRefEntry();
881    // dbr.setSource(proxy.getDbSource());
882    // dbr.setVersion(null);
883  0 String accId = proxy.getAccessionIdFromQuery(q);
884    // dbr.setAccessionId(accId);
885  0 boolean rfound = false;
886  0 for (int r = 0, nr = rs.length; r < nr; r++)
887    {
888  0 if (rs[r] != null)
889    {
890  0 List<DBRefEntry> found = DBRefUtils.searchRefs(rs[r].getDBRefs(),
891    accId);
892  0 if (!found.isEmpty())
893    {
894  0 rfound = true;
895  0 break;
896    }
897    }
898    }
899  0 if (!rfound)
900    {
901  0 nextFetch.add(q);
902    }
903    }
904    }
905   
906    /**
907    *
908    * @return a standard title for any results retrieved using the currently
909    * selected source and settings
910    */
 
911  0 toggle public String getDefaultRetrievalTitle()
912    {
913  0 return "Retrieved from "
914    + ((StringPair) database.getSelectedItem()).getDisplay();
915    }
916   
917    /**
918    * constructs an alignment frame given the data and metadata
919    *
920    * @param al
921    * @param title
922    * @param currentFileFormat
923    * @param preferredFeatureColours
924    * @return the alignment
925    */
 
926  0 toggle public AlignmentI parseResult(AlignmentI al, String title,
927    FileFormatI currentFileFormat,
928    FeatureSettingsModelI preferredFeatureColours)
929    {
930   
931  0 if (al != null && al.getHeight() > 0)
932    {
933  0 if (title == null)
934    {
935  0 title = getDefaultRetrievalTitle();
936    }
937  0 if (alignFrame == null)
938    {
939  0 AlignFrame af = new AlignFrame(al, AlignFrame.DEFAULT_WIDTH,
940    AlignFrame.DEFAULT_HEIGHT);
941  0 if (currentFileFormat != null)
942    {
943  0 af.currentFileFormat = currentFileFormat;
944    }
945   
946  0 List<SequenceI> alsqs = al.getSequences();
947  0 synchronized (alsqs)
948    {
949  0 for (SequenceI sq : alsqs)
950    {
951  0 if (sq.getFeatures().hasFeatures())
952    {
953  0 af.setShowSeqFeatures(true);
954  0 break;
955    }
956    }
957    }
958   
959  0 af.getViewport().applyFeaturesStyle(preferredFeatureColours);
960  0 if (Cache.getDefault("HIDE_INTRONS", true))
961    {
962  0 af.hideFeatureColumns(SequenceOntologyI.EXON, false);
963    }
964  0 af.alignPanel.alignmentChanged(); // 11th hour patch for JAL-4594
965  0 Desktop.addInternalFrame(af, title, AlignFrame.DEFAULT_WIDTH,
966    AlignFrame.DEFAULT_HEIGHT);
967   
968  0 af.setStatus(MessageManager
969    .getString("label.successfully_pasted_alignment_file"));
970   
971  0 try
972    {
973  0 af.setMaximum(Cache.getDefault("SHOW_FULLSCREEN", false));
974    } catch (Exception ex)
975    {
976    }
977    }
978    else
979    {
980  0 alignFrame.viewport.addAlignment(al, title);
981    }
982    }
983  0 return al;
984    }
985   
 
986  0 toggle void showErrorMessage(final String error)
987    {
988  0 resetDialog();
989  0 javax.swing.SwingUtilities.invokeLater(new Runnable()
990    {
 
991  0 toggle @Override
992    public void run()
993    {
994  0 JvOptionPane.showInternalMessageDialog(Desktop.desktop, error,
995    MessageManager.getString("label.error_retrieving_data"),
996    JvOptionPane.WARNING_MESSAGE);
997    }
998    });
999    }
1000   
 
1001  0 toggle public IProgressIndicator getProgressIndicator()
1002    {
1003  0 return progressIndicator;
1004    }
1005   
 
1006  0 toggle public void setProgressIndicator(IProgressIndicator progressIndicator)
1007    {
1008  0 this.progressIndicator = progressIndicator;
1009    }
1010   
1011    /**
1012    * Hide this panel (on clicking the database button to open the database
1013    * chooser)
1014    */
 
1015  0 toggle void hidePanel()
1016    {
1017  0 frame.setVisible(false);
1018    }
1019   
 
1020  0 toggle public void setQuery(String ids)
1021    {
1022  0 textArea.setText(ids);
1023    }
1024   
1025    /**
1026    * Called to modify the search panel for embedding as an alternative tab of a
1027    * free text search panel. The database choice list is hidden (since the
1028    * choice has been made), and a Back button is made visible (which reopens the
1029    * Sequence Fetcher panel).
1030    *
1031    * @param parentPanel
1032    */
 
1033  0 toggle public void embedIn(GFTSPanel parentPanel)
1034    {
1035  0 database.setVisible(false);
1036  0 backBtn.setVisible(true);
1037  0 parentSearchPanel = parentPanel;
1038    }
1039    }