Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
TDBeaconsFTSRestClient | 52 | 108 | 43 |
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 | package jalview.fts.service.threedbeacons; | |
22 | ||
23 | import java.net.URI; | |
24 | import java.util.ArrayList; | |
25 | import java.util.Collection; | |
26 | import java.util.Iterator; | |
27 | import java.util.List; | |
28 | import java.util.Map; | |
29 | ||
30 | import javax.ws.rs.core.MediaType; | |
31 | ||
32 | import org.json.simple.parser.ParseException; | |
33 | ||
34 | import com.sun.jersey.api.client.Client; | |
35 | import com.sun.jersey.api.client.ClientResponse; | |
36 | import com.sun.jersey.api.client.WebResource; | |
37 | import com.sun.jersey.api.client.config.DefaultClientConfig; | |
38 | ||
39 | import jalview.datamodel.SequenceI; | |
40 | import jalview.fts.api.FTSData; | |
41 | import jalview.fts.api.FTSDataColumnI; | |
42 | import jalview.fts.api.FTSRestClientI; | |
43 | import jalview.fts.api.StructureFTSRestClientI; | |
44 | import jalview.fts.core.FTSDataColumnPreferences.PreferenceSource; | |
45 | import jalview.fts.core.FTSRestClient; | |
46 | import jalview.fts.core.FTSRestRequest; | |
47 | import jalview.fts.core.FTSRestResponse; | |
48 | import jalview.util.JSONUtils; | |
49 | import jalview.util.MessageManager; | |
50 | import jalview.util.Platform; | |
51 | ||
52 | public class TDBeaconsFTSRestClient extends FTSRestClient | |
53 | implements StructureFTSRestClientI | |
54 | { | |
55 | /** | |
56 | * production server URI | |
57 | */ | |
58 | private static String TDB_PROD_API = "https://www.ebi.ac.uk/pdbe/pdbe-kb/3dbeacons/api/uniprot/summary/"; | |
59 | ||
60 | /** | |
61 | * dev server URI | |
62 | */ | |
63 | private static String TDB_DEV_API = "https://wwwdev.ebi.ac.uk/pdbe/pdbe-kb/3dbeacons/api/uniprot/summary/"; | |
64 | ||
65 | private static String DEFAULT_THREEDBEACONS_DOMAIN = TDB_PROD_API; | |
66 | ||
67 | public static FTSRestClientI instance = null; | |
68 | ||
69 | 5 | protected TDBeaconsFTSRestClient() |
70 | { | |
71 | } | |
72 | ||
73 | 14 | @SuppressWarnings("unchecked") |
74 | @Override | |
75 | public FTSRestResponse executeRequest(FTSRestRequest tdbRestRequest) | |
76 | throws Exception | |
77 | { | |
78 | 14 | try |
79 | { | |
80 | 14 | String query = tdbRestRequest.getSearchTerm(); |
81 | 14 | Client client; |
82 | 14 | Class<ClientResponse> clientResponseClass; |
83 | 14 | if (Platform.isJS()) |
84 | { | |
85 | // JavaScript only | |
86 | 0 | client = (Client) (Object) new jalview.javascript.web.Client(); |
87 | 0 | clientResponseClass = (Class<ClientResponse>) (Object) jalview.javascript.web.ClientResponse.class; |
88 | } | |
89 | else | |
90 | /** | |
91 | * Java only | |
92 | * | |
93 | * @j2sIgnore | |
94 | */ | |
95 | { | |
96 | 14 | client = Client.create(new DefaultClientConfig()); |
97 | 14 | clientResponseClass = ClientResponse.class; |
98 | } | |
99 | ||
100 | 14 | WebResource webResource; |
101 | 14 | webResource = client.resource(DEFAULT_THREEDBEACONS_DOMAIN + query); |
102 | ||
103 | 14 | URI uri = webResource.getURI(); |
104 | 14 | jalview.bin.Console.outPrintln(uri.toString()); |
105 | ||
106 | // Execute the REST request | |
107 | 14 | ClientResponse clientResponse; |
108 | 14 | if (isMocked()) |
109 | { | |
110 | 14 | clientResponse = null; |
111 | } | |
112 | else | |
113 | { | |
114 | 0 | clientResponse = webResource.accept(MediaType.APPLICATION_JSON) |
115 | .get(clientResponseClass); | |
116 | } | |
117 | ||
118 | // Get the JSON string from the response object or directly from the | |
119 | // client (JavaScript) | |
120 | 14 | Map<String, Object> jsonObj = null; |
121 | 14 | String responseString = null; |
122 | ||
123 | // Check the response status and report exception if one occurs | |
124 | 14 | int responseStatus = isMocked() |
125 | 14 | ? (mockQueries.containsKey(query) ? 200 : 404) |
126 | : clientResponse.getStatus(); | |
127 | 14 | switch (responseStatus) |
128 | { | |
129 | // if success | |
130 | 13 | case 200: |
131 | 13 | if (Platform.isJS()) |
132 | { | |
133 | 0 | jsonObj = clientResponse.getEntity(Map.class); |
134 | } | |
135 | else | |
136 | { | |
137 | 13 | responseString = isMocked() ? mockQueries.get(query) |
138 | : clientResponse.getEntity(String.class); | |
139 | } | |
140 | 13 | break; |
141 | 0 | case 400: |
142 | 0 | throw new Exception(parseJsonExceptionString(responseString)); |
143 | 1 | case 404: |
144 | 1 | return emptyTDBeaconsJsonResponse(); |
145 | 0 | default: |
146 | 0 | throw new Exception( |
147 | getMessageByHTTPStatusCode(responseStatus, "3DBeacons")); | |
148 | } | |
149 | // Process the response and return the result to the caller. | |
150 | 13 | return parseTDBeaconsJsonResponse(responseString, jsonObj, |
151 | tdbRestRequest); | |
152 | } catch (Exception e) | |
153 | { | |
154 | 0 | String exceptionMsg = e.getMessage(); |
155 | 0 | if (exceptionMsg != null) |
156 | { | |
157 | 0 | if (exceptionMsg.contains("SocketException")) |
158 | { | |
159 | // No internet connection | |
160 | 0 | throw new Exception(MessageManager.getString( |
161 | "exception.unable_to_detect_internet_connection")); | |
162 | } | |
163 | 0 | else if (exceptionMsg.contains("UnknownHostException")) |
164 | { | |
165 | // The server is unreachable | |
166 | 0 | throw new Exception(MessageManager.formatMessage( |
167 | "exception.fts_server_unreachable", "3DB Hub")); | |
168 | } | |
169 | } | |
170 | 0 | throw e; |
171 | ||
172 | } | |
173 | ||
174 | } | |
175 | ||
176 | /** | |
177 | * returns response for when the 3D-Beacons service doesn't have a record for | |
178 | * the given query - in 2.11.2 this triggers a failover to the PDBe FTS | |
179 | * | |
180 | * @return null | |
181 | */ | |
182 | 1 | private FTSRestResponse emptyTDBeaconsJsonResponse() |
183 | { | |
184 | 1 | return null; |
185 | } | |
186 | ||
187 | 0 | public String setSearchTerm(String term) |
188 | { | |
189 | 0 | return term; |
190 | } | |
191 | ||
192 | 0 | public static FTSRestResponse parseTDBeaconsJsonResponse( |
193 | String tdbJsonResponseString, FTSRestRequest tdbRestRequest) | |
194 | { | |
195 | 0 | return parseTDBeaconsJsonResponse(tdbJsonResponseString, |
196 | (Map<String, Object>) null, tdbRestRequest); | |
197 | } | |
198 | ||
199 | 13 | @SuppressWarnings("unchecked") |
200 | public static FTSRestResponse parseTDBeaconsJsonResponse( | |
201 | String tdbJsonResponseString, Map<String, Object> jsonObj, | |
202 | FTSRestRequest tdbRestRequest) | |
203 | { | |
204 | 13 | FTSRestResponse searchResult = new FTSRestResponse(); |
205 | 13 | List<FTSData> result = null; |
206 | ||
207 | 13 | try |
208 | { | |
209 | 13 | if (jsonObj == null) |
210 | { | |
211 | 13 | jsonObj = (Map<String, Object>) JSONUtils |
212 | .parse(tdbJsonResponseString); | |
213 | } | |
214 | ||
215 | 13 | Object uniprot_entry = jsonObj.get("uniprot_entry"); |
216 | // TODO: decide if anything from uniprot_entry needs to be reported via | |
217 | // the FTSRestResponse object | |
218 | // Arnaud added seqLength = (Long) ((Map<String, Object>) | |
219 | // jsonObj.get("uniprot_entry")).get("sequence_length"); | |
220 | ||
221 | 13 | List<Object> structures = (List<Object>) jsonObj.get("structures"); |
222 | 13 | result = new ArrayList<>(); |
223 | ||
224 | 13 | int numFound = 0; |
225 | 5106 | for (Iterator<Object> strucIter = structures.iterator(); strucIter |
226 | .hasNext();) | |
227 | { | |
228 | 5093 | Map<String, Object> structure = (Map<String, Object>) strucIter |
229 | .next(); | |
230 | 5093 | result.add(getFTSData(structure, tdbRestRequest)); |
231 | 5093 | numFound++; |
232 | } | |
233 | ||
234 | 13 | searchResult.setNumberOfItemsFound(numFound); |
235 | 13 | searchResult.setSearchSummary(result); |
236 | ||
237 | } catch (ParseException e) | |
238 | { | |
239 | 0 | e.printStackTrace(); |
240 | } | |
241 | 13 | return searchResult; |
242 | } | |
243 | ||
244 | 5093 | private static FTSData getFTSData( |
245 | Map<String, Object> tdbJsonStructureSummary, | |
246 | FTSRestRequest tdbRequest) | |
247 | { | |
248 | 5093 | String primaryKey = null; |
249 | 5093 | Object[] summaryRowData; |
250 | ||
251 | 5093 | SequenceI associatedSequence; |
252 | ||
253 | 5093 | Collection<FTSDataColumnI> displayFields = tdbRequest.getWantedFields(); |
254 | 5093 | SequenceI associatedSeq = tdbRequest.getAssociatedSequence(); |
255 | 5093 | int colCounter = 0; |
256 | 5093 | summaryRowData = new Object[(associatedSeq != null) |
257 | ? displayFields.size() + 1 | |
258 | : displayFields.size()]; | |
259 | 5093 | if (associatedSeq != null) |
260 | { | |
261 | 5030 | associatedSequence = associatedSeq; |
262 | 5030 | summaryRowData[0] = associatedSequence; |
263 | 5030 | colCounter = 1; |
264 | } | |
265 | 5093 | Map<String, Object> tdbJsonStructure = (Map<String, Object>) tdbJsonStructureSummary |
266 | .get("summary"); | |
267 | 5093 | for (FTSDataColumnI field : displayFields) |
268 | { | |
269 | 75702 | String fieldData = (tdbJsonStructure.get(field.getCode()) == null) |
270 | ? " " | |
271 | : tdbJsonStructure.get(field.getCode()).toString(); | |
272 | // jalview.bin.Console.outPrintln("Field : " + field + " Data : " + | |
273 | // fieldData); | |
274 | 75702 | if (field.isPrimaryKeyColumn()) |
275 | { | |
276 | 5093 | primaryKey = fieldData; |
277 | 5093 | summaryRowData[colCounter++] = primaryKey; |
278 | } | |
279 | 70609 | else if (fieldData == null || fieldData.trim().isEmpty()) |
280 | { | |
281 | 20088 | summaryRowData[colCounter++] = null; |
282 | } | |
283 | else | |
284 | { | |
285 | 50521 | try |
286 | { | |
287 | 50521 | summaryRowData[colCounter++] = (field.getDataType() |
288 | .getDataTypeClass() == Integer.class) | |
289 | ? Integer.valueOf(fieldData) | |
290 | 40461 | : (field.getDataType() |
291 | .getDataTypeClass() == Double.class) | |
292 | ? Double.valueOf(fieldData) | |
293 | : fieldData; | |
294 | } catch (Exception e) | |
295 | { | |
296 | // e.printStackTrace(); | |
297 | 0 | jalview.bin.Console |
298 | .outPrintln("offending value:" + fieldData + fieldData); | |
299 | } | |
300 | } | |
301 | } | |
302 | 5093 | final String primaryKey1 = primaryKey; |
303 | 5093 | final Object[] summaryRowData1 = summaryRowData; |
304 | ||
305 | 5093 | return new TDB_FTSData(primaryKey, tdbJsonStructure, summaryRowData1); |
306 | } | |
307 | ||
308 | // private static FTSData getFTSData(Map<String, Object> doc, | |
309 | // FTSRestRequest tdbRestRequest) | |
310 | // { | |
311 | // String primaryKey = null; | |
312 | // | |
313 | // Object[] summaryRowData; | |
314 | // | |
315 | // Collection<FTSDataColumnI> displayFields = | |
316 | // tdbRestRequest.getWantedFields(); | |
317 | // int colCounter = 0; | |
318 | // summaryRowData = new Object[displayFields.size() + 1]; | |
319 | // | |
320 | // return null; | |
321 | // } | |
322 | ||
323 | 0 | private String parseJsonExceptionString(String jsonErrorString) |
324 | { | |
325 | // TODO Auto-generated method stub | |
326 | 0 | return null; |
327 | } | |
328 | ||
329 | 5 | @Override |
330 | public String getColumnDataConfigFileName() | |
331 | { | |
332 | 5 | return "/fts/tdbeacons_data_columns.txt"; |
333 | } | |
334 | ||
335 | 166 | public static FTSRestClientI getInstance() |
336 | { | |
337 | 166 | if (instance == null) |
338 | { | |
339 | 5 | instance = new TDBeaconsFTSRestClient(); |
340 | } | |
341 | 166 | return instance; |
342 | } | |
343 | ||
344 | private Collection<FTSDataColumnI> allDefaultDisplayedStructureDataColumns; | |
345 | ||
346 | 70 | @Override |
347 | public Collection<FTSDataColumnI> getAllDefaultDisplayedStructureDataColumns() | |
348 | { | |
349 | 70 | if (allDefaultDisplayedStructureDataColumns == null |
350 | || allDefaultDisplayedStructureDataColumns.isEmpty()) | |
351 | { | |
352 | 5 | allDefaultDisplayedStructureDataColumns = new ArrayList<>(); |
353 | 5 | allDefaultDisplayedStructureDataColumns |
354 | .addAll(super.getAllDefaultDisplayedFTSDataColumns()); | |
355 | } | |
356 | 70 | return allDefaultDisplayedStructureDataColumns; |
357 | } | |
358 | ||
359 | 71 | @Override |
360 | public String[] getPreferencesColumnsFor(PreferenceSource source) | |
361 | { | |
362 | 71 | String[] columnNames = null; |
363 | 71 | switch (source) |
364 | { | |
365 | 1 | case SEARCH_SUMMARY: |
366 | 1 | columnNames = new String[] { "", "Display", "Group" }; |
367 | 1 | break; |
368 | 70 | case STRUCTURE_CHOOSER: |
369 | 70 | columnNames = new String[] { "", "Display", "Group" }; |
370 | 70 | break; |
371 | 0 | case PREFERENCES: |
372 | 0 | columnNames = new String[] { "3DB Beacons Field", |
373 | "Show in search summary", "Show in structure summary" }; | |
374 | 0 | break; |
375 | 0 | default: |
376 | 0 | break; |
377 | } | |
378 | 71 | return columnNames; |
379 | } | |
380 | } |