package jalview.ws.dbsources; import jalview.ws.uimodel.PDBRestRequest; import jalview.ws.uimodel.PDBRestResponse; import jalview.ws.uimodel.PDBRestResponse.PDBResponseSummary; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.ws.rs.core.MediaType; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.WebResource; import com.sun.jersey.api.client.config.ClientConfig; import com.sun.jersey.api.client.config.DefaultClientConfig; import com.sun.jersey.api.json.JSONConfiguration; public class PDBRestClient { private String pdbSearchEndpoint = "http://wwwdev.ebi.ac.uk/pdbe/search/pdb/select?"; /** * Takes a PDBRestRequest object and returns a response upon execution * * @param pdbRestRequest * the pdbRequest to be sent * @return the pdbResponse object for the given pdbRequest */ public PDBRestResponse executeRequest(PDBRestRequest pdbRestRequest) { ClientConfig clientConfig = new DefaultClientConfig(); clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); Client client = Client.create(clientConfig); String query = pdbRestRequest.getFieldToSearchBy() + pdbRestRequest.getSearchTerm() + ((pdbRestRequest.isAllowEmptySeq()) ? "" : " AND molecule_sequence:['' TO *]"); String wantedFields = getPDBDocFieldsAsCommaDelimitedString(pdbRestRequest .getWantedFields()); String responseSize = (pdbRestRequest.getResponseSize() == 0) ? "200" : String.valueOf(pdbRestRequest.getResponseSize()); String sortParam = (pdbRestRequest.getFieldToSortBy() == null || pdbRestRequest .getFieldToSortBy().trim().isEmpty()) ? "" : (pdbRestRequest .getFieldToSortBy() + (pdbRestRequest.isAscending() ? " asc" : " desc")); WebResource webResource = client.resource(pdbSearchEndpoint) .queryParam("wt", "json").queryParam("fl", wantedFields) .queryParam("rows", responseSize) .queryParam("q", query) .queryParam("sort", sortParam); ClientResponse clientResponse = webResource.accept( MediaType.APPLICATION_JSON).get(ClientResponse.class); String responseString = clientResponse.getEntity(String.class); if (clientResponse.getStatus() != 200) { if (clientResponse.getStatus() == 400) { throw new RuntimeException(parseJsonExceptionString(responseString)); } else { throw new RuntimeException("Failed : HTTP error code : " + clientResponse.getStatus()); } } clientResponse = null; client = null; return parsePDBJsonResponse(responseString, pdbRestRequest); } /** * Process error response from PDB server if/when one occurs. * * @param jsonResponse * the json string containing error message from the server * @return the processed error message from the json string */ public static String parseJsonExceptionString(String jsonErrorResponse) { String errorMessage = "RunTime error"; try { JSONParser jsonParser = new JSONParser(); JSONObject jsonObj = (JSONObject) jsonParser.parse(jsonErrorResponse); JSONObject errorResponse = (JSONObject) jsonObj.get("error"); errorMessage = errorResponse.get("msg").toString(); JSONObject responseHeader = (JSONObject) jsonObj .get("responseHeader"); errorMessage += responseHeader.get("params").toString(); } catch (ParseException e) { e.printStackTrace(); } return errorMessage; } /** * Parses json response string from PDB REST API to a PDBRestResponse * instance. The parsed response is dynamic and based upon some of the request * parameters. * * @param pdbJsonResponseString * the json string to be parsed * @param pdbRestRequest * the request object which contains parameters used to process the * json string * @return */ @SuppressWarnings("unchecked") public static PDBRestResponse parsePDBJsonResponse( String pdbJsonResponseString, PDBRestRequest pdbRestRequest) { PDBRestResponse searchResult = new PDBRestResponse(); List result = null; try { JSONParser jsonParser = new JSONParser(); JSONObject jsonObj = (JSONObject) jsonParser .parse(pdbJsonResponseString); JSONObject pdbResponse = (JSONObject) jsonObj.get("response"); String queryTime = ((JSONObject) jsonObj.get("responseHeader")).get( "QTime").toString(); int numFound = Integer .valueOf(pdbResponse.get("numFound").toString()); if (numFound > 0) { result = new ArrayList(); JSONArray docs = (JSONArray) pdbResponse.get("docs"); for (Iterator docIter = docs.iterator(); docIter .hasNext();) { JSONObject doc = docIter.next(); // if (doc.get("molecule_sequence") != null) // { result.add(searchResult.new PDBResponseSummary(doc, pdbRestRequest)); // } } searchResult.setNumberOfItemsFound(numFound); searchResult.setResponseTime(queryTime); searchResult.setSearchSummary(result); } } catch (ParseException e) { e.printStackTrace(); } return searchResult; } /** * Takes a collection of PDBDocField and converts it into a comma delimited * string. * * @param pdbDocfields * @return */ public static String getPDBDocFieldsAsCommaDelimitedString( List pdbDocfields) { String result = ""; if (pdbDocfields != null && !pdbDocfields.isEmpty()) { StringBuilder returnedFields = new StringBuilder(); for (PDBDocField field : pdbDocfields) { returnedFields.append(",").append(field.getCode()); } returnedFields.deleteCharAt(0); result = returnedFields.toString(); } return result; } /** * Represents the fields retrievable from a PDB Document response * */ public enum PDBDocField { PDB_ID("PDB Id", "pdb_id"), TITLE("Title", "title"), MOLECULE_NAME( "Molecule", "molecule_name"), MOLECULE_TYPE("Molecule Type", "molecule_type"), MOLECULE_SEQUENCE("Sequence", "molecule_sequence"), UNIPROT_FEATURES("Uniprot Features", "uniprot_features"), PFAM_ACCESSION("PFAM Accession", "pfam_accession"), INTERPRO_ACCESSION("InterPro Accession", "interpro_accession"), UNIPROT_ACCESSION("UniProt Accession", "uniprot_accession"), R_FACTOR("R Factor", "r_factor"), RESOLUTION( "Resolution", "resolution"), DATA_QUALITY("Data Quality", "data_quality"), OVERALL_QUALITY("Overall Quality", "overall_quality"), POLYMER_COUNT("Polymer Count", "number_of_polymers"), PROTEIN_CHAIN_COUNT( "Protein Chain Count", "number_of_protein_chains"), BOUND_MOLECULE_COUNT( "Bound Molecule Count", "number_of_bound_molecules"), POLYMER_RESIDUE_COUNT( "Polymer Residue Count", "number_of_polymer_residues"), UNIPROT_COVERAGE( "UniProt Coverage", "uniprot_coverage"), GENUS("GENUS", "genus"), GENE_NAME( "Gene Name", "gene_name"), EXPERIMENTAL_METHOD( "Experimental Method", "experimental_method"), ALL("ALL", "text"); private String name; private String code; PDBDocField(String name, String code) { this.name = name; this.code = code; } public String getName() { return name; } public String getCode() { return code; } public String toString() { return name; } } }