JAL-1667 updated test and internationalization messages
[jalview.git] / src / jalview / ws / dbsources / PDBRestClient.java
1 package jalview.ws.dbsources;
2
3 import jalview.ws.uimodel.PDBRestRequest;
4 import jalview.ws.uimodel.PDBRestResponse;
5 import jalview.ws.uimodel.PDBRestResponse.PDBResponseSummary;
6
7 import java.util.ArrayList;
8 import java.util.Iterator;
9 import java.util.List;
10
11 import javax.ws.rs.core.MediaType;
12
13 import org.json.simple.JSONArray;
14 import org.json.simple.JSONObject;
15 import org.json.simple.parser.JSONParser;
16 import org.json.simple.parser.ParseException;
17
18 import com.sun.jersey.api.client.Client;
19 import com.sun.jersey.api.client.ClientResponse;
20 import com.sun.jersey.api.client.WebResource;
21 import com.sun.jersey.api.client.config.ClientConfig;
22 import com.sun.jersey.api.client.config.DefaultClientConfig;
23 import com.sun.jersey.api.json.JSONConfiguration;
24
25 public class PDBRestClient
26 {
27   private String pdbSearchEndpoint = "http://wwwdev.ebi.ac.uk/pdbe/search/pdb/select?";
28
29   /**
30    * Takes a PDBRestRequest object and returns a response upon execution
31    * 
32    * @param pdbRestRequest
33    *          the pdbRequest to be sent
34    * @return the pdbResponse object for the given pdbRequest
35    */
36   public PDBRestResponse executeRequest(PDBRestRequest pdbRestRequest)
37   {
38     ClientConfig clientConfig = new DefaultClientConfig();
39     clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING,
40             Boolean.TRUE);
41     Client client = Client.create(clientConfig);
42
43     String query = pdbRestRequest.getFieldToSearchBy()
44             + pdbRestRequest.getSearchTerm()
45             + ((pdbRestRequest.isAllowEmptySeq()) ? ""
46                     : " AND molecule_sequence:['' TO *]");
47
48     String wantedFields = getPDBDocFieldsAsCommaDelimitedString(pdbRestRequest
49             .getWantedFields());
50
51     String responseSize = (pdbRestRequest.getResponseSize() == 0) ? "200"
52             : String.valueOf(pdbRestRequest.getResponseSize());
53     String sortParam = (pdbRestRequest.getFieldToSortBy() == null || pdbRestRequest
54             .getFieldToSortBy().trim().isEmpty()) ? ""
55  : (pdbRestRequest
56             .getFieldToSortBy() + (pdbRestRequest.isAscending() ? " asc"
57             : " desc"));
58
59     WebResource webResource = client.resource(pdbSearchEndpoint)
60             .queryParam("wt", "json").queryParam("fl", wantedFields)
61             .queryParam("rows", responseSize)
62             .queryParam("q", query)
63             .queryParam("sort", sortParam);
64     ClientResponse clientResponse = webResource.accept(
65             MediaType.APPLICATION_JSON).get(ClientResponse.class);
66
67     String responseString = clientResponse.getEntity(String.class);
68     if (clientResponse.getStatus() != 200)
69     {
70       if (clientResponse.getStatus() == 400)
71       {
72         throw new RuntimeException(parseJsonExceptionString(responseString));
73       }
74       else
75       {
76       throw new RuntimeException("Failed : HTTP error code : "
77               + clientResponse.getStatus());
78       }
79     }
80     clientResponse = null;
81     client = null;
82     return parsePDBJsonResponse(responseString, pdbRestRequest);
83   }
84
85   /**
86    * Process error response from PDB server if/when one occurs.
87    * 
88    * @param jsonResponse
89    *          the json string containing error message from the server
90    * @return the processed error message from the json string
91    */
92   public static String parseJsonExceptionString(String jsonErrorResponse)
93   {
94     String errorMessage = "RunTime error";
95     try
96     {
97       JSONParser jsonParser = new JSONParser();
98       JSONObject jsonObj = (JSONObject) jsonParser.parse(jsonErrorResponse);
99       JSONObject errorResponse = (JSONObject) jsonObj.get("error");
100       errorMessage = errorResponse.get("msg").toString();
101
102       JSONObject responseHeader = (JSONObject) jsonObj
103               .get("responseHeader");
104       errorMessage += responseHeader.get("params").toString();
105     } catch (ParseException e)
106     {
107       e.printStackTrace();
108     }
109     return errorMessage;
110   }
111
112   /**
113    * Parses json response string from PDB REST API to a PDBRestResponse
114    * instance. The parsed response is dynamic and based upon some of the request
115    * parameters.
116    * 
117    * @param pdbJsonResponseString
118    *          the json string to be parsed
119    * @param pdbRestRequest
120    *          the request object which contains parameters used to process the
121    *          json string
122    * @return
123    */
124   @SuppressWarnings("unchecked")
125   public static PDBRestResponse parsePDBJsonResponse(
126           String pdbJsonResponseString,
127           PDBRestRequest pdbRestRequest)
128   {
129     PDBRestResponse searchResult = new PDBRestResponse();
130     List<PDBResponseSummary> result = null;
131     try
132     {
133       JSONParser jsonParser = new JSONParser();
134       JSONObject jsonObj = (JSONObject) jsonParser
135               .parse(pdbJsonResponseString);
136
137       JSONObject pdbResponse = (JSONObject) jsonObj.get("response");
138       String queryTime = ((JSONObject) jsonObj.get("responseHeader")).get(
139               "QTime").toString();
140       int numFound = Integer
141               .valueOf(pdbResponse.get("numFound").toString());
142       if (numFound > 0)
143       {
144         result = new ArrayList<PDBResponseSummary>();
145         JSONArray docs = (JSONArray) pdbResponse.get("docs");
146         for (Iterator<JSONObject> docIter = docs.iterator(); docIter
147                 .hasNext();)
148         {
149           JSONObject doc = docIter.next();
150           // if (doc.get("molecule_sequence") != null)
151           // {
152           result.add(searchResult.new PDBResponseSummary(doc, pdbRestRequest));
153           // }
154         }
155         searchResult.setNumberOfItemsFound(numFound);
156         searchResult.setResponseTime(queryTime);
157         searchResult.setSearchSummary(result);
158       }
159     } catch (ParseException e)
160     {
161       e.printStackTrace();
162     }
163
164     return searchResult;
165   }
166
167   /**
168    * Takes a collection of PDBDocField and converts it into a comma delimited
169    * string.
170    * 
171    * @param pdbDocfields
172    * @return
173    */
174   public static String getPDBDocFieldsAsCommaDelimitedString(
175           List<PDBDocField> pdbDocfields)
176   {
177     String result = "";
178     if (pdbDocfields != null && !pdbDocfields.isEmpty())
179     {
180       StringBuilder returnedFields = new StringBuilder();
181       for (PDBDocField field : pdbDocfields)
182       {
183         returnedFields.append(",").append(field.getCode());
184       }
185       returnedFields.deleteCharAt(0); 
186       result = returnedFields.toString();
187     }
188     return result;
189   }
190
191
192   /**
193    * Represents the fields retrievable from a PDB Document response
194    *
195    */
196   public enum PDBDocField
197   {
198     PDB_ID("PDB Id", "pdb_id"), TITLE("Title", "title"), MOLECULE_NAME(
199             "Molecule", "molecule_name"), MOLECULE_TYPE("Molecule Type",
200             "molecule_type"), MOLECULE_SEQUENCE("Sequence",
201             "molecule_sequence"), UNIPROT_FEATURES("Uniprot Features",
202             "uniprot_features"), PFAM_ACCESSION("PFAM Accession",
203             "pfam_accession"), INTERPRO_ACCESSION("InterPro Accession",
204             "interpro_accession"), UNIPROT_ACCESSION("UniProt Accession",
205             "uniprot_accession"), R_FACTOR("R Factor", "r_factor"), RESOLUTION(
206             "Resolution", "resolution"), DATA_QUALITY("Data Quality",
207             "data_quality"), OVERALL_QUALITY("Overall Quality",
208             "overall_quality"), POLYMER_COUNT("Polymer Count",
209             "number_of_polymers"), PROTEIN_CHAIN_COUNT(
210             "Protein Chain Count", "number_of_protein_chains"), BOUND_MOLECULE_COUNT(
211             "Bound Molecule Count", "number_of_bound_molecules"), POLYMER_RESIDUE_COUNT(
212             "Polymer Residue Count", "number_of_polymer_residues"), UNIPROT_COVERAGE(
213             "UniProt Coverage", "uniprot_coverage"), GENUS("GENUS", "genus"), GENE_NAME(
214             "Gene Name", "gene_name"), EXPERIMENTAL_METHOD(
215             "Experimental Method", "experimental_method"), ALL("ALL",
216             "text");
217
218     private String name;
219
220     private String code;
221
222     PDBDocField(String name, String code)
223     {
224       this.name = name;
225       this.code = code;
226     }
227
228     public String getName()
229     {
230       return name;
231     }
232
233     public String getCode()
234     {
235       return code;
236     }
237
238     public String toString()
239     {
240       return name;
241     }
242   }
243 }