package jalview.gui.structurechooser; import java.util.Collection; import java.util.List; import java.util.Objects; import java.util.Vector; import javax.swing.JTable; import javax.swing.table.TableModel; import jalview.datamodel.DBRefEntry; import jalview.datamodel.PDBEntry; import jalview.datamodel.SequenceI; import jalview.fts.api.FTSData; import jalview.fts.api.FTSDataColumnI; import jalview.fts.api.FTSRestClientI; import jalview.fts.core.FTSDataColumnPreferences; import jalview.fts.core.FTSRestRequest; import jalview.fts.core.FTSRestResponse; import jalview.jbgui.FilterOption; /** * logic for querying sources of structural data for structures of sequences * * @author jprocter * * @param */ public abstract class StructureChooserQuerySource { protected FTSDataColumnPreferences docFieldPrefs; /** * max length of a GET URL (probably :( ) */ protected static int MAX_QLENGTH = 7820; public StructureChooserQuerySource() { } public static StructureChooserQuerySource getPDBfts() { return new PDBStructureChooserQuerySource(); } public static StructureChooserQuerySource getTDBfts() { return new ThreeDBStructureChooserQuerySource(); } public FTSDataColumnPreferences getDocFieldPrefs() { return docFieldPrefs; } public void setDocFieldPrefs(FTSDataColumnPreferences docFieldPrefs) { this.docFieldPrefs = docFieldPrefs; } public FTSDataColumnPreferences getInitialFieldPreferences() { return docFieldPrefs; } /** * 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 */ public abstract String buildQuery(SequenceI seq); /** * Remove the following special characters from input string +, -, &, !, (, ), * {, }, [, ], ^, ", ~, *, ?, :, \ * * @param seqName * @return */ public 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) { String ref = dbRef.getAccessionId().replaceAll("GO:", ""); return ref; } static PDBEntry getFindEntry(String id, Vector pdbEntries) { Objects.requireNonNull(id); Objects.requireNonNull(pdbEntries); PDBEntry foundEntry = null; for (PDBEntry entry : pdbEntries) { if (entry.getId().equalsIgnoreCase(id)) { return entry; } } return foundEntry; } /** * FTSRestClient specific query builder to recover associated structure data * records for a sequence * * @param seq * - seq to generate a query for * @param wantedFields * - fields to retrieve * @param selectedFilterOpt * - criterion for ranking results (e.g. resolution) * @param b * - sort ascending or descending * @return * @throws Exception */ public abstract FTSRestResponse fetchStructuresMetaData(SequenceI seq, Collection wantedFields, FilterOption selectedFilterOpt, boolean b) throws Exception; /** * FTSRestClient specific query builder to pick top ranked entry from a * fetchStructuresMetaData query * * @param seq * - seq to generate a query for * @param discoveredStructuresSet - existing set of entries - allows client side selection * @param wantedFields * - fields to retrieve * @param selectedFilterOpt * - criterion for ranking results (e.g. resolution) * @param b * - sort ascending or descending * @return * @throws Exception */ public abstract FTSRestResponse selectFirstRankedQuery(SequenceI seq, Collection discoveredStructuresSet, Collection wantedFields, String fieldToFilterBy, boolean b) throws Exception; /** * * @param discoveredStructuresSet * @return the table model for the given result set for this engine */ public TableModel getTableModel( Collection discoveredStructuresSet) { return FTSRestResponse.getTableModel(getLastFTSRequest(), discoveredStructuresSet); } protected abstract FTSRestRequest getLastFTSRequest(); public abstract PDBEntry[] collectSelectedRows(JTable restable, int[] selectedRows, List selectedSeqsToView); /** * @param VIEWS_FILTER * - a String key that can be used by the caller to tag the returned filter * options to distinguish them in a collection * @return list of FilterOption - convention is that the last one in the list * will be constructed with 'addSeparator==true' */ public abstract List getAvailableFilterOptions(String VIEWS_FILTER); /** * construct a structure chooser query source for the given set of sequences * @param selectedSeqs * @return PDBe or 3DB query source */ public static StructureChooserQuerySource getQuerySourceFor( SequenceI[] selectedSeqs) { ThreeDBStructureChooserQuerySource tdbSource = new ThreeDBStructureChooserQuerySource(); boolean hasUniprot=false; boolean hasNA=false,hasProtein=false; for (SequenceI seq:selectedSeqs) { hasNA|=!seq.isProtein(); hasProtein |= seq.isProtein(); if (seq.isProtein()) { String query = tdbSource.buildQuery(seq); if (query!=null && query.length()>0) { hasUniprot=true; } } } if (hasProtein && hasUniprot && !hasNA) { return tdbSource; } return new PDBStructureChooserQuerySource(); } /** * some filter options may mean the original query needs to be executed again. * @param selectedFilterOpt * @return true if the fetchStructuresMetadata method needs to be called again */ public abstract boolean needsRefetch(FilterOption selectedFilterOpt); }