JAL-1668 added filtering and sorting capabilites
[jalview.git] / src / jalview / ws / dbsources / PDBRestClient.java
1 package jalview.ws.dbsources;
2
3 import jalview.ws.uimodel.PDBSearchRequest;
4 import jalview.ws.uimodel.PDBSearchResponse;
5 import jalview.ws.uimodel.PDBSearchResponse.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   public static void main(String[] args)
30   {
31     PDBSearchRequest request = new PDBSearchRequest();
32     request.setAllowEmptySeq(false);
33     request.setResponseSize(100);
34     request.setFieldToSearchBy("pfam_name");
35     request.setSearchTerm("Lipoc*");
36     List<PDBDocField> wantedFields = new ArrayList<PDBDocField>();
37     wantedFields.add(PDBDocField.MOLECULE_TYPE);
38     wantedFields.add(PDBDocField.PDB_ID);
39     wantedFields.add(PDBDocField.GENUS);
40     wantedFields.add(PDBDocField.GENE_NAME);
41     wantedFields.add(PDBDocField.TITLE);
42     request.setWantedFields(wantedFields);
43     new PDBRestClient().executeRequest(request);
44   }
45
46   public PDBSearchResponse executeRequest(PDBSearchRequest request)
47   {
48     ClientConfig clientConfig = new DefaultClientConfig();
49     clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING,
50             Boolean.TRUE);
51     Client client = Client.create(clientConfig);
52
53     String query = request.getFieldToSearchBy()
54             + request.getSearchTerm()
55             + ((request.isAllowEmptySeq()) ? ""
56                     : " AND molecule_sequence:['' TO *]");
57
58     String wantedFields = getFieldsAsCommaDelimitedString(request
59             .getWantedFields());
60
61     String responseSize = (request.getResponseSize() == 0) ? "200" : String
62             .valueOf(request.getResponseSize());
63     String sortParam = (request.getFieldToSortBy() == null || request
64             .getFieldToSortBy().trim().isEmpty()) ? ""
65             : (request
66             .getFieldToSortBy() + (request.isAscending() ? " asc" : " desc"));
67
68     WebResource webResource = client.resource(pdbSearchEndpoint)
69             .queryParam("wt", "json").queryParam("fl", wantedFields)
70             .queryParam("rows", responseSize)
71             .queryParam("q", query)
72             .queryParam("sort", sortParam);
73     ClientResponse clientResponse = webResource.accept(
74             MediaType.APPLICATION_JSON).get(ClientResponse.class);
75
76     String responseString = clientResponse.getEntity(String.class);
77     if (clientResponse.getStatus() != 200)
78     {
79       if (clientResponse.getStatus() == 400)
80       {
81         throw new RuntimeException(parseException(responseString));
82       }
83       else
84       {
85       throw new RuntimeException("Failed : HTTP error code : "
86               + clientResponse.getStatus());
87       }
88     }
89     // System.out.println("--------------> " + responseString);
90     return parseResponse(responseString, request.getWantedFields(),
91             request.getAssociatedSequence());
92   }
93
94   private String parseException(String jsonResponse)
95   {
96     String errorMessage = "RunTime error";
97     try
98     {
99       JSONParser jsonParser = new JSONParser();
100       JSONObject jsonObj = (JSONObject) jsonParser.parse(jsonResponse);
101       JSONObject errorResponse = (JSONObject) jsonObj.get("error");
102       errorMessage = errorResponse.get("msg").toString();
103
104       JSONObject responseHeader = (JSONObject) jsonObj
105               .get("responseHeader");
106       errorMessage += responseHeader.get("params").toString();
107     } catch (ParseException e)
108     {
109       e.printStackTrace();
110     }
111     return errorMessage;
112   }
113
114   @SuppressWarnings("unchecked")
115   private PDBSearchResponse parseResponse(String jsonResponse,
116           List<PDBDocField> wantedFields, String associatedSequence)
117   {
118     PDBSearchResponse searchResult = new PDBSearchResponse();
119     List<PDBResponseSummary> result = null;
120     try
121     {
122       JSONParser jsonParser = new JSONParser();
123       JSONObject jsonObj = (JSONObject) jsonParser
124 .parse(jsonResponse);
125
126       JSONObject pdbResponse = (JSONObject) jsonObj.get("response");
127       String queryTime = ((JSONObject) jsonObj.get("responseHeader")).get(
128               "QTime").toString();
129       int numFound = Integer
130               .valueOf(pdbResponse.get("numFound").toString());
131       if (numFound > 0)
132       {
133         result = new ArrayList<PDBResponseSummary>();
134         JSONArray docs = (JSONArray) pdbResponse.get("docs");
135         for (Iterator<JSONObject> docIter = docs.iterator(); docIter
136                 .hasNext();)
137         {
138           JSONObject doc = docIter.next();
139           // if (doc.get("molecule_sequence") != null)
140           // {
141           result.add(searchResult.new PDBResponseSummary(doc, wantedFields,
142                   associatedSequence));
143           // }
144         }
145         searchResult.setItemsFound(numFound);
146         searchResult.setResponseTime(queryTime);
147         searchResult.setSearchSummary(result);
148       }
149     } catch (ParseException e)
150     {
151       e.printStackTrace();
152     }
153
154     return searchResult;
155   }
156
157   private String getFieldsAsCommaDelimitedString(List<PDBDocField> fields)
158   {
159     String result = "";
160     if (fields != null && !fields.isEmpty())
161     {
162       StringBuilder returnedFields = new StringBuilder();
163       for (PDBDocField field : fields)
164       {
165         returnedFields.append(",").append(field.getCode());
166       }
167       returnedFields.deleteCharAt(0);
168       result = returnedFields.toString();
169     }
170     return result;
171   }
172
173
174   public enum PDBDocField
175   {
176     PDB_ID("PDB Id", "pdb_id"), TITLE("Title", "title"), MOLECULE_NAME(
177             "Molecule", "molecule_name"), MOLECULE_TYPE("Molecule Type",
178             "molecule_type"), MOLECULE_SEQUENCE("Sequence",
179             "molecule_sequence"), UNIPROT_FEATURES("Uniprot Features",
180             "uniprot_features"), PFAM_ACCESSION("PFAM Accession",
181             "pfam_accession"), INTERPRO_ACCESSION("InterPro Accession",
182             "interpro_accession"), UNIPROT_ACCESSION("UniProt Accession",
183             "uniprot_accession"), R_FACTOR("R Factor", "r_factor"), RESOLUTION(
184             "Resolution", "resolution"), DATA_QUALITY("Data Quality",
185             "data_quality"), OVERALL_QUALITY("Overall Quality",
186             "overall_quality"), POLYMER_COUNT("Polymer Count",
187             "number_of_polymers"), PROTEIN_CHAIN_COUNT(
188             "Protein Chain Count", "number_of_protein_chains"), BOUND_MOLECULE_COUNT(
189             "Bound Molecule Count", "number_of_bound_molecules"), POLYMER_RESIDUE_COUNT(
190             "Polymer Residue Count", "number_of_polymer_residues"), UNIPROT_COVERAGE(
191             "UniProt Coverage", "uniprot_coverage"), GENUS("GENUS", "genus"), GENE_NAME(
192             "Gene Name", "gene_name"), ALL("ALL", "text");
193
194     private String name;
195
196     private String code;
197
198     PDBDocField(String name, String code)
199     {
200       this.name = name;
201       this.code = code;
202     }
203
204     public String getName()
205     {
206       return name;
207     }
208
209     public String getCode()
210     {
211       return code;
212     }
213
214     public String toString()
215     {
216       return name;
217     }
218   }
219 }