1023b59ab09c98274fb003cb4a932d900b10327c
[jalview.git] / src / jalview / gui / structurechooser / StructureChooserQuerySource.java
1 package jalview.gui.structurechooser;
2
3 import java.util.Collection;
4 import java.util.List;
5 import java.util.Objects;
6 import java.util.Vector;
7
8 import javax.swing.JTable;
9 import javax.swing.table.TableModel;
10
11 import jalview.datamodel.DBRefEntry;
12 import jalview.datamodel.PDBEntry;
13 import jalview.datamodel.SequenceI;
14 import jalview.fts.api.FTSData;
15 import jalview.fts.api.FTSDataColumnI;
16 import jalview.fts.api.FTSRestClientI;
17 import jalview.fts.core.FTSDataColumnPreferences;
18 import jalview.fts.core.FTSRestRequest;
19 import jalview.fts.core.FTSRestResponse;
20 import jalview.jbgui.FilterOption;
21
22 /**
23  * logic for querying sources of structural data for structures of sequences
24  * 
25  * @author jprocter
26  *
27  * @param <T>
28  */
29 public abstract class StructureChooserQuerySource
30 {
31
32   protected FTSDataColumnPreferences docFieldPrefs;
33
34   /**
35    * max length of a GET URL (probably :( )
36    */
37   protected static int MAX_QLENGTH = 7820;
38
39   public StructureChooserQuerySource()
40   {
41   }
42
43   public static StructureChooserQuerySource getPDBfts()
44   {
45           return new PDBStructureChooserQuerySource();
46   }
47
48   public static StructureChooserQuerySource getTDBfts()
49   {
50     return new ThreeDBStructureChooserQuerySource();
51   }
52
53   public FTSDataColumnPreferences getDocFieldPrefs()
54   {
55     return docFieldPrefs;
56   }
57
58   public void setDocFieldPrefs(FTSDataColumnPreferences docFieldPrefs)
59   {
60     this.docFieldPrefs = docFieldPrefs;
61   }
62
63   public FTSDataColumnPreferences getInitialFieldPreferences()
64   {
65     return docFieldPrefs;
66   }
67
68
69   /**
70    * Builds a query string for a given sequences using its DBRef entries
71    * 
72    * @param seq
73    *          the sequences to build a query for
74    * @return the built query string
75    */
76
77   public abstract String buildQuery(SequenceI seq);
78   
79
80   /**
81    * Remove the following special characters from input string +, -, &, !, (, ),
82    * {, }, [, ], ^, ", ~, *, ?, :, \
83    * 
84    * @param seqName
85    * @return
86    */
87   public static String sanitizeSeqName(String seqName)
88   {
89     Objects.requireNonNull(seqName);
90     return seqName.replaceAll("\\[\\d*\\]", "")
91             .replaceAll("[^\\dA-Za-z|_]", "").replaceAll("\\s+", "+");
92   }
93
94   /**
95    * Ensures sequence ref names are not less than 3 characters and does not
96    * contain a database name
97    * 
98    * @param seqName
99    * @return
100    */
101   static boolean isValidSeqName(String seqName)
102   {
103     // System.out.println("seqName : " + seqName);
104     String ignoreList = "pdb,uniprot,swiss-prot";
105     if (seqName.length() < 3)
106     {
107       return false;
108     }
109     if (seqName.contains(":"))
110     {
111       return false;
112     }
113     seqName = seqName.toLowerCase();
114     for (String ignoredEntry : ignoreList.split(","))
115     {
116       if (seqName.contains(ignoredEntry))
117       {
118         return false;
119       }
120     }
121     return true;
122   }
123
124   static String getDBRefId(DBRefEntry dbRef)
125   {
126     String ref = dbRef.getAccessionId().replaceAll("GO:", "");
127     return ref;
128   }
129
130   static PDBEntry getFindEntry(String id, Vector<PDBEntry> pdbEntries)
131   {
132     Objects.requireNonNull(id);
133     Objects.requireNonNull(pdbEntries);
134     PDBEntry foundEntry = null;
135     for (PDBEntry entry : pdbEntries)
136     {
137       if (entry.getId().equalsIgnoreCase(id))
138       {
139         return entry;
140       }
141     }
142     return foundEntry;
143   }
144
145   /**
146    * FTSRestClient specific query builder to recover associated structure data
147    * records for a sequence
148    * 
149    * @param seq
150    *          - seq to generate a query for
151    * @param wantedFields
152    *          - fields to retrieve
153    * @param selectedFilterOpt
154    *          - criterion for ranking results (e.g. resolution)
155    * @param b
156    *          - sort ascending or descending
157    * @return
158    * @throws Exception
159    */
160   public abstract FTSRestResponse fetchStructuresMetaData(SequenceI seq,
161           Collection<FTSDataColumnI> wantedFields,
162           FilterOption selectedFilterOpt, boolean b) throws Exception;
163
164   /**
165    * FTSRestClient specific query builder to pick top ranked entry from a
166    * fetchStructuresMetaData query
167    * 
168    * @param seq
169    *          - seq to generate a query for
170    * @param discoveredStructuresSet - existing set of entries - allows client side selection
171    * @param wantedFields
172    *          - fields to retrieve
173    * @param selectedFilterOpt
174    *          - criterion for ranking results (e.g. resolution)
175    * @param b
176    *          - sort ascending or descending
177    * @return
178    * @throws Exception
179    */
180   public abstract FTSRestResponse selectFirstRankedQuery(SequenceI seq,
181           Collection<FTSData> discoveredStructuresSet, Collection<FTSDataColumnI> wantedFields, String fieldToFilterBy,
182           boolean b) throws Exception;
183
184   /**
185    * 
186    * @param discoveredStructuresSet
187    * @return the table model for the given result set for this engine
188    */
189   public TableModel getTableModel(
190           Collection<FTSData> discoveredStructuresSet)
191   {
192     return FTSRestResponse.getTableModel(getLastFTSRequest(),
193             discoveredStructuresSet);
194   }
195
196   protected abstract FTSRestRequest getLastFTSRequest();
197
198   public abstract PDBEntry[] collectSelectedRows(JTable restable,
199           int[] selectedRows, List<SequenceI> selectedSeqsToView);
200
201   /**
202    * @param VIEWS_FILTER
203    *          - a String key that can be used by the caller to tag the returned filter
204    *          options to distinguish them in a collection
205    * @return list of FilterOption - convention is that the last one in the list
206    *         will be constructed with 'addSeparator==true'
207    */
208   public abstract List<FilterOption> getAvailableFilterOptions(String VIEWS_FILTER);
209
210   /**
211    * construct a structure chooser query source for the given set of sequences
212    * @param selectedSeqs
213    * @return PDBe or 3DB query source
214    */
215   public static StructureChooserQuerySource getQuerySourceFor(
216           SequenceI[] selectedSeqs)
217   {
218     ThreeDBStructureChooserQuerySource tdbSource = new ThreeDBStructureChooserQuerySource();
219     boolean hasUniprot=false,hasCanonical=false;
220     boolean hasNA=false,hasProtein=false;
221     int protWithoutUni=0;
222     for (SequenceI seq : selectedSeqs)
223     {
224       hasNA |= !seq.isProtein();
225       hasProtein |= seq.isProtein();
226       if (seq.isProtein())
227       {
228         int refsAvailable = ThreeDBStructureChooserQuerySource.checkUniprotRefs(seq.getDBRefs());
229         if (refsAvailable > -2)
230         {
231           if (refsAvailable > -1)
232             hasCanonical = true;
233         }
234         hasUniprot = true;
235       }
236       else
237       {
238         protWithoutUni++;
239       }
240     }
241     //
242     // logic: all canonicals - no fetchdb
243     // some uniprot no canonicals: prompt do fetchDb for remaining
244     // no uniprot but protein: offer 3d-beacons search
245     //
246     if (hasProtein && hasUniprot && !hasNA)
247     {
248       return tdbSource;
249     }
250     return new PDBStructureChooserQuerySource();
251   }
252
253   /**
254    * some filter options may mean the original query needs to be executed again. 
255    * @param selectedFilterOpt
256    * @return true if the fetchStructuresMetadata method needs to be called again
257    */
258   public abstract boolean needsRefetch(FilterOption selectedFilterOpt);
259
260   
261   
262   public void updateAvailableFilterOptions(String VIEWS_FILTER,
263           List<FilterOption> xtantOptions, Collection<FTSData> lastFTSData)
264   {
265     // TODO Auto-generated method stub
266     
267   }}