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