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