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