+ /**
+ * Initializes parameters used by the Structure Chooser Panel
+ */
+ protected void init()
+ {
+ if (!Jalview.isHeadlessMode())
+ {
+ progressBar = new ProgressBar(this.statusPanel, this.statusBar);
+ }
+
+ chk_superpose.setSelected(Cache.getDefault(AUTOSUPERIMPOSE, true));
+
+ // ensure a filter option is in force for search
+ populateFilterComboBox(true, cachedPDBExists);
+ Thread discoverPDBStructuresThread = new Thread(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ long startTime = System.currentTimeMillis();
+ updateProgressIndicator(MessageManager
+ .getString("status.loading_cached_pdb_entries"), startTime);
+ loadLocalCachedPDBEntries();
+ updateProgressIndicator(null, startTime);
+ updateProgressIndicator(MessageManager.getString(
+ "status.searching_for_pdb_structures"), startTime);
+ fetchStructuresMetaData();
+ // revise filter options if no results were found
+ populateFilterComboBox(isStructuresDiscovered(), cachedPDBExists);
+ discoverStructureViews();
+ updateProgressIndicator(null, startTime);
+ mainFrame.setVisible(true);
+ updateCurrentView();
+ }
+ });
+ discoverPDBStructuresThread.start();
+ }
+
+ /**
+ * Builds a drop-down choice list of existing structure viewers to which new
+ * structures may be added. If this list is empty then it, and the 'Add'
+ * button, are hidden.
+ */
+ private void discoverStructureViews()
+ {
+ if (Desktop.instance != null)
+ {
+ targetView.removeAllItems();
+ if (lastTargetedView != null && !lastTargetedView.isVisible())
+ {
+ lastTargetedView = null;
+ }
+ int linkedViewsAt = 0;
+ for (StructureViewerBase view : Desktop.instance
+ .getStructureViewers(null, null))
+ {
+ StructureViewer viewHandler = (lastTargetedView != null
+ && lastTargetedView.sview == view) ? lastTargetedView
+ : StructureViewer.reconfigure(view);
+
+ if (view.isLinkedWith(ap))
+ {
+ targetView.insertItemAt(viewHandler,
+ linkedViewsAt++);
+ }
+ else
+ {
+ targetView.addItem(viewHandler);
+ }
+ }
+
+ /*
+ * show option to Add to viewer if at least 1 viewer found
+ */
+ targetView.setVisible(false);
+ if (targetView.getItemCount() > 0)
+ {
+ targetView.setVisible(true);
+ if (lastTargetedView != null)
+ {
+ targetView.setSelectedItem(lastTargetedView);
+ }
+ else
+ {
+ targetView.setSelectedIndex(0);
+ }
+ }
+ btn_add.setVisible(targetView.isVisible());
+ }
+ }
+
+ /**
+ * Updates the progress indicator with the specified message
+ *
+ * @param message
+ * displayed message for the operation
+ * @param id
+ * unique handle for this indicator
+ */
+ protected void updateProgressIndicator(String message, long id)
+ {
+ if (progressIndicator != null)
+ {
+ progressIndicator.setProgressBar(message, id);
+ }
+ }
+
+ /**
+ * Retrieve meta-data for all the structure(s) for a given sequence(s) in a
+ * selection group
+ */
+ void fetchStructuresMetaData()
+ {
+ long startTime = System.currentTimeMillis();
+ pdbRestClient = PDBFTSRestClient.getInstance();
+ Collection<FTSDataColumnI> wantedFields = pdbDocFieldPrefs
+ .getStructureSummaryFields();
+
+ discoveredStructuresSet = new LinkedHashSet<>();
+ HashSet<String> errors = new HashSet<>();
+ for (SequenceI seq : selectedSequences)
+ {
+ FTSRestRequest pdbRequest = new FTSRestRequest();
+ pdbRequest.setAllowEmptySeq(false);
+ pdbRequest.setResponseSize(500);
+ pdbRequest.setFieldToSearchBy("(");
+ FilterOption selectedFilterOpt = ((FilterOption) cmb_filterOption
+ .getSelectedItem());
+ pdbRequest.setFieldToSortBy(selectedFilterOpt.getValue(),
+ !chk_invertFilter.isSelected());
+ pdbRequest.setWantedFields(wantedFields);
+ pdbRequest.setSearchTerm(buildQuery(seq) + ")");
+ pdbRequest.setAssociatedSequence(seq);
+ FTSRestResponse resultList;
+ try
+ {
+ resultList = pdbRestClient.executeRequest(pdbRequest);
+ } catch (Exception e)
+ {
+ e.printStackTrace();
+ errors.add(e.getMessage());
+ continue;
+ }
+ lastPdbRequest = pdbRequest;
+ if (resultList.getSearchSummary() != null
+ && !resultList.getSearchSummary().isEmpty())
+ {
+ discoveredStructuresSet.addAll(resultList.getSearchSummary());
+ }
+ }
+
+ int noOfStructuresFound = 0;
+ String totalTime = (System.currentTimeMillis() - startTime)
+ + " milli secs";
+ if (discoveredStructuresSet != null
+ && !discoveredStructuresSet.isEmpty())
+ {
+ getResultTable().setModel(FTSRestResponse
+ .getTableModel(lastPdbRequest, discoveredStructuresSet));
+ noOfStructuresFound = discoveredStructuresSet.size();
+ mainFrame.setTitle(MessageManager.formatMessage(
+ "label.structure_chooser_no_of_structures",
+ noOfStructuresFound, totalTime));
+ }
+ else
+ {
+ mainFrame.setTitle(MessageManager
+ .getString("label.structure_chooser_manual_association"));
+ if (errors.size() > 0)
+ {
+ StringBuilder errorMsg = new StringBuilder();
+ for (String error : errors)
+ {
+ errorMsg.append(error).append("\n");
+ }
+ JvOptionPane.showMessageDialog(this, errorMsg.toString(),
+ MessageManager.getString("label.pdb_web-service_error"),
+ JvOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+
+ protected void loadLocalCachedPDBEntries()
+ {
+ ArrayList<CachedPDB> entries = new ArrayList<>();
+ for (SequenceI seq : selectedSequences)
+ {
+ if (seq.getDatasetSequence() != null
+ && seq.getDatasetSequence().getAllPDBEntries() != null)
+ {
+ for (PDBEntry pdbEntry : seq.getDatasetSequence()
+ .getAllPDBEntries())
+ {
+ if (pdbEntry.getFile() != null)
+ {
+ entries.add(new CachedPDB(seq, pdbEntry));
+ }
+ }
+ }
+ }
+ cachedPDBExists = !entries.isEmpty();
+ PDBEntryTableModel tableModelx = new PDBEntryTableModel(entries);
+ tbl_local_pdb.setModel(tableModelx);
+ }
+
+ /**
+ * Builds a query string for a given sequences using its DBRef entries
+ *
+ * @param seq
+ * the sequences to build a query for
+ * @return the built query string
+ */
+
+ static String buildQuery(SequenceI seq)
+ {
+ boolean isPDBRefsFound = false;
+ boolean isUniProtRefsFound = false;
+ StringBuilder queryBuilder = new StringBuilder();
+ Set<String> seqRefs = new LinkedHashSet<>();
+
+ /*
+ * note PDBs as DBRefEntry so they are not duplicated in query
+ */
+ Set<String> pdbids = new HashSet<>();
+
+ if (seq.getAllPDBEntries() != null
+ && queryBuilder.length() < MAX_QLENGTH)
+ {
+ for (PDBEntry entry : seq.getAllPDBEntries())
+ {
+ if (isValidSeqName(entry.getId()))
+ {
+ String id = entry.getId().toLowerCase();
+ queryBuilder.append("pdb_id:").append(id).append(" OR ");
+ isPDBRefsFound = true;
+ pdbids.add(id);
+ }
+ }
+ }
+
+ List<DBRefEntry> refs = seq.getDBRefs();
+ if (refs != null && refs.size() != 0)
+ {
+ for (int ib = 0, nb = refs.size(); ib < nb; ib++)
+ {
+ DBRefEntry dbRef = refs.get(ib);
+ if (isValidSeqName(getDBRefId(dbRef))
+ && queryBuilder.length() < MAX_QLENGTH)
+ {
+ if (dbRef.getSource().equalsIgnoreCase(DBRefSource.UNIPROT))
+ {
+ queryBuilder.append("uniprot_accession:")
+ .append(getDBRefId(dbRef)).append(" OR ");
+ queryBuilder.append("uniprot_id:").append(getDBRefId(dbRef))
+ .append(" OR ");
+ isUniProtRefsFound = true;
+ }
+ else if (dbRef.getSource().equalsIgnoreCase(DBRefSource.PDB))
+ {
+
+ String id = getDBRefId(dbRef).toLowerCase();
+ if (!pdbids.contains(id))
+ {
+ queryBuilder.append("pdb_id:").append(id).append(" OR ");
+ isPDBRefsFound = true;
+ pdbids.add(id);
+ }
+ }
+ else
+ {
+ seqRefs.add(getDBRefId(dbRef));
+ }
+ }
+ }
+ }
+
+ if (!isPDBRefsFound && !isUniProtRefsFound)
+ {
+ String seqName = seq.getName();
+ seqName = sanitizeSeqName(seqName);
+ String[] names = seqName.toLowerCase().split("\\|");
+ for (String name : names)
+ {
+ // System.out.println("Found name : " + name);
+ name.trim();
+ if (isValidSeqName(name))
+ {
+ seqRefs.add(name);
+ }
+ }
+
+ for (String seqRef : seqRefs)
+ {
+ queryBuilder.append("text:").append(seqRef).append(" OR ");
+ }
+ }
+
+ int endIndex = queryBuilder.lastIndexOf(" OR ");
+ if (queryBuilder.toString().length() < 6)
+ {
+ return null;
+ }
+ String query = queryBuilder.toString().substring(0, endIndex);
+ return query;
+ }
+
+ /**
+ * Remove the following special characters from input string +, -, &, !, (, ),
+ * {, }, [, ], ^, ", ~, *, ?, :, \
+ *
+ * @param seqName
+ * @return
+ */
+ static String sanitizeSeqName(String seqName)
+ {
+ Objects.requireNonNull(seqName);
+ return seqName.replaceAll("\\[\\d*\\]", "")
+ .replaceAll("[^\\dA-Za-z|_]", "").replaceAll("\\s+", "+");
+ }
+
+ /**
+ * Ensures sequence ref names are not less than 3 characters and does not
+ * contain a database name
+ *
+ * @param seqName
+ * @return
+ */
+ static boolean isValidSeqName(String seqName)
+ {
+ // System.out.println("seqName : " + seqName);
+ String ignoreList = "pdb,uniprot,swiss-prot";
+ if (seqName.length() < 3)
+ {
+ return false;
+ }
+ if (seqName.contains(":"))
+ {
+ return false;
+ }
+ seqName = seqName.toLowerCase();
+ for (String ignoredEntry : ignoreList.split(","))
+ {
+ if (seqName.contains(ignoredEntry))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ static String getDBRefId(DBRefEntry dbRef)