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