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