X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fjalview%2Fgui%2FSequenceFetcher.java;h=45d944df495781e0f1eb80e5de296c98085f5e56;hb=2f8f4850cd8437b7c2a2450df2391426aaa3e1b8;hp=6687020665eccf454053aba9f36cafb00a0ed203;hpb=7123652dcf889fca74cb7e8c52ba24e845abfc34;p=jalview.git diff --git a/src/jalview/gui/SequenceFetcher.java b/src/jalview/gui/SequenceFetcher.java index 6687020..3b93059 100755 --- a/src/jalview/gui/SequenceFetcher.java +++ b/src/jalview/gui/SequenceFetcher.java @@ -1,556 +1,942 @@ /* - * Jalview - A Sequence Alignment Editor and Viewer - * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors + * + * This file is part of Jalview. + * + * Jalview is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * + * + * Jalview is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * along with Jalview. If not, see . + * The Jalview Authors are detailed in the 'AUTHORS' file. */ package jalview.gui; -import java.io.*; -import java.util.*; +import java.awt.BorderLayout; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; + +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JInternalFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.SwingConstants; + +import jalview.api.FeatureSettingsModelI; +import jalview.bin.Cache; +import jalview.bin.Console; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.DBRefEntry; +import jalview.datamodel.SequenceI; +import jalview.fts.core.GFTSPanel; +import jalview.fts.service.pdb.PDBFTSPanel; +import jalview.fts.service.threedbeacons.TDBeaconsFTSPanel; +import jalview.fts.service.uniprot.UniprotFTSPanel; +import jalview.io.FileFormatI; +import jalview.io.gff.SequenceOntologyI; +import jalview.util.DBRefUtils; +import jalview.util.MessageManager; +import jalview.util.Platform; +import jalview.ws.seqfetcher.DbSourceProxy; + +/** + * A panel where the use may choose a database source, and enter one or more + * accessions, to retrieve entries from the database. + *

+ * If the selected source is Uniprot or PDB, a free text search panel is opened + * instead to perform the search and selection. + */ +public class SequenceFetcher extends JPanel implements Runnable +{ + private class StringPair + { + private String key; -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; + private String display; -import MCview.*; -import jalview.datamodel.*; -import jalview.datamodel.xdb.embl.*; -import jalview.analysis.*; -import java.io.File; -import jalview.io.*; + public StringPair(String s1, String s2) + { + key = s1; + display = s2; + } -public class SequenceFetcher -extends JPanel implements Runnable -{ - JInternalFrame frame; - AlignFrame alignFrame; - StringBuffer result; - final String noDbSelected = "-- Select Database --"; - public SequenceFetcher(AlignFrame af) - { - alignFrame = af; - database.addItem(noDbSelected); - database.addItem("Uniprot"); - database.addItem("EMBL"); - database.addItem("EMBLCDS"); - database.addItem("PDB"); - database.addItem("PFAM"); + public StringPair(String s) + { + this(s, s); + } - try + public String getKey() { - jbInit(); + return key; } - catch (Exception ex) + + public String getDisplay() { - ex.printStackTrace(); + return display; } - frame = new JInternalFrame(); - frame.setContentPane(this); - if (System.getProperty("os.name").startsWith("Mac")) + @Override + public String toString() + { + return display; + } + + public boolean equals(StringPair other) + { + return other.key == this.key; + } + } + + private static jalview.ws.SequenceFetcher sfetch = null; + + JLabel exampleAccession; + + JComboBox database; + + JCheckBox replacePunctuation; + + JButton okBtn; + + JButton exampleBtn; + + JButton closeBtn; + + JButton backBtn; + + JTextArea textArea; + + JInternalFrame frame; + + IProgressIndicator guiWindow; + + AlignFrame alignFrame; + + GFTSPanel parentSearchPanel; + + IProgressIndicator progressIndicator; + + volatile boolean _isConstructing = false; + + /** + * Returns the shared instance of the SequenceFetcher client + * + * @return + */ + public static jalview.ws.SequenceFetcher getSequenceFetcherSingleton() + { + if (sfetch == null) { - Desktop.addInternalFrame(frame, getFrameTitle(), 400, 140); + sfetch = new jalview.ws.SequenceFetcher(); } - else + return sfetch; + } + + /** + * Constructor given a client to receive any status or progress messages + * (currently either the Desktop, or an AlignFrame panel) + * + * @param guiIndic + */ + public SequenceFetcher(IProgressIndicator guiIndic) + { + this(guiIndic, null, null); + } + + /** + * Constructor with specified database and accession(s) to retrieve + * + * @param guiIndic + * @param selectedDb + * @param queryString + */ + public SequenceFetcher(IProgressIndicator guiIndic, + final String selectedDb, final String queryString) + { + this.progressIndicator = guiIndic; + getSequenceFetcherSingleton(); + this.guiWindow = progressIndicator; + + if (progressIndicator instanceof AlignFrame) { - Desktop.addInternalFrame(frame, getFrameTitle(), 400, 125); + alignFrame = (AlignFrame) progressIndicator; } + + jbInit(selectedDb); + textArea.setText(queryString); + + frame = new JInternalFrame(); + frame.setContentPane(this); + frame.setFrameIcon(WindowIcons.fetchIcon); + Desktop.addInternalFrame(frame, getFrameTitle(), true, 400, + Platform.isAMacAndNotJS() ? 240 : 180); } private String getFrameTitle() { - return ( (alignFrame == null) ? "New " : "Additional ") + - "Sequence Fetcher"; + return ((alignFrame == null) + ? MessageManager.getString("label.new_sequence_fetcher") + : MessageManager + .getString("label.additional_sequence_fetcher")); } - private void jbInit() - throws Exception + private void jbInit(String selectedDb) { - this.setLayout(gridBagLayout1); + this.setLayout(new BorderLayout()); + + database = new JComboBox<>(); + database.setFont(JvSwingUtils.getLabelFont()); + StringPair instructionItem = new StringPair( + MessageManager.getString("action.select_ddbb")); + database.setPrototypeDisplayValue(instructionItem); + String[] sources = new jalview.ws.SequenceFetcher().getSupportedDb(); + Arrays.sort(sources, String.CASE_INSENSITIVE_ORDER); + database.addItem(instructionItem); + for (String source : sources) + { + List slist = sfetch.getSourceProxy(source); + if (slist.size() == 1 && slist.get(0) != null) + { + database.addItem(new StringPair(source, slist.get(0).getDbName())); + } + else + { + database.addItem(new StringPair(source)); + } + } + setDatabaseSelectedItem(selectedDb); + if (database.getSelectedIndex() == -1) + { + database.setSelectedIndex(0); + } + database.setMaximumRowCount(database.getItemCount()); + database.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + String currentSelection = ((StringPair) database.getSelectedItem()) + .getKey(); + updateExampleQuery(currentSelection); + + if ("pdb".equalsIgnoreCase(currentSelection)) + { + frame.dispose(); + new PDBFTSPanel(SequenceFetcher.this); + } + else if ("uniprot".equalsIgnoreCase(currentSelection)) + { + frame.dispose(); + new UniprotFTSPanel(SequenceFetcher.this); + } + else if ("3d-beacons".equalsIgnoreCase(currentSelection)) + { + frame.dispose(); + new TDBeaconsFTSPanel(SequenceFetcher.this); + } + else + { + otherSourceAction(); + } + } + }); + + exampleAccession = new JLabel(""); + exampleAccession.setFont(new Font("Verdana", Font.BOLD, 11)); + JLabel jLabel1 = new JLabel(MessageManager + .getString("label.separate_multiple_accession_ids")); + jLabel1.setFont(new Font("Verdana", Font.ITALIC, 11)); + jLabel1.setHorizontalAlignment(SwingConstants.LEFT); + + replacePunctuation = new JCheckBox( + MessageManager.getString("label.replace_commas_semicolons")); + replacePunctuation.setHorizontalAlignment(SwingConstants.LEFT); + replacePunctuation.setFont(new Font("Verdana", Font.ITALIC, 11)); + okBtn = new JButton(MessageManager.getString("action.ok")); + okBtn.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + ok_actionPerformed(); + } + }); + JButton clear = new JButton(MessageManager.getString("action.clear")); + clear.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + clear_actionPerformed(); + } + }); - database.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11)); - database.setMinimumSize(new Dimension(160, 21)); - database.setPreferredSize(new Dimension(160, 21)); - jLabel1.setFont(new java.awt.Font("Verdana", Font.ITALIC, 11)); - jLabel1.setText( - "Separate multiple accession ids with semi colon \";\""); - ok.setText("OK"); - ok.addActionListener(new ActionListener() + exampleBtn = new JButton(MessageManager.getString("label.example")); + exampleBtn.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { - ok_actionPerformed(e); + example_actionPerformed(); } }); - close.setText("Close"); - close.addActionListener(new ActionListener() + closeBtn = new JButton(MessageManager.getString("action.cancel")); + closeBtn.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { close_actionPerformed(e); } }); - textfield.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11)); - textfield.addActionListener(new ActionListener() + backBtn = new JButton(MessageManager.getString("action.back")); + backBtn.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { - ok_actionPerformed(e); + parentSearchPanel.btn_back_ActionPerformed(); } }); - jPanel1.add(ok); - jPanel1.add(close); - this.add(jLabel1, new GridBagConstraints(0, 0, 2, 1, 0.0, 0.0 - , GridBagConstraints.WEST, - GridBagConstraints.NONE, - new Insets(7, 4, 0, 6), 77, 6)); - this.add(jPanel1, new GridBagConstraints(0, 2, 2, 1, 1.0, 1.0 - , GridBagConstraints.WEST, - GridBagConstraints.BOTH, - new Insets(7, -2, 7, 12), 241, -2)); - this.add(database, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0 - , GridBagConstraints.WEST, - GridBagConstraints.NONE, - new Insets(0, 4, 0, 0), 1, 0)); - this.add(textfield, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0 - , GridBagConstraints.CENTER, - GridBagConstraints.NONE, - new Insets(0, 0, 0, 6), 211, 1)); + // back not visible unless embedded + backBtn.setVisible(false); + + textArea = new JTextArea(); + textArea.setFont(JvSwingUtils.getLabelFont()); + textArea.setLineWrap(true); + textArea.addKeyListener(new KeyAdapter() + { + @Override + public void keyPressed(KeyEvent e) + { + if (e.getKeyCode() == KeyEvent.VK_ENTER) + { + ok_actionPerformed(); + } + } + }); + + JPanel actionPanel = new JPanel(); + actionPanel.add(backBtn); + actionPanel.add(exampleBtn); + actionPanel.add(clear); + actionPanel.add(okBtn); + actionPanel.add(closeBtn); + + JPanel databasePanel = new JPanel(); + databasePanel.setLayout(new BorderLayout()); + databasePanel.add(database, BorderLayout.NORTH); + databasePanel.add(exampleAccession, BorderLayout.CENTER); + JPanel jPanel2a = new JPanel(new BorderLayout()); + jPanel2a.add(jLabel1, BorderLayout.NORTH); + jPanel2a.add(replacePunctuation, BorderLayout.SOUTH); + databasePanel.add(jPanel2a, BorderLayout.SOUTH); + + JPanel idsPanel = new JPanel(); + idsPanel.setLayout(new BorderLayout(0, 5)); + JScrollPane jScrollPane1 = new JScrollPane(); + jScrollPane1.getViewport().add(textArea); + idsPanel.add(jScrollPane1, BorderLayout.CENTER); + + this.add(actionPanel, BorderLayout.SOUTH); + this.add(idsPanel, BorderLayout.CENTER); + this.add(databasePanel, BorderLayout.NORTH); + } + + private void setDatabaseSelectedItem(String db) + { + for (int i = 0; i < database.getItemCount(); i++) + { + StringPair sp = database.getItemAt(i); + if (sp != null && db != null && db.equals(sp.getKey())) + { + database.setSelectedIndex(i); + return; + } + } + } + + /** + * Answers a semi-colon-delimited string with the example query or queries for + * the selected database + * + * @param db + * @return + */ + protected String getExampleQueries(String db) + { + StringBuilder sb = new StringBuilder(); + HashSet hs = new HashSet<>(); + for (DbSourceProxy dbs : sfetch.getSourceProxy(db)) + { + String tq = dbs.getTestQuery(); + if (hs.add(tq)) // not a duplicate source + { + if (sb.length() > 0) + { + sb.append(";"); + } + sb.append(tq); + } + } + return sb.toString(); } - JComboBox database = new JComboBox(); - JLabel jLabel1 = new JLabel(); - JButton ok = new JButton(); - JButton close = new JButton(); - JPanel jPanel1 = new JPanel(); - JTextField textfield = new JTextField(); - GridBagLayout gridBagLayout1 = new GridBagLayout(); - public void close_actionPerformed(ActionEvent e) + /** + * Action on selecting a database other than Uniprot or PDB is to enable or + * disable 'Replace commas', and await input in the query field + */ + protected void otherSourceAction() { try { - frame.setClosed(true); + String eq = exampleAccession.getText(); + // TODO this should be a property of the SequenceFetcher whether commas + // are allowed in the IDs... + + boolean enablePunct = !(eq != null && eq.indexOf(",") > -1); + replacePunctuation.setEnabled(enablePunct); + + } catch (Exception ex) + { + exampleAccession.setText(""); + replacePunctuation.setEnabled(true); } - catch (Exception ex) - {} + repaint(); } - public void ok_actionPerformed(ActionEvent e) + /** + * Sets the text of the example query to incorporate the example accession + * provided by the selected database source + * + * @param selectedDatabase + * @return + */ + protected String updateExampleQuery(String selectedDatabase) { - database.setEnabled(false); - textfield.setEnabled(false); - ok.setEnabled(false); - close.setEnabled(false); + String eq = getExampleQueries(selectedDatabase); + exampleAccession.setText(MessageManager + .formatMessage("label.example_query_param", new String[] + { eq })); + return eq; + } - Thread worker = new Thread(this); - worker.start(); + /** + * Action on clicking the 'Example' button is to write the example accession + * as the query text field value + */ + protected void example_actionPerformed() + { + String eq = getExampleQueries( + ((StringPair) database.getSelectedItem()).getKey()); + textArea.setText(eq); + repaint(); } - private void resetDialog() + /** + * Clears the query input field + */ + protected void clear_actionPerformed() { - database.setEnabled(true); - textfield.setEnabled(true); - ok.setEnabled(true); - close.setEnabled(true); + textArea.setText(""); + repaint(); } - public void run() + /** + * Action on Close button is to close this frame, and also (if it is embedded + * in a search panel) to close the search panel + * + * @param e + */ + protected void close_actionPerformed(ActionEvent e) { - String error = ""; - if (database.getSelectedItem().equals(noDbSelected)) + try + { + frame.setClosed(true); + if (parentSearchPanel != null) + { + parentSearchPanel.btn_cancel_ActionPerformed(); + } + } catch (Exception ex) { - error += "Please select the source database\n"; } - com.stevesoft.pat.Regex empty = new com.stevesoft.pat.Regex("\\s+", ""); - textfield.setText(empty.replaceAll(textfield.getText())); - if (textfield.getText().length() == 0) + } + + /** + * Action on OK is to start the fetch for entered accession(s) + */ + public void ok_actionPerformed() + { + /* + * tidy inputs and check there is something to search for + */ + String t0 = textArea.getText(); + String text = t0.trim(); + if (replacePunctuation.isEnabled() && replacePunctuation.isSelected()) { - error += "Please enter a (semi-colon separated list of) database id(s)"; + text = text.replace(",", ";"); } - if (error.length() > 0) + text = text.replaceAll("(\\s|[; ])+", ";"); + if (!t0.equals(text)) { - showErrorMessage(error); + textArea.setText(text); + } + if (text.isEmpty()) + { + // todo i18n + showErrorMessage( + "Please enter a (semi-colon separated list of) database id(s)"); resetDialog(); return; } - - result = new StringBuffer(); - if (database.getSelectedItem().equals("Uniprot")) + if (database.getSelectedIndex() == 0) { - getUniprotFile(textfield.getText()); + // todo i18n + showErrorMessage("Please choose a database"); + resetDialog(); + return; } - else if (database.getSelectedItem().equals("EMBL") - || database.getSelectedItem().equals("EMBLCDS")) - { - String DBRefSource = database.getSelectedItem().equals("EMBLCDS") - ? jalview.datamodel.DBRefSource.EMBLCDS - : jalview.datamodel.DBRefSource.EMBL; - StringTokenizer st = new StringTokenizer(textfield.getText(), ";"); - SequenceI[] seqs = null; - while(st.hasMoreTokens()) - { - EBIFetchClient dbFetch = new EBIFetchClient(); + exampleBtn.setEnabled(false); + textArea.setEnabled(false); + okBtn.setEnabled(false); + closeBtn.setEnabled(false); + backBtn.setEnabled(false); - File reply = dbFetch.fetchDataAsFile( - database.getSelectedItem().toString().toLowerCase( - ) + ":" + st.nextToken(), - "emblxml",null); + Thread worker = new Thread(this); + worker.start(); + } - jalview.datamodel.xdb.embl.EmblFile efile=null; - if (reply != null && reply.exists()) - { - efile = jalview.datamodel.xdb.embl.EmblFile.getEmblFile(reply); - } - if (efile!=null) { - for (Iterator i=efile.getEntries().iterator(); i.hasNext(); ) { - EmblEntry entry = (EmblEntry) i.next(); - SequenceI[] seqparts = entry.getSequences(false,true, DBRefSource); - if (seqparts!=null) { - SequenceI[] newseqs = null; - int si=0; - if (seqs==null) { - newseqs = new SequenceI[seqparts.length]; - } else { - newseqs = new SequenceI[seqs.length+seqparts.length]; - - for (;si0) { - if (parseResult(new Alignment(seqs), null, null)!=null) - result.append("# Successfully parsed the "+database.getSelectedItem()+" Queries into an Alignment"); - } - } - else if (database.getSelectedItem().equals("PDB")) + @Override + public void run() + { + boolean addToLast = false; + List aresultq = new ArrayList<>(); + List presultTitle = new ArrayList<>(); + List presult = new ArrayList<>(); + List aresult = new ArrayList<>(); + List sources = sfetch.getSourceProxy( + ((StringPair) database.getSelectedItem()).getKey()); + Iterator proxies = sources.iterator(); + String[] qries = textArea.getText().trim().split(";"); + List nextFetch = Arrays.asList(qries); + Iterator en = Arrays.asList(new String[0]).iterator(); + int nqueries = qries.length; + + FeatureSettingsModelI preferredFeatureColours = null; + while (proxies.hasNext() && (en.hasNext() || nextFetch.size() > 0)) { - StringTokenizer qset = new StringTokenizer(textfield.getText(), ";"); - String query; - SequenceI[] seqs = null; - while (qset.hasMoreTokens() && ((query = qset.nextToken())!=null)) + if (!en.hasNext() && nextFetch.size() > 0) { - SequenceI[] seqparts = getPDBFile(query.toUpperCase()); - if (seqparts != null) + en = nextFetch.iterator(); + nqueries = nextFetch.size(); + // save the remaining queries in the original array + qries = nextFetch.toArray(new String[nqueries]); + nextFetch = new ArrayList<>(); + } + + DbSourceProxy proxy = proxies.next(); + try + { + // update status + guiWindow.setProgressBar(MessageManager.formatMessage( + "status.fetching_sequence_queries_from", new String[] + { Integer.valueOf(nqueries).toString(), + proxy.getDbName() }), + Thread.currentThread().hashCode()); + if (proxy.getMaximumQueryCount() == 1) { - if (seqs == null) - { - seqs = seqparts; - } - else + /* + * proxy only handles one accession id at a time + */ + while (en.hasNext()) { - SequenceI[] newseqs = new SequenceI[seqs.length+seqparts.length]; - int i=0; - for (; i < seqs.length; i++) + String acc = en.next(); + if (!fetchSingleAccession(proxy, acc, aresultq, aresult)) { - newseqs[i] = seqs[i]; - seqs[i] = null; + nextFetch.add(acc); } - for (int j=0;j 0) - { - if (parseResult(new Alignment(seqs), null, null)!=null) + else { - result.append( - "# Successfully parsed the PDB File Queries into an Alignment"); + /* + * proxy can fetch multiple accessions at one time + */ + fetchMultipleAccessions(proxy, en, aresultq, aresult, nextFetch); } - } - } - else if( database.getSelectedItem().equals("PFAM")) - { - try + } catch (Exception e) { - result.append(new FastaFile( - "http://www.sanger.ac.uk/cgi-bin/Pfam/getalignment.pl?format=fal&acc=" - + textfield.getText().toUpperCase(), "URL").print() - ); - - if(result.length()>0) - { - parseResult( result.toString(), textfield.getText().toUpperCase() ); - } - - } - catch (java.io.IOException ex) + showErrorMessage("Error retrieving " + textArea.getText() + " from " + + ((StringPair) database.getSelectedItem()).getDisplay()); + // error + // +="Couldn't retrieve sequences from "+database.getSelectedItem(); + System.err.println("Retrieval failed for source ='" + + ((StringPair) database.getSelectedItem()).getDisplay() + + "' and query\n'" + textArea.getText() + "'\n"); + e.printStackTrace(); + } catch (OutOfMemoryError e) + { + showErrorMessage("Out of Memory when retrieving " + + textArea.getText() + " from " + + ((StringPair) database.getSelectedItem()).getDisplay() + + "\nPlease see the Jalview FAQ for instructions for increasing the memory available to Jalview.\n"); + e.printStackTrace(); + } catch (Error e) { - result = null; + showErrorMessage("Serious Error retrieving " + textArea.getText() + + " from " + + ((StringPair) database.getSelectedItem()).getDisplay()); + e.printStackTrace(); } - } - - if (result == null || result.length() == 0) - { - showErrorMessage("Error retrieving " + textfield.getText() - + " from " + database.getSelectedItem()); - } - - resetDialog(); - return; - } - void getUniprotFile(String id) - { - EBIFetchClient ebi = new EBIFetchClient(); - File file = ebi.fetchDataAsFile("uniprot:" + id, "xml", null); - - DBRefFetcher dbref = new DBRefFetcher(); - Vector entries = dbref.getUniprotEntries(file); - - if (entries != null) - { - //First, make the new sequences - Enumeration en = entries.elements(); - while (en.hasMoreElements()) + // Stack results ready for opening in alignment windows + if (aresult != null && aresult.size() > 0) { - UniprotEntry entry = (UniprotEntry) en.nextElement(); - - StringBuffer name = new StringBuffer(">UniProt/Swiss-Prot"); - Enumeration en2 = entry.getAccession().elements(); - while (en2.hasMoreElements()) - { - name.append("|"); - name.append(en2.nextElement()); - } - en2 = entry.getName().elements(); - while (en2.hasMoreElements()) + FeatureSettingsModelI proxyColourScheme = proxy + .getFeatureColourScheme(); + if (proxyColourScheme != null) { - name.append("|"); - name.append(en2.nextElement()); + preferredFeatureColours = proxyColourScheme; } - if (entry.getProtein() != null) + AlignmentI ar = null; + if (proxy.isAlignmentSource()) { - name.append(" " + entry.getProtein().getName().elementAt(0)); + addToLast = false; + // new window for each result + while (aresult.size() > 0) + { + presult.add(aresult.remove(0)); + presultTitle.add( + aresultq.remove(0) + " " + getDefaultRetrievalTitle()); + } } - - result.append(name + "\n" + entry.getUniprotSequence().getContent() + - "\n"); - - } - - //Then read in the features and apply them to the dataset - Alignment al = parseResult(result.toString(), null); - for (int i = 0; i < entries.size(); i++) - { - UniprotEntry entry = (UniprotEntry) entries.elementAt(i); - Enumeration e = entry.getDbReference().elements(); - Vector onlyPdbEntries = new Vector(); - while (e.hasMoreElements()) + else { - PDBEntry pdb = (PDBEntry) e.nextElement(); - if (!pdb.getType().equals("PDB")) + String titl = null; + if (addToLast && presult.size() > 0) { - continue; + ar = presult.remove(presult.size() - 1); + titl = presultTitle.remove(presultTitle.size() - 1); } - - onlyPdbEntries.addElement(pdb); + // concatenate all results in one window + while (aresult.size() > 0) + { + if (ar == null) + { + ar = aresult.remove(0); + } + else + { + ar.append(aresult.remove(0)); + } + } + addToLast = true; + presult.add(ar); + presultTitle.add(titl); } - - Enumeration en2 = entry.getAccession().elements(); - while (en2.hasMoreElements()) + } + guiWindow.setProgressBar( + MessageManager.getString("status.finshed_querying"), + Thread.currentThread().hashCode()); + } + guiWindow + .setProgressBar( + (presult.size() > 0) + ? MessageManager + .getString("status.parsing_results") + : MessageManager.getString("status.processing"), + Thread.currentThread().hashCode()); + // process results + while (presult.size() > 0) + { + parseResult(presult.remove(0), presultTitle.remove(0), null, + preferredFeatureColours); + } + // only remove visual delay after we finished parsing. + guiWindow.setProgressBar(null, Thread.currentThread().hashCode()); + if (nextFetch.size() > 0) + { + StringBuffer sb = new StringBuffer(); + sb.append("Didn't retrieve the following " + + (nextFetch.size() == 1 ? "query" + : nextFetch.size() + " queries") + + ": \n"); + int l = sb.length(), lr = 0; + for (String s : nextFetch) + { + if (l != sb.length()) { - al.getSequenceAt(i).getDatasetSequence().addDBRef(new DBRefEntry( - DBRefSource.UNIPROT, - "0", - en2.nextElement().toString())); + sb.append("; "); } - - - - - al.getSequenceAt(i).getDatasetSequence().setPDBId(onlyPdbEntries); - if (entry.getFeature() != null) + if (lr - sb.length() > 40) { - e = entry.getFeature().elements(); - while (e.hasMoreElements()) - { - SequenceFeature sf = (SequenceFeature) e.nextElement(); - sf.setFeatureGroup("Uniprot"); - al.getSequenceAt(i).getDatasetSequence().addSequenceFeature( sf ); - } + sb.append("\n"); } + sb.append(s); } + showErrorMessage(sb.toString()); } + resetDialog(); } - SequenceI[] getPDBFile(String id) + /** + * Tries to fetch one or more accession ids from the database proxy + * + * @param proxy + * @param accessions + * the queries to fetch + * @param aresultq + * a successful queries list to add to + * @param aresult + * a list of retrieved alignments to add to + * @param nextFetch + * failed queries are added to this list + * @throws Exception + */ + void fetchMultipleAccessions(DbSourceProxy proxy, + Iterator accessions, List aresultq, + List aresult, List nextFetch) throws Exception { - Vector result = new Vector(); - String chain = null; - if (id.indexOf(":") > -1) + StringBuilder multiacc = new StringBuilder(); + List tosend = new ArrayList<>(); + while (accessions.hasNext()) { - chain = id.substring(id.indexOf(":") + 1); - id = id.substring(0, id.indexOf(":")); + String nel = accessions.next(); + tosend.add(nel); + multiacc.append(nel); + if (accessions.hasNext()) + { + multiacc.append(proxy.getAccessionSeparator()); + } } - EBIFetchClient ebi = new EBIFetchClient(); - String file = ebi.fetchDataAsFile("pdb:" + id, "pdb", "raw"). - getAbsolutePath(); - if (file == null) - { - return null; - } try { - PDBfile pdbfile = new PDBfile(file, jalview.io.AppletFormatAdapter.FILE); - for (int i = 0; i < pdbfile.chains.size(); i++) + String query = multiacc.toString(); + AlignmentI rslt = proxy.getSequenceRecords(query); + if (rslt == null || rslt.getHeight() == 0) { - if (chain == null || - ( (PDBChain) pdbfile.chains.elementAt(i)).id. - toUpperCase().equals(chain)) + // no results - pass on all queries to next source + nextFetch.addAll(tosend); + } + else + { + aresultq.add(query); + aresult.add(rslt); + if (tosend.size() > 1) { - PDBChain pdbchain = (PDBChain) pdbfile.chains.elementAt(i); - // Get the Chain's Sequence - who's dataset includes any special features added from the PDB file - SequenceI sq = pdbchain.sequence; - // Specially formatted name for the PDB chain sequences retrieved from the PDB - sq.setName("PDB|"+id+"|"+sq.getName()); - // Might need to add more metadata to the PDBEntry object - // like below - /* - * PDBEntry entry = new PDBEntry(); - // Construct the PDBEntry - entry.setId(id); - if (entry.getProperty() == null) - entry.setProperty(new Hashtable()); - entry.getProperty().put("chains", - pdbchain.id - + "=" + sq.getStart() - + "-" + sq.getEnd()); - sq.getDatasetSequence().addPDBId(entry); - */ - // Add PDB DB Refs - // We make a DBRefEtntry because we have obtained the PDB file from a verifiable source - // JBPNote - PDB DBRefEntry should also carry the chain and mapping information - DBRefEntry dbentry = new DBRefEntry(jalview.datamodel.DBRefSource.PDB, - "0", id + pdbchain.id); - sq.addDBRef(dbentry); - // and add seuqence to the retrieved set - result.addElement(sq.deriveSequence()); + checkResultForQueries(rslt, tosend, nextFetch, proxy); } } - } - catch (Exception ex) // Problem parsing PDB file - { - jalview.bin.Cache.log.warn("Exception when retrieving " + - textfield.getText() + " from " + - database.getSelectedItem(), ex); - return null; - } - SequenceI[] results = new SequenceI[result.size()]; - for (int i = 0, j = result.size(); i < j; i++) + } catch (OutOfMemoryError oome) { - results[i] = (SequenceI) result.elementAt(i); - result.setElementAt(null,i); + new OOMWarning("fetching " + multiacc + " from " + + ((StringPair) database.getSelectedItem()).getDisplay(), + oome, this); } - return results; } - Alignment parseResult(String result, String title) + + /** + * Query for a single accession id via the database proxy + * + * @param proxy + * @param accession + * @param aresultq + * a list of successful queries to add to + * @param aresult + * a list of retrieved alignments to add to + * @return true if the fetch was successful, else false + */ + boolean fetchSingleAccession(DbSourceProxy proxy, String accession, + List aresultq, List aresult) { - String format = new IdentifyFile().Identify(result, "Paste"); - Alignment sequences = null; - if (FormatAdapter.isValidFormat(format)) + boolean success = false; + try { - sequences = null; - try + if (aresult != null) { - sequences = new FormatAdapter().readFile(result.toString(), "Paste", - format); + try + { + // give the server a chance to breathe + Thread.sleep(5); + } catch (Exception e) + { + // + } } - catch (Exception ex) - {} - if (sequences!=null) + AlignmentI indres = null; + try { - return parseResult(sequences, title, format); + indres = proxy.getSequenceRecords(accession); + } catch (OutOfMemoryError oome) + { + new OOMWarning( + "fetching " + accession + " from " + proxy.getDbName(), + oome, this); } + if (indres != null) + { + aresultq.add(accession); + aresult.add(indres); + success = true; + } + } catch (Exception e) + { + Console.info("Error retrieving " + accession + " from " + + proxy.getDbName(), e); } - else + return success; + } + + /** + * Checks which of the queries were successfully retrieved by searching the + * DBRefs of the retrieved sequences for a match. Any not found are added to + * the 'nextFetch' list. + * + * @param rslt + * @param queries + * @param nextFetch + * @param proxy + */ + void checkResultForQueries(AlignmentI rslt, List queries, + List nextFetch, DbSourceProxy proxy) + { + SequenceI[] rs = rslt.getSequencesArray(); + + for (String q : queries) { - showErrorMessage("Error retrieving " + textfield.getText() - + " from " + database.getSelectedItem()); + // BH 2019.01.25 dbr is never used. + // DBRefEntry dbr = new DBRefEntry(); + // dbr.setSource(proxy.getDbSource()); + // dbr.setVersion(null); + String accId = proxy.getAccessionIdFromQuery(q); + // dbr.setAccessionId(accId); + boolean rfound = false; + for (int r = 0, nr = rs.length; r < nr; r++) + { + if (rs[r] != null) + { + List found = DBRefUtils.searchRefs(rs[r].getDBRefs(), + accId); + if (!found.isEmpty()) + { + rfound = true; + break; + } + } + } + if (!rfound) + { + nextFetch.add(q); + } } + } - return null; + /** + * + * @return a standard title for any results retrieved using the currently + * selected source and settings + */ + public String getDefaultRetrievalTitle() + { + return "Retrieved from " + + ((StringPair) database.getSelectedItem()).getDisplay(); } - Alignment parseResult(Alignment al, String title, String currentFileFormat) + /** + * constructs an alignment frame given the data and metadata + * + * @param al + * @param title + * @param currentFileFormat + * @param preferredFeatureColours + * @return the alignment + */ + public AlignmentI parseResult(AlignmentI al, String title, + FileFormatI currentFileFormat, + FeatureSettingsModelI preferredFeatureColours) { if (al != null && al.getHeight() > 0) { + if (title == null) + { + title = getDefaultRetrievalTitle(); + } if (alignFrame == null) { - AlignFrame af = new AlignFrame(al, - AlignFrame.DEFAULT_WIDTH, - AlignFrame.DEFAULT_HEIGHT); - if (currentFileFormat!=null) + AlignFrame af = new AlignFrame(al, AlignFrame.DEFAULT_WIDTH, + AlignFrame.DEFAULT_HEIGHT); + if (currentFileFormat != null) { - af.currentFileFormat = currentFileFormat; // WHAT IS THE DEFAULT FORMAT FOR NON-FormatAdapter Sourced Alignments? + af.currentFileFormat = currentFileFormat; } - if(title==null) + List alsqs = al.getSequences(); + synchronized (alsqs) { - title = "Retrieved from " + database.getSelectedItem(); + for (SequenceI sq : alsqs) + { + if (sq.getFeatures().hasFeatures()) + { + af.setShowSeqFeatures(true); + break; + } + } } - Desktop.addInternalFrame(af, - title, - AlignFrame.DEFAULT_WIDTH, - AlignFrame.DEFAULT_HEIGHT); + af.getViewport().applyFeaturesStyle(preferredFeatureColours); + if (Cache.getDefault("HIDE_INTRONS", true)) + { + af.hideFeatureColumns(SequenceOntologyI.EXON, false); + } + Desktop.addInternalFrame(af, title, AlignFrame.DEFAULT_WIDTH, + AlignFrame.DEFAULT_HEIGHT); - af.statusBar.setText("Successfully pasted alignment file"); + af.setStatus(MessageManager + .getString("label.successfully_pasted_alignment_file")); try { - af.setMaximum(jalview.bin.Cache.getDefault("SHOW_FULLSCREEN", false)); + af.setMaximum(Cache.getDefault("SHOW_FULLSCREEN", false)); + } catch (Exception ex) + { } - catch (Exception ex) - {} } else { - for (int i = 0; i < al.getHeight(); i++) - { - alignFrame.viewport.alignment.addSequence(al.getSequenceAt(i)); // this also creates dataset sequence entries - } - alignFrame.viewport.setEndSeq(alignFrame.viewport.alignment. - getHeight()); - alignFrame.viewport.alignment.getWidth(); - alignFrame.viewport.firePropertyChange("alignment", null, - alignFrame.viewport. - getAlignment().getSequences()); + alignFrame.viewport.addAlignment(al, title); } } return al; @@ -561,13 +947,52 @@ extends JPanel implements Runnable resetDialog(); javax.swing.SwingUtilities.invokeLater(new Runnable() { + @Override public void run() { - JOptionPane.showInternalMessageDialog(Desktop.desktop, - error, "Error Retrieving Data", - JOptionPane.WARNING_MESSAGE); + JvOptionPane.showInternalMessageDialog(Desktop.desktop, error, + MessageManager.getString("label.error_retrieving_data"), + JvOptionPane.WARNING_MESSAGE); } }); } -} + public IProgressIndicator getProgressIndicator() + { + return progressIndicator; + } + + public void setProgressIndicator(IProgressIndicator progressIndicator) + { + this.progressIndicator = progressIndicator; + } + + /** + * Hide this panel (on clicking the database button to open the database + * chooser) + */ + void hidePanel() + { + frame.setVisible(false); + } + + public void setQuery(String ids) + { + textArea.setText(ids); + } + + /** + * Called to modify the search panel for embedding as an alternative tab of a + * free text search panel. The database choice list is hidden (since the + * choice has been made), and a Back button is made visible (which reopens the + * Sequence Fetcher panel). + * + * @param parentPanel + */ + public void embedIn(GFTSPanel parentPanel) + { + database.setVisible(false); + backBtn.setVisible(true); + parentSearchPanel = parentPanel; + } +}