JAL-1563 JAL-2091 Added generic pagination for FTS Service, pagination for PDB FTS...
[jalview.git] / src / jalview / fts / service / uniprot / UniProtFTSRestClient.java
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
22 package jalview.fts.service.uniprot;
23
24 import jalview.fts.api.FTSData;
25 import jalview.fts.api.FTSDataColumnI;
26 import jalview.fts.api.FTSRestClientI;
27 import jalview.fts.core.FTSRestClient;
28 import jalview.fts.core.FTSRestRequest;
29 import jalview.fts.core.FTSRestResponse;
30 import jalview.util.MessageManager;
31
32 import java.util.ArrayList;
33 import java.util.Collection;
34 import java.util.List;
35 import java.util.Objects;
36
37 import javax.ws.rs.core.MediaType;
38
39 import com.sun.jersey.api.client.Client;
40 import com.sun.jersey.api.client.ClientResponse;
41 import com.sun.jersey.api.client.WebResource;
42 import com.sun.jersey.api.client.config.ClientConfig;
43 import com.sun.jersey.api.client.config.DefaultClientConfig;
44
45 public class UniProtFTSRestClient extends FTSRestClient
46 {
47   private static FTSRestClientI instance = null;
48
49   public static final String UNIPROT_SEARCH_ENDPOINT = "http://www.uniprot.org/uniprot/?";
50
51   @Override
52   public FTSRestResponse executeRequest(FTSRestRequest uniportRestRequest)
53           throws Exception
54   {
55     try
56     {
57       ClientConfig clientConfig = new DefaultClientConfig();
58       Client client = Client.create(clientConfig);
59
60       String wantedFields = getDataColumnsFieldsAsCommaDelimitedString(uniportRestRequest
61               .getWantedFields());
62       int responseSize = (uniportRestRequest.getResponseSize() == 0) ? getDefaultResponsePageSize()
63               : uniportRestRequest.getResponseSize();
64
65       int offSet = uniportRestRequest.getOffSet();
66
67       String query = uniportRestRequest.getFieldToSearchBy()
68               .equalsIgnoreCase("Search All") ? uniportRestRequest
69               .getSearchTerm() : uniportRestRequest.getFieldToSearchBy()
70               + ":" + uniportRestRequest.getSearchTerm();
71
72       // + (uniportRestRequest.isAllowUnpublishedEntries() ? ""
73       // : " AND status:REL");
74       // System.out.println(">>>>> Query : " + query);
75       // System.out.println(">>>>> Columns : " + wantedFields);
76       // System.out.println(">>>>> Response size: " + responseSize
77       // + " offset : "
78       // + offSet);
79       WebResource webResource = null;
80       webResource = client.resource(UNIPROT_SEARCH_ENDPOINT)
81               .queryParam("format", "tab")
82               .queryParam("columns", wantedFields)
83               .queryParam("limit", String.valueOf(responseSize))
84               .queryParam("offset", String.valueOf(offSet))
85               .queryParam("sort", "score").queryParam("query", query);
86       // Execute the REST request
87       ClientResponse clientResponse = webResource.accept(
88               MediaType.TEXT_PLAIN).get(ClientResponse.class);
89       String uniProtTabDelimittedResponseString = clientResponse
90               .getEntity(String.class);
91       // Make redundant objects eligible for garbage collection to conserve
92       // memory
93       // System.out.println(">>>>> response : "
94       // + uniProtTabDelimittedResponseString);
95       if (clientResponse.getStatus() != 200)
96       {
97         String errorMessage = getMessageByHTTPStatusCode(
98                 clientResponse.getStatus(), "Uniprot");
99         throw new Exception(errorMessage);
100
101       }
102       clientResponse = null;
103       client = null;
104       return parseUniprotResponse(uniProtTabDelimittedResponseString,
105               uniportRestRequest);
106     } catch (Exception e)
107     {
108       String exceptionMsg = e.getMessage();
109       if (exceptionMsg.contains("SocketException"))
110       {
111         // No internet connection
112         throw new Exception(
113                 MessageManager
114                         .getString("exception.unable_to_detect_internet_connection"));
115       }
116       else if (exceptionMsg.contains("UnknownHostException"))
117       {
118         // The server 'http://www.uniprot.org' is unreachable
119         throw new Exception(MessageManager.formatMessage(
120                 "exception.fts_server_unreachable", "Uniprot"));
121       }
122       else
123       {
124         throw e;
125       }
126     }
127   }
128
129
130   public FTSRestResponse parseUniprotResponse(
131           String uniProtTabDelimittedResponseString,
132           FTSRestRequest uniprotRestRequest)
133   {
134     FTSRestResponse searchResult = new FTSRestResponse();
135     List<FTSData> result = null;
136     if (uniProtTabDelimittedResponseString == null
137             || uniProtTabDelimittedResponseString.trim().isEmpty())
138     {
139       searchResult.setNumberOfItemsFound(0);
140       return searchResult;
141     }
142     String[] foundDataRow = uniProtTabDelimittedResponseString.split("\n");
143     if (foundDataRow != null && foundDataRow.length > 0)
144     {
145       result = new ArrayList<FTSData>();
146       String titleRow = getDataColumnsFieldsAsTabDelimitedString(uniprotRestRequest
147               .getWantedFields());
148       // System.out.println(">>>>Title row : " + titleRow);
149       for (String dataRow : foundDataRow)
150       {
151         if (dataRow.equalsIgnoreCase(titleRow))
152         {
153           // System.out.println(">>>>>>>>>> matched!!!");
154           continue;
155         }
156         // System.out.println(dataRow);
157         result.add(getFTSData(dataRow, uniprotRestRequest));
158       }
159       searchResult.setNumberOfItemsFound(result.size());
160       searchResult.setSearchSummary(result);
161     }
162     return searchResult;
163   }
164
165   /**
166    * Takes a collection of FTSDataColumnI and converts its 'code' values into a
167    * tab delimited string.
168    * 
169    * @param dataColumnFields
170    *          the collection of FTSDataColumnI to process
171    * @return the generated comma delimited string from the supplied
172    *         FTSDataColumnI collection
173    */
174   private String getDataColumnsFieldsAsTabDelimitedString(
175           Collection<FTSDataColumnI> dataColumnFields)
176   {
177     String result = "";
178     if (dataColumnFields != null && !dataColumnFields.isEmpty())
179     {
180       StringBuilder returnedFields = new StringBuilder();
181       for (FTSDataColumnI field : dataColumnFields)
182       {
183         if (field.getName().equalsIgnoreCase("Uniprot Id"))
184         {
185           returnedFields.append("\t").append("Entry");
186         }
187         else
188         {
189           returnedFields.append("\t").append(field.getName());
190         }
191       }
192       returnedFields.deleteCharAt(0);
193       result = returnedFields.toString();
194     }
195     return result;
196   }
197
198   public static FTSData getFTSData(String tabDelimittedDataStr,
199           FTSRestRequest request)
200   {
201     String primaryKey = null;
202
203     Object[] summaryRowData;
204
205     Collection<FTSDataColumnI> diplayFields = request.getWantedFields();
206     int colCounter = 0;
207     summaryRowData = new Object[diplayFields.size()];
208     String[] columns = tabDelimittedDataStr.split("\t");
209     for (FTSDataColumnI field : diplayFields)
210     {
211       try
212       {
213         String fieldData = columns[colCounter];
214         if (field.isPrimaryKeyColumn())
215         {
216           primaryKey = fieldData;
217           summaryRowData[colCounter++] = primaryKey;
218         }
219         else if (fieldData == null || fieldData.isEmpty())
220         {
221           summaryRowData[colCounter++] = null;
222         }
223         else
224         {
225           try
226           {
227             summaryRowData[colCounter++] = (field.getDataColumnClass() == Integer.class) ? Integer
228                     .valueOf(fieldData)
229                     : (field.getDataColumnClass() == Double.class) ? Double
230                             .valueOf(fieldData) : fieldData;
231           } catch (Exception e)
232           {
233             e.printStackTrace();
234               System.out.println("offending value:" + fieldData);
235           }
236         }
237       } catch (Exception e)
238       {
239         // e.printStackTrace();
240       }
241     }
242
243     final String primaryKey1 = primaryKey;
244
245     final Object[] summaryRowData1 = summaryRowData;
246     return new FTSData()
247     {
248       @Override
249       public Object[] getSummaryData()
250       {
251         return summaryRowData1;
252       }
253
254       @Override
255       public Object getPrimaryKey()
256       {
257         return primaryKey1;
258       }
259
260       /**
261        * Returns a string representation of this object;
262        */
263       @Override
264       public String toString()
265       {
266         StringBuilder summaryFieldValues = new StringBuilder();
267         for (Object summaryField : summaryRowData1)
268         {
269           summaryFieldValues.append(
270                   summaryField == null ? " " : summaryField.toString())
271                   .append("\t");
272         }
273         return summaryFieldValues.toString();
274       }
275
276       /**
277        * Returns hash code value for this object
278        */
279       @Override
280       public int hashCode()
281       {
282         return Objects.hash(primaryKey1, this.toString());
283       }
284
285       @Override
286       public boolean equals(Object that)
287       {
288         return this.toString().equals(that.toString());
289       }
290     };
291   }
292
293
294   public static FTSRestClientI getInstance()
295   {
296     if (instance == null)
297     {
298       instance = new UniProtFTSRestClient();
299     }
300     return instance;
301   }
302
303   @Override
304   public String getColumnDataConfigFileName()
305   {
306     return "/fts/uniprot_data_columns.txt";
307   }
308
309 }