JAL-1668 Tab for summary config, auto refresh after config and table column sorting
[jalview.git] / src / jalview / gui / StructureChooser.java
1 /*
2
3  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
4  * Copyright (C) 2014 The Jalview Authors
5  * 
6  * This file is part of Jalview.
7  * 
8  * Jalview is free software: you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License 
10  * as published by the Free Software Foundation, either version 3
11  * of the License, or (at your option) any later version.
12  *  
13  * Jalview is distributed in the hope that it will be useful, but 
14  * WITHOUT ANY WARRANTY; without even the implied warranty 
15  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
16  * PURPOSE.  See the GNU General Public License for more details.
17  * 
18  * You should have received a copy of the GNU General Public License
19  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
20  * The Jalview Authors are detailed in the 'AUTHORS' file.
21  */
22
23 package jalview.gui;
24
25 import jalview.datamodel.DBRefEntry;
26 import jalview.datamodel.PDBEntry;
27 import jalview.datamodel.SequenceI;
28 import jalview.jbgui.GStructureChooser;
29 import jalview.jbgui.PDBDocFieldPreferences;
30 import jalview.util.MessageManager;
31 import jalview.ws.dbsources.PDBRestClient;
32 import jalview.ws.dbsources.PDBRestClient.PDBDocField;
33 import jalview.ws.uimodel.PDBRestRequest;
34 import jalview.ws.uimodel.PDBRestResponse;
35 import jalview.ws.uimodel.PDBRestResponse.PDBResponseSummary;
36
37 import java.awt.event.ItemEvent;
38 import java.util.ArrayList;
39 import java.util.Collection;
40 import java.util.HashSet;
41 import java.util.LinkedHashSet;
42 import java.util.List;
43 import java.util.Vector;
44
45 import javax.swing.JCheckBox;
46 import javax.swing.JComboBox;
47 import javax.swing.JLabel;
48
49 /**
50  * Provides the behaviors for the Structure chooser Panel
51  * 
52  * @author tcnofoegbu
53  *
54  */
55 @SuppressWarnings("serial")
56 public class StructureChooser extends GStructureChooser
57 {
58   private boolean structuresDiscovered = false;
59
60   private SequenceI selectedSequence;
61
62   private SequenceI[] selectedSequences;
63
64   private IProgressIndicator progressIndicator;
65
66   private Collection<PDBResponseSummary> discoveredStructuresSet;
67
68   private PDBRestRequest lastPdbRequest;
69
70   private PDBRestClient pdbRestCleint;
71
72   private String selectedPdbFileName;
73
74   private boolean isValidPBDEntry;
75
76   public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
77           AlignmentPanel ap)
78   {
79     this.ap = ap;
80     this.selectedSequence = selectedSeq;
81     this.selectedSequences = selectedSeqs;
82     this.progressIndicator = (ap == null) ? null : ap.alignFrame;
83     init();
84   }
85
86   /**
87    * Initializes parameters used by the Structure Chooser Panel
88    */
89   public void init()
90   {
91     Thread discoverPDBStructuresThread = new Thread(new Runnable()
92     {
93       @Override
94       public void run()
95       {
96         long startTime = System.currentTimeMillis();
97         String msg = MessageManager.getString("status.fetching_db_refs");
98         updateProgressIndicator(msg, startTime);
99         fetchStructuresMetaData();
100         populateFilterComboBox();
101         updateProgressIndicator(null, startTime);
102         mainFrame.setVisible(true);
103         updateCurrentView();
104       }
105     });
106     discoverPDBStructuresThread.start();
107   }
108
109   /**
110    * Updates the progress indicator with the specified message
111    * 
112    * @param message
113    *          displayed message for the operation
114    * @param id
115    *          unique handle for this indicator
116    */
117   public void updateProgressIndicator(String message, long id)
118   {
119     if (progressIndicator != null)
120     {
121       progressIndicator.setProgressBar(message, id);
122     }
123   }
124
125   /**
126    * Retrieve meta-data for all the structure(s) for a given sequence(s) in a
127    * selection group
128    */
129   public void fetchStructuresMetaData()
130   {
131     long startTime = System.currentTimeMillis();
132     Collection<PDBDocField> wantedFields = PDBDocFieldPreferences
133             .getStructureSummaryFields();
134
135     discoveredStructuresSet = new LinkedHashSet<PDBResponseSummary>();
136     for (SequenceI seq : selectedSequences)
137     {
138       PDBRestRequest pdbRequest = new PDBRestRequest();
139       pdbRequest.setAllowEmptySeq(false);
140       pdbRequest.setResponseSize(500);
141       pdbRequest.setFieldToSearchBy("(text:");
142       pdbRequest.setWantedFields(wantedFields);
143       pdbRequest.setSearchTerm(buildQuery(seq) + ")");
144       pdbRequest.setAssociatedSequence(seq.getName());
145       pdbRestCleint = new PDBRestClient();
146       PDBRestResponse resultList = pdbRestCleint.executeRequest(pdbRequest);
147       lastPdbRequest = pdbRequest;
148       if (resultList.getSearchSummary() != null
149               && !resultList.getSearchSummary().isEmpty())
150       {
151         discoveredStructuresSet.addAll(resultList.getSearchSummary());
152         updateSequenceDbRef(seq, resultList.getSearchSummary());
153       }
154     }
155
156     int noOfStructuresFound = 0;
157     if (discoveredStructuresSet != null
158             && !discoveredStructuresSet.isEmpty())
159     {
160       tbl_summary.setModel(PDBRestResponse.getTableModel(lastPdbRequest,
161               discoveredStructuresSet));
162       structuresDiscovered = true;
163       noOfStructuresFound = discoveredStructuresSet.size();
164     }
165     String totalTime = (System.currentTimeMillis() - startTime)
166             + " milli secs";
167     mainFrame.setTitle("Structure Chooser - " + noOfStructuresFound
168             + " Found (" + totalTime + ")");
169   }
170
171   /**
172    * Update the DBRef entry for a given sequence with values retrieved from
173    * PDBResponseSummary
174    * 
175    * @param seq
176    *          the Sequence to update its DBRef entry
177    * @param responseSummaries
178    *          a collection of PDBResponseSummary
179    */
180   public void updateSequenceDbRef(SequenceI seq,
181           Collection<PDBResponseSummary> responseSummaries)
182   {
183     for (PDBResponseSummary response : responseSummaries)
184     {
185       PDBEntry newEntry = new PDBEntry();
186       newEntry.setId(response.getPdbId());
187       newEntry.setType("PDB");
188       seq.getDatasetSequence().addPDBId(newEntry);
189     }
190   }
191
192   /**
193    * Builds a query string for a given sequences using its DBRef entries
194    * 
195    * @param seq
196    *          the sequences to build a query for
197    * @return the built query string
198    */
199   @SuppressWarnings("unchecked")
200   public static String buildQuery(SequenceI seq)
201   {
202     String query = seq.getName();
203     StringBuilder queryBuilder = new StringBuilder();
204     int count = 0;
205
206     if (seq.getPDBId() != null)
207     {
208       for (PDBEntry entry : (Vector<PDBEntry>) seq.getPDBId())
209       {
210         queryBuilder.append("text:").append(entry.getId()).append(" OR ");
211       }
212     }
213
214     if (seq.getDBRef() != null && seq.getDBRef().length != 0)
215     {
216       for (DBRefEntry dbRef : seq.getDBRef())
217       {
218         queryBuilder.append("text:")
219                 .append(dbRef.getAccessionId().replaceAll("GO:", ""))
220                 .append(" OR ");
221         ++count;
222         if (count > 10)
223         {
224           break;
225         }
226       }
227       int endIndex = queryBuilder.lastIndexOf(" OR ");
228       query = queryBuilder.toString().substring(5, endIndex);
229     }
230     return query;
231   }
232
233   /**
234    * Filters a given list of discovered structures based on supplied argument
235    * 
236    * @param fieldToFilterBy
237    *          the field to filter by
238    */
239   public void filterResultSet(final String fieldToFilterBy)
240   {
241
242     // SwingWorker aWorker = new SwingWorker()
243     // {
244     // long startTime = System.currentTimeMillis();
245     //
246     // @Override
247     // protected Object doInBackground() throws Exception
248     // {
249     // lbl_loading.setVisible(true);
250     //
251     // Collection<PDBDocField> wantedFields = PDBDocFieldPreferences
252     // .getStructureSummaryFields();
253     // Collection<PDBResponseSummary> filteredResponse = new
254     // HashSet<PDBResponseSummary>();
255     // for (SequenceI seq : selectedSequences)
256     // {
257     // PDBRestRequest pdbRequest = new PDBRestRequest();
258     // pdbRequest.setAllowEmptySeq(false);
259     // pdbRequest.setResponseSize(1);
260     // pdbRequest.setFieldToSearchBy("(text:");
261     // pdbRequest.setFieldToSortBy(fieldToFilterBy,
262     // !chk_invertFilter.isSelected());
263     // pdbRequest.setSearchTerm(buildQuery(seq) + ")");
264     // pdbRequest.setWantedFields(wantedFields);
265     // pdbRequest.setAssociatedSequence(seq.getName());
266     // pdbRestCleint = new PDBRestClient();
267     // PDBRestResponse resultList = pdbRestCleint
268     // .executeRequest(pdbRequest);
269     // lastPdbRequest = pdbRequest;
270     // if (resultList.getSearchSummary() != null
271     // && !resultList.getSearchSummary().isEmpty())
272     // {
273     // filteredResponse.addAll(resultList.getSearchSummary());
274     // }
275     // }
276     //
277     // if (!filteredResponse.isEmpty())
278     // {
279     // final int filterResponseCount = filteredResponse.size();
280     // Collection<PDBResponseSummary> reorderedStructuresSet = new
281     // LinkedHashSet<PDBResponseSummary>();
282     // reorderedStructuresSet.addAll(filteredResponse);
283     // reorderedStructuresSet.addAll(discoveredStructuresSet);
284     // tbl_summary.setModel(PDBRestResponse.getTableModel(
285     // lastPdbRequest, reorderedStructuresSet));
286     //
287     // // Update the model here
288     // // ListSelectionModel model = tbl_summary.getSelectionModel();
289     // // model.clearSelection();
290     // // model.addSelectionInterval(0, filterResponseCount - 1);
291     // // EventQueue.invokeLater(new Runnable()
292     // // {
293     // // public void run()
294     // // {
295     // // tbl_summary.addRowSelectionInterval(0, filterResponseCount - 1);
296     //
297     // // }
298     // // });
299     // // Discard unwanted objects to make them eligible for garbage
300     // // collection
301     // reorderedStructuresSet = null;
302     // }
303     // return null;
304     // }
305     //
306     // public void done()
307     // {
308     // lbl_loading.setVisible(false);
309     // tbl_summary.addRowSelectionInterval(0, 2);
310     // String totalTime = (System.currentTimeMillis() - startTime)
311     // + " milli secs";
312     // mainFrame.setTitle("Structure Chooser - Filter time (" + totalTime
313     // + ")");
314     // validateSelections();
315     // }
316     // };
317     // aWorker.execute();
318
319     Thread filterThread = new Thread(new Runnable()
320     {
321       @Override
322       public void run()
323       {
324         long startTime = System.currentTimeMillis();
325         try
326         {
327           lbl_loading.setVisible(true);
328
329           Collection<PDBDocField> wantedFields = PDBDocFieldPreferences
330                   .getStructureSummaryFields();
331           Collection<PDBResponseSummary> filteredResponse = new HashSet<PDBResponseSummary>();
332           for (SequenceI seq : selectedSequences)
333           {
334             PDBRestRequest pdbRequest = new PDBRestRequest();
335             pdbRequest.setAllowEmptySeq(false);
336             pdbRequest.setResponseSize(1);
337             pdbRequest.setFieldToSearchBy("(text:");
338             pdbRequest.setFieldToSortBy(fieldToFilterBy,
339                     !chk_invertFilter.isSelected());
340             pdbRequest.setSearchTerm(buildQuery(seq) + ")");
341             pdbRequest.setWantedFields(wantedFields);
342             pdbRequest.setAssociatedSequence(seq.getName());
343             pdbRestCleint = new PDBRestClient();
344             PDBRestResponse resultList = pdbRestCleint
345                     .executeRequest(pdbRequest);
346             lastPdbRequest = pdbRequest;
347             if (resultList.getSearchSummary() != null
348                     && !resultList.getSearchSummary().isEmpty())
349             {
350               filteredResponse.addAll(resultList.getSearchSummary());
351             }
352           }
353
354           if (!filteredResponse.isEmpty())
355           {
356             final int filterResponseCount = filteredResponse.size();
357             Collection<PDBResponseSummary> reorderedStructuresSet = new LinkedHashSet<PDBResponseSummary>();
358             reorderedStructuresSet.addAll(filteredResponse);
359             reorderedStructuresSet.addAll(discoveredStructuresSet);
360             tbl_summary.setModel(PDBRestResponse.getTableModel(
361                     lastPdbRequest, reorderedStructuresSet));
362
363             // Update the model here
364             // ListSelectionModel model = tbl_summary.getSelectionModel();
365             // model.clearSelection();
366             // model.addSelectionInterval(0, filterResponseCount - 1);
367             // EventQueue.invokeLater(new Runnable()
368             // {
369             // public void run()
370             // {
371             tbl_summary.addRowSelectionInterval(0, filterResponseCount - 1);
372
373             // }
374             // });
375             // Discard unwanted objects to make them eligible for garbage
376             // collection
377             reorderedStructuresSet = null;
378           }
379
380           lbl_loading.setVisible(false);
381           String totalTime = (System.currentTimeMillis() - startTime)
382                   + " milli secs";
383           mainFrame.setTitle("Structure Chooser - Filter time ("
384                   + totalTime + ")");
385
386           validateSelections();
387         } catch (Exception e)
388         {
389           e.printStackTrace();
390         }
391       }
392     });
393     filterThread.start();
394   }
395
396
397   /**
398    * Handles action event for btn_pdbFromFile
399    */
400   public void pdbFromFile_actionPerformed()
401   {
402     jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(
403             jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
404     chooser.setFileView(new jalview.io.JalviewFileView());
405     chooser.setDialogTitle(MessageManager.formatMessage(
406             "label.select_pdb_file_for", new String[]
407             { selectedSequence.getDisplayId(false) }));
408     chooser.setToolTipText(MessageManager.formatMessage(
409             "label.load_pdb_file_associate_with_sequence", new String[]
410             { selectedSequence.getDisplayId(false) }));
411
412     int value = chooser.showOpenDialog(null);
413     if (value == jalview.io.JalviewFileChooser.APPROVE_OPTION)
414     {
415       selectedPdbFileName = chooser.getSelectedFile().getPath();
416       jalview.bin.Cache.setProperty("LAST_DIRECTORY", selectedPdbFileName);
417       validateSelections();
418     }
419   }
420
421   /**
422    * Populates the filter combo-box options dynamically depending on discovered
423    * structures
424    */
425   protected void populateFilterComboBox()
426   {
427     if (isStructuresDiscovered())
428     {
429       cmb_filterOption.addItem(new FilterOption("Best Quality",
430               PDBDocField.OVERALL_QUALITY.getCode(), VIEWS_FILTER));
431       cmb_filterOption.addItem(new FilterOption("Best UniProt Coverage",
432               PDBDocField.UNIPROT_COVERAGE.getCode(), VIEWS_FILTER));
433       cmb_filterOption.addItem(new FilterOption("Highest Resolution",
434               PDBDocField.RESOLUTION.getCode(), VIEWS_FILTER));
435       cmb_filterOption.addItem(new FilterOption("Highest Protein Chain",
436               PDBDocField.PROTEIN_CHAIN_COUNT.getCode(), VIEWS_FILTER));
437       cmb_filterOption.addItem(new FilterOption("Highest Bound Molecules",
438               PDBDocField.BOUND_MOLECULE_COUNT.getCode(), VIEWS_FILTER));
439       cmb_filterOption.addItem(new FilterOption("Highest Polymer Residues",
440               PDBDocField.POLYMER_RESIDUE_COUNT.getCode(), VIEWS_FILTER));
441     }
442     cmb_filterOption.addItem(new FilterOption("Enter PDB Id", "-",
443             VIEWS_ENTER_ID));
444     cmb_filterOption.addItem(new FilterOption("From File", "-",
445             VIEWS_FROM_FILE));
446   }
447
448   /**
449    * Updates the displayed view based on the selected filter option
450    */
451   protected void updateCurrentView()
452   {
453     FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
454             .getSelectedItem());
455     layout_switchableViews.show(pnl_switchableViews,
456             selectedFilterOpt.getView());
457     String filterTitle = mainFrame.getTitle();
458     mainFrame.setTitle(frameTitle);
459     chk_invertFilter.setVisible(false);
460     if (selectedFilterOpt.getView() == VIEWS_FILTER)
461     {
462       mainFrame.setTitle(filterTitle);
463       chk_invertFilter.setVisible(true);
464       filterResultSet(selectedFilterOpt.getValue());
465     }
466     else
467     {
468       idInputAssSeqPanel.loadCmbAssSeq();
469       fileChooserAssSeqPanel.loadCmbAssSeq();
470     }
471     validateSelections();
472   }
473
474   /**
475    * Validates user selection and activates the view button if all parameters
476    * are correct
477    */
478   public void validateSelections()
479   {
480     FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
481             .getSelectedItem());
482     btn_view.setEnabled(false);
483     String currentView = selectedFilterOpt.getView();
484     if (currentView == VIEWS_FILTER)
485     {
486       if (tbl_summary.getSelectedRows().length > 0)
487       {
488         btn_view.setEnabled(true);
489       }
490     }
491     else if (currentView == VIEWS_ENTER_ID)
492     {
493       validateAssociationEnterPdb();
494     }
495     else if (currentView == VIEWS_FROM_FILE)
496     {
497       validateAssociationFromFile();
498     }
499   }
500
501   /**
502    * Validates inputs from the Manual PDB entry panel
503    */
504   public void validateAssociationEnterPdb()
505   {
506     AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) idInputAssSeqPanel
507             .getCmb_assSeq().getSelectedItem();
508     lbl_pdbManualFetchStatus.setIcon(errorImage);
509     if (selectedSequences.length == 1
510             || !assSeqOpt.getName().equalsIgnoreCase(
511                     "-Select Associated Seq-"))
512     {
513       txt_search.setEnabled(true);
514       if (isValidPBDEntry)
515       {
516         btn_view.setEnabled(true);
517         lbl_pdbManualFetchStatus.setIcon(goodImage);
518       }
519     }
520     else
521     {
522       txt_search.setEnabled(false);
523       lbl_pdbManualFetchStatus.setIcon(errorImage);
524     }
525   }
526
527   /**
528    * Validates inputs for the manual PDB file selection options
529    */
530   public void validateAssociationFromFile()
531   {
532     AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel
533             .getCmb_assSeq().getSelectedItem();
534     lbl_fromFileStatus.setIcon(errorImage);
535     if (selectedSequences.length == 1
536             || (assSeqOpt != null
537             && !assSeqOpt.getName().equalsIgnoreCase(
538                     "-Select Associated Seq-")))
539     {
540       btn_pdbFromFile.setEnabled(true);
541       if (selectedPdbFileName != null && selectedPdbFileName.length() > 0)
542       {
543         btn_view.setEnabled(true);
544         lbl_fromFileStatus.setIcon(goodImage);
545       }
546     }
547     else
548     {
549       btn_pdbFromFile.setEnabled(false);
550       lbl_fromFileStatus.setIcon(errorImage);
551     }
552   }
553
554   @Override
555   public void cmbAssSeqStateChanged()
556   {
557     validateSelections();
558   }
559
560   /**
561    * Handles the state change event for the 'filter' combo-box and 'invert'
562    * check-box
563    */
564   @Override
565   protected void stateChanged(ItemEvent e)
566   {
567     if (e.getSource() instanceof JCheckBox)
568     {
569       updateCurrentView();
570     }
571     else
572     {
573       if (e.getStateChange() == ItemEvent.SELECTED)
574       {
575         updateCurrentView();
576       }
577     }
578
579   }
580
581   /**
582    * Handles action event for btn_ok
583    */
584   @Override
585   public void ok_ActionPerformed()
586   {
587     FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
588             .getSelectedItem());
589     String currentView = selectedFilterOpt.getView();
590     if (currentView == VIEWS_FILTER)
591     {
592       int pdbIdCol = PDBRestClient.getPDBIdColumIndex(
593               lastPdbRequest.getWantedFields(), true);
594       int[] selectedRows = tbl_summary.getSelectedRows();
595       PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
596       int count = 0;
597       for (int summaryRow : selectedRows)
598       {
599         String pdbIdStr = tbl_summary.getValueAt(summaryRow, pdbIdCol)
600                 .toString();
601         PDBEntry pdbEntry = new PDBEntry();
602         pdbEntry.setId(pdbIdStr);
603         pdbEntry.setType("PDB");
604         pdbEntriesToView[count++] = pdbEntry;
605       }
606       new StructureViewer(ap.getStructureSelectionManager())
607               .viewStructures(ap, pdbEntriesToView,
608                       ap.av.collateForPDB(pdbEntriesToView));
609     }
610     else if (currentView == VIEWS_ENTER_ID)
611     {
612       selectedSequence = ((AssociateSeqOptions) idInputAssSeqPanel
613               .getCmb_assSeq().getSelectedItem()).getSequence();
614       PDBEntry pdbEntry = new PDBEntry();
615       pdbEntry.setId(txt_search.getText());
616       pdbEntry.setType("PDB");
617       selectedSequence.getDatasetSequence().addPDBId(pdbEntry);
618       PDBEntry[] pdbEntriesToView = new PDBEntry[]
619       { pdbEntry };
620       new StructureViewer(ap.getStructureSelectionManager())
621               .viewStructures(ap, pdbEntriesToView,
622                       ap.av.collateForPDB(pdbEntriesToView));
623     }
624     else if (currentView == VIEWS_FROM_FILE)
625     {
626       selectedSequence = ((AssociateSeqOptions) fileChooserAssSeqPanel
627               .getCmb_assSeq().getSelectedItem()).getSequence();
628       new AssociatePdbFileWithSeq().associatePdbWithSeq(
629               selectedPdbFileName, jalview.io.AppletFormatAdapter.FILE,
630               selectedSequence, true, Desktop.instance);
631     }
632     mainFrame.dispose();
633   }
634
635   /**
636    * Populates the combo-box used in associating manually fetched structures to
637    * a unique sequence when more than one sequence selection is made.
638    */
639   public void populateCmbAssociateSeqOptions(
640           JComboBox<AssociateSeqOptions> cmb_assSeq, JLabel lbl_associateSeq)
641   {
642     cmb_assSeq.removeAllItems();
643     cmb_assSeq.addItem(new AssociateSeqOptions("-Select Associated Seq-",
644             null));
645     // cmb_assSeq.addItem(new AssociateSeqOptions("Auto Detect", null));
646     lbl_associateSeq.setVisible(false);
647     if (selectedSequences.length > 1)
648     {
649       for (SequenceI seq : selectedSequences)
650       {
651         cmb_assSeq.addItem(new AssociateSeqOptions(seq));
652       }
653     }
654     else
655     {
656       String seqName = selectedSequence.getDisplayId(false);
657       seqName = seqName.length() <= 40 ? seqName : seqName.substring(0, 39);
658       lbl_associateSeq.setText(seqName);
659       lbl_associateSeq.setVisible(true);
660       cmb_assSeq.setVisible(false);
661     }
662   }
663
664   public boolean isStructuresDiscovered()
665   {
666     return structuresDiscovered;
667   }
668
669   public void setStructuresDiscovered(boolean structuresDiscovered)
670   {
671     this.structuresDiscovered = structuresDiscovered;
672   }
673
674   public Collection<PDBResponseSummary> getDiscoveredStructuresSet()
675   {
676     return discoveredStructuresSet;
677   }
678
679   @Override
680   protected void txt_search_ActionPerformed()
681   {
682     isValidPBDEntry = false;
683     if (txt_search.getText().length() > 0)
684     {
685       List<PDBDocField> wantedFields = new ArrayList<PDBDocField>();
686       wantedFields.add(PDBDocField.PDB_ID);
687       PDBRestRequest pdbRequest = new PDBRestRequest();
688       pdbRequest.setAllowEmptySeq(false);
689       pdbRequest.setResponseSize(1);
690       pdbRequest.setFieldToSearchBy("(pdb_id:");
691       pdbRequest.setWantedFields(wantedFields);
692       pdbRequest.setSearchTerm(txt_search.getText() + ")");
693       pdbRequest.setAssociatedSequence(selectedSequence.getName());
694       pdbRestCleint = new PDBRestClient();
695       PDBRestResponse resultList = pdbRestCleint.executeRequest(pdbRequest);
696       if (resultList.getSearchSummary() != null
697               && resultList.getSearchSummary().size() > 0)
698       {
699         isValidPBDEntry = true;
700       }
701     }
702     validateSelections();
703   }
704
705   @Override
706   public void tabRefresh()
707   {
708     if (selectedSequences != null)
709     {
710       Thread refreshThread = new Thread(new Runnable()
711       {
712         @Override
713         public void run()
714         {
715           fetchStructuresMetaData();
716           filterResultSet(((FilterOption) cmb_filterOption
717                   .getSelectedItem()).getValue());
718         }
719       });
720       refreshThread.start();
721     }
722   }
723
724 }