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