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