96b67e499314b879a78aba486cbd5224d6cdebe6
[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 wantedFields
171    *          - fields to retrieve
172    * @param selectedFilterOpt
173    *          - criterion for ranking results (e.g. resolution)
174    * @param b
175    *          - sort ascending or descending
176    * @return
177    * @throws Exception
178    */
179   public abstract FTSRestResponse selectFirstRankedQuery(SequenceI seq,
180           Collection<FTSDataColumnI> wantedFields, String fieldToFilterBy,
181           boolean b) throws Exception;
182
183   /**
184    * 
185    * @param discoveredStructuresSet
186    * @return the table model for the given result set for this engine
187    */
188   public TableModel getTableModel(
189           Collection<FTSData> discoveredStructuresSet)
190   {
191     return FTSRestResponse.getTableModel(getLastFTSRequest(),
192             discoveredStructuresSet);
193   }
194
195   protected abstract FTSRestRequest getLastFTSRequest();
196
197   public abstract PDBEntry[] collectSelectedRows(JTable restable,
198           int[] selectedRows, List<SequenceI> selectedSeqsToView);
199
200   /**
201    * @param VIEWS_FILTER
202    *          - a String key that can be used by the caller to tag the returned filter
203    *          options to distinguish them in a collection
204    * @return list of FilterOption - convention is that the last one in the list
205    *         will be constructed with 'addSeparator==true'
206    */
207   public abstract List<FilterOption> getAvailableFilterOptions(String VIEWS_FILTER);
208
209   /**
210    * construct a structure chooser query source for the given set of sequences
211    * @param selectedSeqs
212    * @return PDBe or 3DB query source
213    */
214   public static StructureChooserQuerySource getQuerySourceFor(
215           SequenceI[] selectedSeqs)
216   {
217     ThreeDBStructureChooserQuerySource tdbSource = new ThreeDBStructureChooserQuerySource();
218     boolean hasUniprot=false;
219     boolean hasNA=false,hasProtein=false;
220     for (SequenceI seq:selectedSeqs)
221     {
222       hasNA|=!seq.isProtein();
223       hasProtein |= seq.isProtein();
224       if (seq.isProtein())
225       {
226         String query = tdbSource.buildQuery(seq);
227         if (query!=null && query.length()>0)
228         {
229           hasUniprot=true;
230         }
231       }
232     }
233     if (hasProtein && hasUniprot && !hasNA)
234     {
235       return tdbSource;
236     }
237     return new PDBStructureChooserQuerySource();
238   }
239
240 }