Clover icon

Coverage Report

  1. Project Clover database Thu Aug 13 2020 12:04:21 BST
  2. Package jalview.gui

File StructureChooser.java

 

Coverage histogram

../../img/srcFileCovDistChart4.png
44% of files have more coverage

Code metrics

180
498
51
3
1,406
1,122
168
0.34
9.76
17
3.29

Classes

Class Line # Actions
StructureChooser 69 468 150
0.3581871435.8%
StructureChooser.PDBEntryTableModel 1282 26 15
0.2105263221.1%
StructureChooser.CachedPDB 1358 4 3
0.00%
 

Contributing tests

This file is covered by 3 tests. .

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ The Jalview Authors
4    *
5    * This file is part of Jalview.
6    *
7    * Jalview is free software: you can redistribute it and/or
8    * modify it under the terms of the GNU General Public License
9    * as published by the Free Software Foundation, either version 3
10    * of the License, or (at your option) any later version.
11    *
12    * Jalview is distributed in the hope that it will be useful, but
13    * WITHOUT ANY WARRANTY; without even the implied warranty
14    * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15    * PURPOSE. See the GNU General Public License for more details.
16    *
17    * You should have received a copy of the GNU General Public License
18    * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19    * The Jalview Authors are detailed in the 'AUTHORS' file.
20    */
21   
22    package jalview.gui;
23   
24    import jalview.api.structures.JalviewStructureDisplayI;
25    import jalview.bin.Cache;
26    import jalview.bin.Jalview;
27    import jalview.datamodel.DBRefEntry;
28    import jalview.datamodel.DBRefSource;
29    import jalview.datamodel.PDBEntry;
30    import jalview.datamodel.SequenceI;
31    import jalview.fts.api.FTSData;
32    import jalview.fts.api.FTSDataColumnI;
33    import jalview.fts.api.FTSRestClientI;
34    import jalview.fts.core.FTSRestRequest;
35    import jalview.fts.core.FTSRestResponse;
36    import jalview.fts.service.pdb.PDBFTSRestClient;
37    import jalview.io.DataSourceType;
38    import jalview.jbgui.GStructureChooser;
39    import jalview.structure.StructureMapping;
40    import jalview.structure.StructureSelectionManager;
41    import jalview.util.MessageManager;
42    import jalview.ws.DBRefFetcher;
43    import jalview.ws.sifts.SiftsSettings;
44   
45    import java.awt.event.ItemEvent;
46    import java.util.ArrayList;
47    import java.util.Collection;
48    import java.util.HashSet;
49    import java.util.LinkedHashSet;
50    import java.util.List;
51    import java.util.Objects;
52    import java.util.Set;
53    import java.util.Vector;
54   
55    import javax.swing.JCheckBox;
56    import javax.swing.JComboBox;
57    import javax.swing.JLabel;
58    import javax.swing.JTable;
59    import javax.swing.SwingUtilities;
60    import javax.swing.table.AbstractTableModel;
61   
62    /**
63    * Provides the behaviors for the Structure chooser Panel
64    *
65    * @author tcnofoegbu
66    *
67    */
68    @SuppressWarnings("serial")
 
69    public class StructureChooser extends GStructureChooser
70    implements IProgressIndicator
71    {
72    private static final String AUTOSUPERIMPOSE = "AUTOSUPERIMPOSE";
73   
74    private static int MAX_QLENGTH = 7820;
75   
76    private SequenceI selectedSequence;
77   
78    private SequenceI[] selectedSequences;
79   
80    private IProgressIndicator progressIndicator;
81   
82    private Collection<FTSData> discoveredStructuresSet;
83   
84    private FTSRestRequest lastPdbRequest;
85   
86    private FTSRestClientI pdbRestClient;
87   
88    private String selectedPdbFileName;
89   
90    private boolean isValidPBDEntry;
91   
92    private boolean cachedPDBExists;
93   
94    private static StructureViewer lastTargetedView = null;
95   
 
96  1 toggle public StructureChooser(SequenceI[] selectedSeqs, SequenceI selectedSeq,
97    AlignmentPanel ap)
98    {
99  1 this.ap = ap;
100  1 this.selectedSequence = selectedSeq;
101  1 this.selectedSequences = selectedSeqs;
102  1 this.progressIndicator = (ap == null) ? null : ap.alignFrame;
103  1 init();
104    }
105   
106    /**
107    * Initializes parameters used by the Structure Chooser Panel
108    */
 
109  1 toggle protected void init()
110    {
111  1 if (!Jalview.isHeadlessMode())
112    {
113  1 progressBar = new ProgressBar(this.statusPanel, this.statusBar);
114    }
115   
116  1 chk_superpose.setSelected(Cache.getDefault(AUTOSUPERIMPOSE, true));
117   
118    // ensure a filter option is in force for search
119  1 populateFilterComboBox(true, cachedPDBExists);
120  1 Thread discoverPDBStructuresThread = new Thread(new Runnable()
121    {
 
122  1 toggle @Override
123    public void run()
124    {
125  1 long startTime = System.currentTimeMillis();
126  1 updateProgressIndicator(MessageManager
127    .getString("status.loading_cached_pdb_entries"), startTime);
128  1 loadLocalCachedPDBEntries();
129  1 updateProgressIndicator(null, startTime);
130  1 updateProgressIndicator(MessageManager.getString(
131    "status.searching_for_pdb_structures"), startTime);
132  1 fetchStructuresMetaData();
133    // revise filter options if no results were found
134  1 populateFilterComboBox(isStructuresDiscovered(), cachedPDBExists);
135  1 discoverStructureViews();
136  1 updateProgressIndicator(null, startTime);
137  1 mainFrame.setVisible(true);
138  1 updateCurrentView();
139    }
140    });
141  1 discoverPDBStructuresThread.start();
142    }
143   
144    /**
145    * Builds a drop-down choice list of existing structure viewers to which new
146    * structures may be added. If this list is empty then it, and the 'Add'
147    * button, are hidden.
148    */
 
149  1 toggle private void discoverStructureViews()
150    {
151  1 if (Desktop.instance != null)
152    {
153  1 targetView.removeAllItems();
154  1 if (lastTargetedView != null && !lastTargetedView.isVisible())
155    {
156  0 lastTargetedView = null;
157    }
158  1 int linkedViewsAt = 0;
159  1 for (StructureViewerBase view : Desktop.instance
160    .getStructureViewers(null, null))
161    {
162  0 StructureViewer viewHandler = (lastTargetedView != null
163    && lastTargetedView.sview == view) ? lastTargetedView
164    : StructureViewer.reconfigure(view);
165   
166  0 if (view.isLinkedWith(ap))
167    {
168  0 targetView.insertItemAt(viewHandler,
169    linkedViewsAt++);
170    }
171    else
172    {
173  0 targetView.addItem(viewHandler);
174    }
175    }
176   
177    /*
178    * show option to Add to viewer if at least 1 viewer found
179    */
180  1 targetView.setVisible(false);
181  1 if (targetView.getItemCount() > 0)
182    {
183  0 targetView.setVisible(true);
184  0 if (lastTargetedView != null)
185    {
186  0 targetView.setSelectedItem(lastTargetedView);
187    }
188    else
189    {
190  0 targetView.setSelectedIndex(0);
191    }
192    }
193  1 btn_add.setVisible(targetView.isVisible());
194    }
195    }
196   
197    /**
198    * Updates the progress indicator with the specified message
199    *
200    * @param message
201    * displayed message for the operation
202    * @param id
203    * unique handle for this indicator
204    */
 
205  4 toggle protected void updateProgressIndicator(String message, long id)
206    {
207  4 if (progressIndicator != null)
208    {
209  0 progressIndicator.setProgressBar(message, id);
210    }
211    }
212   
213    /**
214    * Retrieve meta-data for all the structure(s) for a given sequence(s) in a
215    * selection group
216    */
 
217  1 toggle void fetchStructuresMetaData()
218    {
219  1 long startTime = System.currentTimeMillis();
220  1 pdbRestClient = PDBFTSRestClient.getInstance();
221  1 Collection<FTSDataColumnI> wantedFields = pdbDocFieldPrefs
222    .getStructureSummaryFields();
223   
224  1 discoveredStructuresSet = new LinkedHashSet<>();
225  1 HashSet<String> errors = new HashSet<>();
226  1 for (SequenceI seq : selectedSequences)
227    {
228  1 FTSRestRequest pdbRequest = new FTSRestRequest();
229  1 pdbRequest.setAllowEmptySeq(false);
230  1 pdbRequest.setResponseSize(500);
231  1 pdbRequest.setFieldToSearchBy("(");
232  1 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
233    .getSelectedItem());
234  1 pdbRequest.setFieldToSortBy(selectedFilterOpt.getValue(),
235    !chk_invertFilter.isSelected());
236  1 pdbRequest.setWantedFields(wantedFields);
237  1 pdbRequest.setSearchTerm(buildQuery(seq) + ")");
238  1 pdbRequest.setAssociatedSequence(seq);
239  1 FTSRestResponse resultList;
240  1 try
241    {
242  1 resultList = pdbRestClient.executeRequest(pdbRequest);
243    } catch (Exception e)
244    {
245  1 e.printStackTrace();
246  1 errors.add(e.getMessage());
247  1 continue;
248    }
249  0 lastPdbRequest = pdbRequest;
250  0 if (resultList.getSearchSummary() != null
251    && !resultList.getSearchSummary().isEmpty())
252    {
253  0 discoveredStructuresSet.addAll(resultList.getSearchSummary());
254    }
255    }
256   
257  1 int noOfStructuresFound = 0;
258  1 String totalTime = (System.currentTimeMillis() - startTime)
259    + " milli secs";
260  1 if (discoveredStructuresSet != null
261    && !discoveredStructuresSet.isEmpty())
262    {
263  0 getResultTable().setModel(FTSRestResponse
264    .getTableModel(lastPdbRequest, discoveredStructuresSet));
265  0 noOfStructuresFound = discoveredStructuresSet.size();
266  0 mainFrame.setTitle(MessageManager.formatMessage(
267    "label.structure_chooser_no_of_structures",
268    noOfStructuresFound, totalTime));
269    }
270    else
271    {
272  1 mainFrame.setTitle(MessageManager
273    .getString("label.structure_chooser_manual_association"));
274  1 if (errors.size() > 0)
275    {
276  1 StringBuilder errorMsg = new StringBuilder();
277  1 for (String error : errors)
278    {
279  1 errorMsg.append(error).append("\n");
280    }
281  1 JvOptionPane.showMessageDialog(this, errorMsg.toString(),
282    MessageManager.getString("label.pdb_web-service_error"),
283    JvOptionPane.ERROR_MESSAGE);
284    }
285    }
286    }
287   
 
288  1 toggle protected void loadLocalCachedPDBEntries()
289    {
290  1 ArrayList<CachedPDB> entries = new ArrayList<>();
291  1 for (SequenceI seq : selectedSequences)
292    {
293  1 if (seq.getDatasetSequence() != null
294    && seq.getDatasetSequence().getAllPDBEntries() != null)
295    {
296  1 for (PDBEntry pdbEntry : seq.getDatasetSequence()
297    .getAllPDBEntries())
298    {
299  0 if (pdbEntry.getFile() != null)
300    {
301  0 entries.add(new CachedPDB(seq, pdbEntry));
302    }
303    }
304    }
305    }
306  1 cachedPDBExists = !entries.isEmpty();
307  1 PDBEntryTableModel tableModelx = new PDBEntryTableModel(entries);
308  1 tbl_local_pdb.setModel(tableModelx);
309    }
310   
311    /**
312    * Builds a query string for a given sequences using its DBRef entries
313    *
314    * @param seq
315    * the sequences to build a query for
316    * @return the built query string
317    */
318   
 
319  5 toggle static String buildQuery(SequenceI seq)
320    {
321  5 boolean isPDBRefsFound = false;
322  5 boolean isUniProtRefsFound = false;
323  5 StringBuilder queryBuilder = new StringBuilder();
324  5 Set<String> seqRefs = new LinkedHashSet<>();
325   
326    /*
327    * note PDBs as DBRefEntry so they are not duplicated in query
328    */
329  5 Set<String> pdbids = new HashSet<>();
330   
331  5 if (seq.getAllPDBEntries() != null
332    && queryBuilder.length() < MAX_QLENGTH)
333    {
334  5 for (PDBEntry entry : seq.getAllPDBEntries())
335    {
336  2 if (isValidSeqName(entry.getId()))
337    {
338  2 String id = entry.getId().toLowerCase();
339  2 queryBuilder.append("pdb_id:").append(id).append(" OR ");
340  2 isPDBRefsFound = true;
341  2 pdbids.add(id);
342    }
343    }
344    }
345   
346  5 List<DBRefEntry> refs = seq.getDBRefs();
347  5 if (refs != null && refs.size() != 0)
348    {
349  22 for (int ib = 0, nb = refs.size(); ib < nb; ib++)
350    {
351  18 DBRefEntry dbRef = refs.get(ib);
352  18 if (isValidSeqName(getDBRefId(dbRef))
353    && queryBuilder.length() < MAX_QLENGTH)
354    {
355  18 if (dbRef.getSource().equalsIgnoreCase(DBRefSource.UNIPROT))
356    {
357  1 queryBuilder.append("uniprot_accession:")
358    .append(getDBRefId(dbRef)).append(" OR ");
359  1 queryBuilder.append("uniprot_id:").append(getDBRefId(dbRef))
360    .append(" OR ");
361  1 isUniProtRefsFound = true;
362    }
363  17 else if (dbRef.getSource().equalsIgnoreCase(DBRefSource.PDB))
364    {
365   
366  1 String id = getDBRefId(dbRef).toLowerCase();
367  1 if (!pdbids.contains(id))
368    {
369  1 queryBuilder.append("pdb_id:").append(id).append(" OR ");
370  1 isPDBRefsFound = true;
371  1 pdbids.add(id);
372    }
373    }
374    else
375    {
376  16 seqRefs.add(getDBRefId(dbRef));
377    }
378    }
379    }
380    }
381   
382  5 if (!isPDBRefsFound && !isUniProtRefsFound)
383    {
384  2 String seqName = seq.getName();
385  2 seqName = sanitizeSeqName(seqName);
386  2 String[] names = seqName.toLowerCase().split("\\|");
387  2 for (String name : names)
388    {
389    // System.out.println("Found name : " + name);
390  8 name.trim();
391  8 if (isValidSeqName(name))
392    {
393  4 seqRefs.add(name);
394    }
395    }
396   
397  2 for (String seqRef : seqRefs)
398    {
399  6 queryBuilder.append("text:").append(seqRef).append(" OR ");
400    }
401    }
402   
403  5 int endIndex = queryBuilder.lastIndexOf(" OR ");
404  5 if (queryBuilder.toString().length() < 6)
405    {
406  0 return null;
407    }
408  5 String query = queryBuilder.toString().substring(0, endIndex);
409  5 return query;
410    }
411   
412    /**
413    * Remove the following special characters from input string +, -, &, !, (, ),
414    * {, }, [, ], ^, ", ~, *, ?, :, \
415    *
416    * @param seqName
417    * @return
418    */
 
419  6 toggle static String sanitizeSeqName(String seqName)
420    {
421  6 Objects.requireNonNull(seqName);
422  6 return seqName.replaceAll("\\[\\d*\\]", "")
423    .replaceAll("[^\\dA-Za-z|_]", "").replaceAll("\\s+", "+");
424    }
425   
426    /**
427    * Ensures sequence ref names are not less than 3 characters and does not
428    * contain a database name
429    *
430    * @param seqName
431    * @return
432    */
 
433  28 toggle static boolean isValidSeqName(String seqName)
434    {
435    // System.out.println("seqName : " + seqName);
436  28 String ignoreList = "pdb,uniprot,swiss-prot";
437  28 if (seqName.length() < 3)
438    {
439  2 return false;
440    }
441  26 if (seqName.contains(":"))
442    {
443  0 return false;
444    }
445  26 seqName = seqName.toLowerCase();
446  26 for (String ignoredEntry : ignoreList.split(","))
447    {
448  74 if (seqName.contains(ignoredEntry))
449    {
450  2 return false;
451    }
452    }
453  24 return true;
454    }
455   
 
456  37 toggle static String getDBRefId(DBRefEntry dbRef)
457    {
458  37 String ref = dbRef.getAccessionId().replaceAll("GO:", "");
459  37 return ref;
460    }
461   
462    /**
463    * Filters a given list of discovered structures based on supplied argument
464    *
465    * @param fieldToFilterBy
466    * the field to filter by
467    */
 
468  0 toggle void filterResultSet(final String fieldToFilterBy)
469    {
470  0 Thread filterThread = new Thread(new Runnable()
471    {
 
472  0 toggle @Override
473    public void run()
474    {
475  0 long startTime = System.currentTimeMillis();
476  0 pdbRestClient = PDBFTSRestClient.getInstance();
477  0 lbl_loading.setVisible(true);
478  0 Collection<FTSDataColumnI> wantedFields = pdbDocFieldPrefs
479    .getStructureSummaryFields();
480  0 Collection<FTSData> filteredResponse = new HashSet<>();
481  0 HashSet<String> errors = new HashSet<>();
482   
483  0 for (SequenceI seq : selectedSequences)
484    {
485  0 FTSRestRequest pdbRequest = new FTSRestRequest();
486  0 if (fieldToFilterBy.equalsIgnoreCase("uniprot_coverage"))
487    {
488  0 pdbRequest.setAllowEmptySeq(false);
489  0 pdbRequest.setResponseSize(1);
490  0 pdbRequest.setFieldToSearchBy("(");
491  0 pdbRequest.setSearchTerm(buildQuery(seq) + ")");
492  0 pdbRequest.setWantedFields(wantedFields);
493  0 pdbRequest.setAssociatedSequence(seq);
494  0 pdbRequest.setFacet(true);
495  0 pdbRequest.setFacetPivot(fieldToFilterBy + ",entry_entity");
496  0 pdbRequest.setFacetPivotMinCount(1);
497    }
498    else
499    {
500  0 pdbRequest.setAllowEmptySeq(false);
501  0 pdbRequest.setResponseSize(1);
502  0 pdbRequest.setFieldToSearchBy("(");
503  0 pdbRequest.setFieldToSortBy(fieldToFilterBy,
504    !chk_invertFilter.isSelected());
505  0 pdbRequest.setSearchTerm(buildQuery(seq) + ")");
506  0 pdbRequest.setWantedFields(wantedFields);
507  0 pdbRequest.setAssociatedSequence(seq);
508    }
509  0 FTSRestResponse resultList;
510  0 try
511    {
512  0 resultList = pdbRestClient.executeRequest(pdbRequest);
513    } catch (Exception e)
514    {
515  0 e.printStackTrace();
516  0 errors.add(e.getMessage());
517  0 continue;
518    }
519  0 lastPdbRequest = pdbRequest;
520  0 if (resultList.getSearchSummary() != null
521    && !resultList.getSearchSummary().isEmpty())
522    {
523  0 filteredResponse.addAll(resultList.getSearchSummary());
524    }
525    }
526   
527  0 String totalTime = (System.currentTimeMillis() - startTime)
528    + " milli secs";
529  0 if (!filteredResponse.isEmpty())
530    {
531  0 final int filterResponseCount = filteredResponse.size();
532  0 Collection<FTSData> reorderedStructuresSet = new LinkedHashSet<>();
533  0 reorderedStructuresSet.addAll(filteredResponse);
534  0 reorderedStructuresSet.addAll(discoveredStructuresSet);
535  0 getResultTable().setModel(FTSRestResponse
536    .getTableModel(lastPdbRequest, reorderedStructuresSet));
537   
538  0 FTSRestResponse.configureTableColumn(getResultTable(),
539    wantedFields, tempUserPrefs);
540  0 getResultTable().getColumn("Ref Sequence").setPreferredWidth(120);
541  0 getResultTable().getColumn("Ref Sequence").setMinWidth(100);
542  0 getResultTable().getColumn("Ref Sequence").setMaxWidth(200);
543    // Update table selection model here
544  0 getResultTable().addRowSelectionInterval(0,
545    filterResponseCount - 1);
546  0 mainFrame.setTitle(MessageManager.formatMessage(
547    "label.structure_chooser_filter_time", totalTime));
548    }
549    else
550    {
551  0 mainFrame.setTitle(MessageManager.formatMessage(
552    "label.structure_chooser_filter_time", totalTime));
553  0 if (errors.size() > 0)
554    {
555  0 StringBuilder errorMsg = new StringBuilder();
556  0 for (String error : errors)
557    {
558  0 errorMsg.append(error).append("\n");
559    }
560  0 JvOptionPane.showMessageDialog(null, errorMsg.toString(),
561    MessageManager.getString("label.pdb_web-service_error"),
562    JvOptionPane.ERROR_MESSAGE);
563    }
564    }
565   
566  0 lbl_loading.setVisible(false);
567   
568  0 validateSelections();
569    }
570    });
571  0 filterThread.start();
572    }
573   
574    /**
575    * Handles action event for btn_pdbFromFile
576    */
 
577  0 toggle @Override
578    protected void pdbFromFile_actionPerformed()
579    {
580    // TODO: JAL-3048 not needed for Jalview-JS until JSmol dep and StructureChooser
581    // works
582  0 jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(
583    jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
584  0 chooser.setFileView(new jalview.io.JalviewFileView());
585  0 chooser.setDialogTitle(
586    MessageManager.formatMessage("label.select_pdb_file_for",
587    selectedSequence.getDisplayId(false)));
588  0 chooser.setToolTipText(MessageManager.formatMessage(
589    "label.load_pdb_file_associate_with_sequence",
590    selectedSequence.getDisplayId(false)));
591   
592  0 int value = chooser.showOpenDialog(null);
593  0 if (value == jalview.io.JalviewFileChooser.APPROVE_OPTION)
594    {
595  0 selectedPdbFileName = chooser.getSelectedFile().getPath();
596  0 jalview.bin.Cache.setProperty("LAST_DIRECTORY", selectedPdbFileName);
597  0 validateSelections();
598    }
599    }
600   
601    /**
602    * Populates the filter combo-box options dynamically depending on discovered
603    * structures
604    */
 
605  5 toggle protected void populateFilterComboBox(boolean haveData,
606    boolean cachedPDBExist)
607    {
608    /*
609    * temporarily suspend the change listener behaviour
610    */
611  5 cmb_filterOption.removeItemListener(this);
612   
613  5 cmb_filterOption.removeAllItems();
614  5 if (haveData)
615    {
616  3 cmb_filterOption.addItem(new FilterOption(
617    MessageManager.getString("label.best_quality"),
618    "overall_quality", VIEWS_FILTER, false));
619  3 cmb_filterOption.addItem(new FilterOption(
620    MessageManager.getString("label.best_resolution"),
621    "resolution", VIEWS_FILTER, false));
622  3 cmb_filterOption.addItem(new FilterOption(
623    MessageManager.getString("label.most_protein_chain"),
624    "number_of_protein_chains", VIEWS_FILTER, false));
625  3 cmb_filterOption.addItem(new FilterOption(
626    MessageManager.getString("label.most_bound_molecules"),
627    "number_of_bound_molecules", VIEWS_FILTER, false));
628  3 cmb_filterOption.addItem(new FilterOption(
629    MessageManager.getString("label.most_polymer_residues"),
630    "number_of_polymer_residues", VIEWS_FILTER, true));
631    }
632  5 cmb_filterOption.addItem(
633    new FilterOption(MessageManager.getString("label.enter_pdb_id"),
634    "-", VIEWS_ENTER_ID, false));
635  5 cmb_filterOption.addItem(
636    new FilterOption(MessageManager.getString("label.from_file"),
637    "-", VIEWS_FROM_FILE, false));
638   
639  5 if (cachedPDBExist)
640    {
641  1 FilterOption cachedOption = new FilterOption(
642    MessageManager.getString("label.cached_structures"),
643    "-", VIEWS_LOCAL_PDB, false);
644  1 cmb_filterOption.addItem(cachedOption);
645  1 cmb_filterOption.setSelectedItem(cachedOption);
646    }
647   
648  5 cmb_filterOption.addItemListener(this);
649    }
650   
651    /**
652    * Updates the displayed view based on the selected filter option
653    */
 
654  1 toggle protected void updateCurrentView()
655    {
656  1 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
657    .getSelectedItem());
658  1 layout_switchableViews.show(pnl_switchableViews,
659    selectedFilterOpt.getView());
660  1 String filterTitle = mainFrame.getTitle();
661  1 mainFrame.setTitle(frameTitle);
662  1 chk_invertFilter.setVisible(false);
663  1 if (selectedFilterOpt.getView() == VIEWS_FILTER)
664    {
665  0 mainFrame.setTitle(filterTitle);
666  0 chk_invertFilter.setVisible(true);
667  0 filterResultSet(selectedFilterOpt.getValue());
668    }
669  1 else if (selectedFilterOpt.getView() == VIEWS_ENTER_ID
670    || selectedFilterOpt.getView() == VIEWS_FROM_FILE)
671    {
672  1 mainFrame.setTitle(MessageManager
673    .getString("label.structure_chooser_manual_association"));
674  1 idInputAssSeqPanel.loadCmbAssSeq();
675  1 fileChooserAssSeqPanel.loadCmbAssSeq();
676    }
677  1 validateSelections();
678    }
679   
680    /**
681    * Validates user selection and enables the 'Add' and 'New View' buttons if
682    * all parameters are correct (the Add button will only be visible if there is
683    * at least one existing structure viewer open). This basically means at least
684    * one structure selected and no error messages.
685    * <p>
686    * The 'Superpose Structures' option is enabled if either more than one
687    * structure is selected, or the 'Add' to existing view option is enabled, and
688    * disabled if the only option is to open a new view of a single structure.
689    */
 
690  3 toggle @Override
691    protected void validateSelections()
692    {
693  3 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
694    .getSelectedItem());
695  3 btn_add.setEnabled(false);
696  3 String currentView = selectedFilterOpt.getView();
697  3 int selectedCount = 0;
698  3 if (currentView == VIEWS_FILTER)
699    {
700  0 selectedCount = getResultTable().getSelectedRows().length;
701  0 if (selectedCount > 0)
702    {
703  0 btn_add.setEnabled(true);
704    }
705    }
706  3 else if (currentView == VIEWS_LOCAL_PDB)
707    {
708  0 selectedCount = tbl_local_pdb.getSelectedRows().length;
709  0 if (selectedCount > 0)
710    {
711  0 btn_add.setEnabled(true);
712    }
713    }
714  3 else if (currentView == VIEWS_ENTER_ID)
715    {
716  3 validateAssociationEnterPdb();
717    }
718  0 else if (currentView == VIEWS_FROM_FILE)
719    {
720  0 validateAssociationFromFile();
721    }
722   
723  3 btn_newView.setEnabled(btn_add.isEnabled());
724   
725    /*
726    * enable 'Superpose' option if more than one structure is selected,
727    * or there are view(s) available to add structure(s) to
728    */
729  3 chk_superpose
730    .setEnabled(selectedCount > 1 || targetView.getItemCount() > 0);
731    }
732   
733    /**
734    * Validates inputs from the Manual PDB entry panel
735    */
 
736  3 toggle protected void validateAssociationEnterPdb()
737    {
738  3 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) idInputAssSeqPanel
739    .getCmb_assSeq().getSelectedItem();
740  3 lbl_pdbManualFetchStatus.setIcon(errorImage);
741  3 lbl_pdbManualFetchStatus.setToolTipText("");
742  3 if (txt_search.getText().length() > 0)
743    {
744  0 lbl_pdbManualFetchStatus.setToolTipText(JvSwingUtils.wrapTooltip(true,
745    MessageManager.formatMessage("info.no_pdb_entry_found_for",
746    txt_search.getText())));
747    }
748   
749  3 if (errorWarning.length() > 0)
750    {
751  0 lbl_pdbManualFetchStatus.setIcon(warningImage);
752  0 lbl_pdbManualFetchStatus.setToolTipText(
753    JvSwingUtils.wrapTooltip(true, errorWarning.toString()));
754    }
755   
756  3 if (selectedSequences.length == 1 || !assSeqOpt.getName()
757    .equalsIgnoreCase("-Select Associated Seq-"))
758    {
759  3 txt_search.setEnabled(true);
760  3 if (isValidPBDEntry)
761    {
762  0 btn_add.setEnabled(true);
763  0 lbl_pdbManualFetchStatus.setToolTipText("");
764  0 lbl_pdbManualFetchStatus.setIcon(goodImage);
765    }
766    }
767    else
768    {
769  0 txt_search.setEnabled(false);
770  0 lbl_pdbManualFetchStatus.setIcon(errorImage);
771    }
772    }
773   
774    /**
775    * Validates inputs for the manual PDB file selection options
776    */
 
777  0 toggle protected void validateAssociationFromFile()
778    {
779  0 AssociateSeqOptions assSeqOpt = (AssociateSeqOptions) fileChooserAssSeqPanel
780    .getCmb_assSeq().getSelectedItem();
781  0 lbl_fromFileStatus.setIcon(errorImage);
782  0 if (selectedSequences.length == 1 || (assSeqOpt != null && !assSeqOpt
783    .getName().equalsIgnoreCase("-Select Associated Seq-")))
784    {
785  0 btn_pdbFromFile.setEnabled(true);
786  0 if (selectedPdbFileName != null && selectedPdbFileName.length() > 0)
787    {
788  0 btn_add.setEnabled(true);
789  0 lbl_fromFileStatus.setIcon(goodImage);
790    }
791    }
792    else
793    {
794  0 btn_pdbFromFile.setEnabled(false);
795  0 lbl_fromFileStatus.setIcon(errorImage);
796    }
797    }
798   
 
799  2 toggle @Override
800    protected void cmbAssSeqStateChanged()
801    {
802  2 validateSelections();
803    }
804   
805    /**
806    * Handles the state change event for the 'filter' combo-box and 'invert'
807    * check-box
808    */
 
809  0 toggle @Override
810    protected void stateChanged(ItemEvent e)
811    {
812  0 if (e.getSource() instanceof JCheckBox)
813    {
814  0 updateCurrentView();
815    }
816    else
817    {
818  0 if (e.getStateChange() == ItemEvent.SELECTED)
819    {
820  0 updateCurrentView();
821    }
822    }
823   
824    }
825   
826    /**
827    * select structures for viewing by their PDB IDs
828    *
829    * @param pdbids
830    * @return true if structures were found and marked as selected
831    */
 
832  0 toggle public boolean selectStructure(String... pdbids)
833    {
834  0 boolean found = false;
835   
836  0 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
837    .getSelectedItem());
838  0 String currentView = selectedFilterOpt.getView();
839  0 JTable restable = (currentView == VIEWS_FILTER) ? getResultTable()
840  0 : (currentView == VIEWS_LOCAL_PDB) ? tbl_local_pdb : null;
841   
842  0 if (restable == null)
843    {
844    // can't select (enter PDB ID, or load file - need to also select which
845    // sequence to associate with)
846  0 return false;
847    }
848   
849  0 int pdbIdColIndex = restable.getColumn("PDB Id").getModelIndex();
850  0 for (int r = 0; r < restable.getRowCount(); r++)
851    {
852  0 for (int p = 0; p < pdbids.length; p++)
853    {
854  0 if (String.valueOf(restable.getValueAt(r, pdbIdColIndex))
855    .equalsIgnoreCase(pdbids[p]))
856    {
857  0 restable.setRowSelectionInterval(r, r);
858  0 found = true;
859    }
860    }
861    }
862  0 return found;
863    }
864   
865    /**
866    * Handles the 'New View' action
867    */
 
868  0 toggle @Override
869    protected void newView_ActionPerformed()
870    {
871  0 targetView.setSelectedItem(null);
872  0 showStructures(false);
873    }
874   
875    /**
876    * Handles the 'Add to existing viewer' action
877    */
 
878  0 toggle @Override
879    protected void add_ActionPerformed()
880    {
881  0 showStructures(false);
882    }
883   
884    /**
885    * structure viewer opened by this dialog, or null
886    */
887    private StructureViewer sViewer = null;
888   
 
889  0 toggle public void showStructures(boolean waitUntilFinished)
890    {
891   
892  0 final StructureSelectionManager ssm = ap.getStructureSelectionManager();
893   
894  0 final int preferredHeight = pnl_filter.getHeight();
895   
896  0 Runnable viewStruc = new Runnable()
897    {
 
898  0 toggle @Override
899    public void run()
900    {
901  0 FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
902    .getSelectedItem());
903  0 String currentView = selectedFilterOpt.getView();
904  0 JTable restable = (currentView == VIEWS_FILTER) ? getResultTable()
905    : tbl_local_pdb;
906   
907  0 if (currentView == VIEWS_FILTER)
908    {
909  0 int pdbIdColIndex = restable.getColumn("PDB Id")
910    .getModelIndex();
911  0 int refSeqColIndex = restable.getColumn("Ref Sequence")
912    .getModelIndex();
913  0 int[] selectedRows = restable.getSelectedRows();
914  0 PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
915  0 int count = 0;
916  0 List<SequenceI> selectedSeqsToView = new ArrayList<>();
917  0 for (int row : selectedRows)
918    {
919  0 String pdbIdStr = restable
920    .getValueAt(row, pdbIdColIndex).toString();
921  0 SequenceI selectedSeq = (SequenceI) restable
922    .getValueAt(row, refSeqColIndex);
923  0 selectedSeqsToView.add(selectedSeq);
924  0 PDBEntry pdbEntry = selectedSeq.getPDBEntry(pdbIdStr);
925  0 if (pdbEntry == null)
926    {
927  0 pdbEntry = getFindEntry(pdbIdStr,
928    selectedSeq.getAllPDBEntries());
929    }
930   
931  0 if (pdbEntry == null)
932    {
933  0 pdbEntry = new PDBEntry();
934  0 pdbEntry.setId(pdbIdStr);
935  0 pdbEntry.setType(PDBEntry.Type.PDB);
936  0 selectedSeq.getDatasetSequence().addPDBId(pdbEntry);
937    }
938  0 pdbEntriesToView[count++] = pdbEntry;
939    }
940  0 SequenceI[] selectedSeqs = selectedSeqsToView
941    .toArray(new SequenceI[selectedSeqsToView.size()]);
942  0 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
943    selectedSeqs);
944    }
945  0 else if (currentView == VIEWS_LOCAL_PDB)
946    {
947  0 int[] selectedRows = tbl_local_pdb.getSelectedRows();
948  0 PDBEntry[] pdbEntriesToView = new PDBEntry[selectedRows.length];
949  0 int count = 0;
950  0 int pdbIdColIndex = tbl_local_pdb.getColumn("PDB Id")
951    .getModelIndex();
952  0 int refSeqColIndex = tbl_local_pdb.getColumn("Ref Sequence")
953    .getModelIndex();
954  0 List<SequenceI> selectedSeqsToView = new ArrayList<>();
955  0 for (int row : selectedRows)
956    {
957  0 PDBEntry pdbEntry = (PDBEntry) tbl_local_pdb.getValueAt(row,
958    pdbIdColIndex);
959  0 pdbEntriesToView[count++] = pdbEntry;
960  0 SequenceI selectedSeq = (SequenceI) tbl_local_pdb
961    .getValueAt(row, refSeqColIndex);
962  0 selectedSeqsToView.add(selectedSeq);
963    }
964  0 SequenceI[] selectedSeqs = selectedSeqsToView
965    .toArray(new SequenceI[selectedSeqsToView.size()]);
966  0 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
967    selectedSeqs);
968    }
969  0 else if (currentView == VIEWS_ENTER_ID)
970    {
971  0 SequenceI userSelectedSeq = ((AssociateSeqOptions) idInputAssSeqPanel
972    .getCmb_assSeq().getSelectedItem()).getSequence();
973  0 if (userSelectedSeq != null)
974    {
975  0 selectedSequence = userSelectedSeq;
976    }
977  0 String pdbIdStr = txt_search.getText();
978  0 PDBEntry pdbEntry = selectedSequence.getPDBEntry(pdbIdStr);
979  0 if (pdbEntry == null)
980    {
981  0 pdbEntry = new PDBEntry();
982  0 if (pdbIdStr.split(":").length > 1)
983    {
984  0 pdbEntry.setId(pdbIdStr.split(":")[0]);
985  0 pdbEntry.setChainCode(pdbIdStr.split(":")[1].toUpperCase());
986    }
987    else
988    {
989  0 pdbEntry.setId(pdbIdStr);
990    }
991  0 pdbEntry.setType(PDBEntry.Type.PDB);
992  0 selectedSequence.getDatasetSequence().addPDBId(pdbEntry);
993    }
994   
995  0 PDBEntry[] pdbEntriesToView = new PDBEntry[] { pdbEntry };
996  0 sViewer = launchStructureViewer(ssm, pdbEntriesToView, ap,
997    new SequenceI[]
998    { selectedSequence });
999    }
1000  0 else if (currentView == VIEWS_FROM_FILE)
1001    {
1002  0 SequenceI userSelectedSeq = ((AssociateSeqOptions) fileChooserAssSeqPanel
1003    .getCmb_assSeq().getSelectedItem()).getSequence();
1004  0 if (userSelectedSeq != null)
1005    {
1006  0 selectedSequence = userSelectedSeq;
1007    }
1008  0 PDBEntry fileEntry = new AssociatePdbFileWithSeq()
1009    .associatePdbWithSeq(selectedPdbFileName,
1010    DataSourceType.FILE, selectedSequence, true,
1011    Desktop.instance);
1012   
1013  0 sViewer = launchStructureViewer(
1014    ssm, new PDBEntry[]
1015    { fileEntry }, ap,
1016    new SequenceI[]
1017    { selectedSequence });
1018    }
1019  0 SwingUtilities.invokeLater(new Runnable()
1020    {
 
1021  0 toggle @Override
1022    public void run()
1023    {
1024  0 closeAction(preferredHeight);
1025  0 mainFrame.dispose();
1026    }
1027    });
1028    }
1029    };
1030  0 Thread runner = new Thread(viewStruc);
1031  0 runner.start();
1032  0 if (waitUntilFinished)
1033    {
1034  0 while (sViewer == null ? runner.isAlive()
1035  0 : (sViewer.sview == null ? true
1036    : !sViewer.sview.hasMapping()))
1037    {
1038  0 try
1039    {
1040  0 Thread.sleep(300);
1041    } catch (InterruptedException ie)
1042    {
1043   
1044    }
1045    }
1046    }
1047    }
1048   
 
1049  0 toggle private PDBEntry getFindEntry(String id, Vector<PDBEntry> pdbEntries)
1050    {
1051  0 Objects.requireNonNull(id);
1052  0 Objects.requireNonNull(pdbEntries);
1053  0 PDBEntry foundEntry = null;
1054  0 for (PDBEntry entry : pdbEntries)
1055    {
1056  0 if (entry.getId().equalsIgnoreCase(id))
1057    {
1058  0 return entry;
1059    }
1060    }
1061  0 return foundEntry;
1062    }
1063   
1064    /**
1065    * Answers a structure viewer (new or existing) configured to superimpose
1066    * added structures or not according to the user's choice
1067    *
1068    * @param ssm
1069    * @return
1070    */
 
1071  0 toggle StructureViewer getTargetedStructureViewer(
1072    StructureSelectionManager ssm)
1073    {
1074  0 Object sv = targetView.getSelectedItem();
1075   
1076  0 return sv == null ? new StructureViewer(ssm) : (StructureViewer) sv;
1077    }
1078   
1079    /**
1080    * Adds PDB structures to a new or existing structure viewer
1081    *
1082    * @param ssm
1083    * @param pdbEntriesToView
1084    * @param alignPanel
1085    * @param sequences
1086    * @return
1087    */
 
1088  0 toggle private StructureViewer launchStructureViewer(
1089    StructureSelectionManager ssm,
1090    final PDBEntry[] pdbEntriesToView,
1091    final AlignmentPanel alignPanel, SequenceI[] sequences)
1092    {
1093  0 long progressId = sequences.hashCode();
1094  0 setProgressBar(MessageManager
1095    .getString("status.launching_3d_structure_viewer"), progressId);
1096  0 final StructureViewer theViewer = getTargetedStructureViewer(ssm);
1097  0 boolean superimpose = chk_superpose.isSelected();
1098  0 theViewer.setSuperpose(superimpose);
1099   
1100    /*
1101    * remember user's choice of superimpose or not
1102    */
1103  0 Cache.setProperty(AUTOSUPERIMPOSE,
1104    Boolean.valueOf(superimpose).toString());
1105   
1106  0 setProgressBar(null, progressId);
1107  0 if (SiftsSettings.isMapWithSifts())
1108    {
1109  0 List<SequenceI> seqsWithoutSourceDBRef = new ArrayList<>();
1110  0 int p = 0;
1111    // TODO: skip PDBEntry:Sequence pairs where PDBEntry doesn't look like a
1112    // real PDB ID. For moment, we can also safely do this if there is already
1113    // a known mapping between the PDBEntry and the sequence.
1114  0 for (SequenceI seq : sequences)
1115    {
1116  0 PDBEntry pdbe = pdbEntriesToView[p++];
1117  0 if (pdbe != null && pdbe.getFile() != null)
1118    {
1119  0 StructureMapping[] smm = ssm.getMapping(pdbe.getFile());
1120  0 if (smm != null && smm.length > 0)
1121    {
1122  0 for (StructureMapping sm : smm)
1123    {
1124  0 if (sm.getSequence() == seq)
1125    {
1126  0 continue;
1127    }
1128    }
1129    }
1130    }
1131  0 if (seq.getPrimaryDBRefs().isEmpty())
1132    {
1133  0 seqsWithoutSourceDBRef.add(seq);
1134  0 continue;
1135    }
1136    }
1137  0 if (!seqsWithoutSourceDBRef.isEmpty())
1138    {
1139  0 int y = seqsWithoutSourceDBRef.size();
1140  0 setProgressBar(MessageManager.formatMessage(
1141    "status.fetching_dbrefs_for_sequences_without_valid_refs",
1142    y), progressId);
1143  0 SequenceI[] seqWithoutSrcDBRef = seqsWithoutSourceDBRef
1144    .toArray(new SequenceI[y]);
1145  0 DBRefFetcher dbRefFetcher = new DBRefFetcher(seqWithoutSrcDBRef);
1146  0 dbRefFetcher.fetchDBRefs(true);
1147   
1148  0 setProgressBar("Fetch complete.", progressId); // todo i18n
1149    }
1150    }
1151  0 if (pdbEntriesToView.length > 1)
1152    {
1153  0 setProgressBar(MessageManager.getString(
1154    "status.fetching_3d_structures_for_selected_entries"),
1155    progressId);
1156  0 theViewer.viewStructures(pdbEntriesToView, sequences, alignPanel);
1157    }
1158    else
1159    {
1160  0 setProgressBar(MessageManager.formatMessage(
1161    "status.fetching_3d_structures_for",
1162    pdbEntriesToView[0].getId()),progressId);
1163  0 theViewer.viewStructures(pdbEntriesToView[0], sequences, alignPanel);
1164    }
1165  0 setProgressBar(null, progressId);
1166    // remember the last viewer we used...
1167  0 lastTargetedView = theViewer;
1168  0 return theViewer;
1169    }
1170   
1171    /**
1172    * Populates the combo-box used in associating manually fetched structures to
1173    * a unique sequence when more than one sequence selection is made.
1174    */
 
1175  2 toggle @Override
1176    protected void populateCmbAssociateSeqOptions(
1177    JComboBox<AssociateSeqOptions> cmb_assSeq,
1178    JLabel lbl_associateSeq)
1179    {
1180  2 cmb_assSeq.removeAllItems();
1181  2 cmb_assSeq.addItem(
1182    new AssociateSeqOptions("-Select Associated Seq-", null));
1183  2 lbl_associateSeq.setVisible(false);
1184  2 if (selectedSequences.length > 1)
1185    {
1186  0 for (SequenceI seq : selectedSequences)
1187    {
1188  0 cmb_assSeq.addItem(new AssociateSeqOptions(seq));
1189    }
1190    }
1191    else
1192    {
1193  2 String seqName = selectedSequence.getDisplayId(false);
1194  2 seqName = seqName.length() <= 40 ? seqName : seqName.substring(0, 39);
1195  2 lbl_associateSeq.setText(seqName);
1196  2 lbl_associateSeq.setVisible(true);
1197  2 cmb_assSeq.setVisible(false);
1198    }
1199    }
1200   
 
1201  1 toggle protected boolean isStructuresDiscovered()
1202    {
1203  1 return discoveredStructuresSet != null
1204    && !discoveredStructuresSet.isEmpty();
1205    }
1206   
1207    protected int PDB_ID_MIN = 3;// or: (Jalview.isJS() ? 3 : 1); // Bob proposes this.
1208    // Doing a search for "1" or "1c" is valuable?
1209    // Those work but are enormously slow.
1210   
 
1211  0 toggle @Override
1212    protected void txt_search_ActionPerformed()
1213    {
1214  0 String text = txt_search.getText().trim();
1215  0 if (text.length() >= PDB_ID_MIN)
1216  0 new Thread()
1217    {
1218   
 
1219  0 toggle @Override
1220    public void run()
1221    {
1222  0 errorWarning.setLength(0);
1223  0 isValidPBDEntry = false;
1224  0 if (text.length() > 0)
1225    {
1226  0 String searchTerm = text.toLowerCase();
1227  0 searchTerm = searchTerm.split(":")[0];
1228    // System.out.println(">>>>> search term : " + searchTerm);
1229  0 List<FTSDataColumnI> wantedFields = new ArrayList<>();
1230  0 FTSRestRequest pdbRequest = new FTSRestRequest();
1231  0 pdbRequest.setAllowEmptySeq(false);
1232  0 pdbRequest.setResponseSize(1);
1233  0 pdbRequest.setFieldToSearchBy("(pdb_id:");
1234  0 pdbRequest.setWantedFields(wantedFields);
1235  0 pdbRequest.setSearchTerm(searchTerm + ")");
1236  0 pdbRequest.setAssociatedSequence(selectedSequence);
1237  0 pdbRestClient = PDBFTSRestClient.getInstance();
1238  0 wantedFields.add(pdbRestClient.getPrimaryKeyColumn());
1239  0 FTSRestResponse resultList;
1240  0 try
1241    {
1242  0 resultList = pdbRestClient.executeRequest(pdbRequest);
1243    } catch (Exception e)
1244    {
1245  0 errorWarning.append(e.getMessage());
1246  0 return;
1247    } finally
1248    {
1249  0 validateSelections();
1250    }
1251  0 if (resultList.getSearchSummary() != null
1252    && resultList.getSearchSummary().size() > 0)
1253    {
1254  0 isValidPBDEntry = true;
1255    }
1256    }
1257  0 validateSelections();
1258    }
1259    }.start();
1260    }
1261   
 
1262  1 toggle @Override
1263    protected void tabRefresh()
1264    {
1265  1 if (selectedSequences != null)
1266    {
1267  0 Thread refreshThread = new Thread(new Runnable()
1268    {
 
1269  0 toggle @Override
1270    public void run()
1271    {
1272  0 fetchStructuresMetaData();
1273  0 filterResultSet(
1274    ((FilterOption) cmb_filterOption.getSelectedItem())
1275    .getValue());
1276    }
1277    });
1278  0 refreshThread.start();
1279    }
1280    }
1281   
 
1282    public class PDBEntryTableModel extends AbstractTableModel
1283    {
1284    String[] columns = { "Ref Sequence", "PDB Id", "Chain", "Type",
1285    "File" };
1286   
1287    private List<CachedPDB> pdbEntries;
1288   
 
1289  1 toggle public PDBEntryTableModel(List<CachedPDB> pdbEntries)
1290    {
1291  1 this.pdbEntries = new ArrayList<>(pdbEntries);
1292    }
1293   
 
1294  5 toggle @Override
1295    public String getColumnName(int columnIndex)
1296    {
1297  5 return columns[columnIndex];
1298    }
1299   
 
1300  7 toggle @Override
1301    public int getRowCount()
1302    {
1303  7 return pdbEntries.size();
1304    }
1305   
 
1306  6 toggle @Override
1307    public int getColumnCount()
1308    {
1309  6 return columns.length;
1310    }
1311   
 
1312  0 toggle @Override
1313    public boolean isCellEditable(int row, int column)
1314    {
1315  0 return false;
1316    }
1317   
 
1318  0 toggle @Override
1319    public Object getValueAt(int rowIndex, int columnIndex)
1320    {
1321  0 Object value = "??";
1322  0 CachedPDB entry = pdbEntries.get(rowIndex);
1323  0 switch (columnIndex)
1324    {
1325  0 case 0:
1326  0 value = entry.getSequence();
1327  0 break;
1328  0 case 1:
1329  0 value = entry.getPdbEntry();
1330  0 break;
1331  0 case 2:
1332  0 value = entry.getPdbEntry().getChainCode() == null ? "_"
1333    : entry.getPdbEntry().getChainCode();
1334  0 break;
1335  0 case 3:
1336  0 value = entry.getPdbEntry().getType();
1337  0 break;
1338  0 case 4:
1339  0 value = entry.getPdbEntry().getFile();
1340  0 break;
1341    }
1342  0 return value;
1343    }
1344   
 
1345  0 toggle @Override
1346    public Class<?> getColumnClass(int columnIndex)
1347    {
1348  0 return columnIndex == 0 ? SequenceI.class : PDBEntry.class;
1349    }
1350   
 
1351  0 toggle public CachedPDB getPDBEntryAt(int row)
1352    {
1353  0 return pdbEntries.get(row);
1354    }
1355   
1356    }
1357   
 
1358    private class CachedPDB
1359    {
1360    private SequenceI sequence;
1361   
1362    private PDBEntry pdbEntry;
1363   
 
1364  0 toggle public CachedPDB(SequenceI sequence, PDBEntry pdbEntry)
1365    {
1366  0 this.sequence = sequence;
1367  0 this.pdbEntry = pdbEntry;
1368    }
1369   
 
1370  0 toggle public SequenceI getSequence()
1371    {
1372  0 return sequence;
1373    }
1374   
 
1375  0 toggle public PDBEntry getPdbEntry()
1376    {
1377  0 return pdbEntry;
1378    }
1379   
1380    }
1381   
1382    private IProgressIndicator progressBar;
1383   
 
1384  0 toggle @Override
1385    public void setProgressBar(String message, long id)
1386    {
1387  0 progressBar.setProgressBar(message, id);
1388    }
1389   
 
1390  0 toggle @Override
1391    public void registerHandler(long id, IProgressIndicatorHandler handler)
1392    {
1393  0 progressBar.registerHandler(id, handler);
1394    }
1395   
 
1396  0 toggle @Override
1397    public boolean operationInProgress()
1398    {
1399  0 return progressBar.operationInProgress();
1400    }
1401   
 
1402  0 toggle public JalviewStructureDisplayI getOpenedStructureViewer()
1403    {
1404  0 return sViewer == null ? null : sViewer.sview;
1405    }
1406    }