X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Ffts%2Fservice%2Fpdb%2FPDBFTSRestClient.java;h=796bc0ef61ccd674213d2fd2b7553a395acf34f6;hb=03bc8848382795bda548083f0bc3202dfe6a9b8b;hp=8e634632a85cfd83555f4ef86d55c930b5f7a2ec;hpb=24fb77e77301499aa9e4e12d40d2ab42e06f56ca;p=jalview.git diff --git a/src/jalview/fts/service/pdb/PDBFTSRestClient.java b/src/jalview/fts/service/pdb/PDBFTSRestClient.java index 8e63463..796bc0e 100644 --- a/src/jalview/fts/service/pdb/PDBFTSRestClient.java +++ b/src/jalview/fts/service/pdb/PDBFTSRestClient.java @@ -20,46 +20,54 @@ */ package jalview.fts.service.pdb; -import jalview.datamodel.SequenceI; -import jalview.fts.api.FTSData; -import jalview.fts.api.FTSDataColumnI; -import jalview.fts.api.FTSRestClientI; -import jalview.fts.core.FTSRestClient; -import jalview.fts.core.FTSRestRequest; -import jalview.fts.core.FTSRestResponse; -import jalview.util.MessageManager; - +import java.io.File; +import java.io.FileInputStream; +import java.io.FileReader; +import java.net.URI; +import java.nio.CharBuffer; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Objects; 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 jalview.datamodel.SequenceI; +import jalview.fts.api.FTSData; +import jalview.fts.api.FTSDataColumnI; +import jalview.fts.api.FTSRestClientI; +import jalview.fts.api.StructureFTSRestClientI; +import jalview.fts.core.FTSDataColumnPreferences; +import jalview.fts.core.FTSDataColumnPreferences.PreferenceSource; +import jalview.fts.core.FTSRestClient; +import jalview.fts.core.FTSRestRequest; +import jalview.fts.core.FTSRestResponse; +import jalview.fts.service.alphafold.AlphafoldRestClient; +import jalview.util.JSONUtils; +import jalview.util.MessageManager; +import jalview.util.Platform; + /** * A rest client for querying the Search endpoint of the PDB API * * @author tcnofoegbu - * */ public class PDBFTSRestClient extends FTSRestClient + implements StructureFTSRestClientI { private static FTSRestClientI instance = null; - public static final String PDB_SEARCH_ENDPOINT = "http://www.ebi.ac.uk/pdbe/search/pdb/select?"; + public static final String PDB_SEARCH_ENDPOINT = "https://www.ebi.ac.uk/pdbe/search/pdb/select?"; protected PDBFTSRestClient() { @@ -73,19 +81,19 @@ public class PDBFTSRestClient extends FTSRestClient * @return the pdbResponse object for the given request * @throws Exception */ + @SuppressWarnings({ "unused", "unchecked" }) @Override public FTSRestResponse executeRequest(FTSRestRequest pdbRestRequest) throws Exception { try { - ClientConfig clientConfig = new DefaultClientConfig(); - Client client = Client.create(clientConfig); - - String wantedFields = getDataColumnsFieldsAsCommaDelimitedString(pdbRestRequest - .getWantedFields()); - int responseSize = (pdbRestRequest.getResponseSize() == 0) ? getDefaultResponsePageSize() + String wantedFields = getDataColumnsFieldsAsCommaDelimitedString( + pdbRestRequest.getWantedFields()); + int responseSize = (pdbRestRequest.getResponseSize() == 0) + ? getDefaultResponsePageSize() : pdbRestRequest.getResponseSize(); + int offSet = pdbRestRequest.getOffSet(); String sortParam = null; if (pdbRestRequest.getFieldToSortBy() == null || pdbRestRequest.getFieldToSortBy().trim().isEmpty()) @@ -107,11 +115,11 @@ public class PDBFTSRestClient extends FTSRestClient } } - String facetPivot = (pdbRestRequest.getFacetPivot() == null || pdbRestRequest - .getFacetPivot().isEmpty()) ? "" : pdbRestRequest - .getFacetPivot(); - String facetPivotMinCount = String.valueOf(pdbRestRequest - .getFacetPivotMinCount()); + String facetPivot = (pdbRestRequest.getFacetPivot() == null + || pdbRestRequest.getFacetPivot().isEmpty()) ? "" + : pdbRestRequest.getFacetPivot(); + String facetPivotMinCount = String + .valueOf(pdbRestRequest.getFacetPivotMinCount()); String query = pdbRestRequest.getFieldToSearchBy() + pdbRestRequest.getSearchTerm() @@ -121,13 +129,37 @@ public class PDBFTSRestClient extends FTSRestClient : " AND status:REL"); // Build request parameters for the REST Request - WebResource webResource = null; + + // BH 2018 the trick here is to coerce the classes in Javascript to be + // different from the ones in Java yet still allow this to be correct for + // Java + Client client; + Class clientResponseClass; + if (Platform.isJS()) + { + // JavaScript only -- coerce types to Java types for Java + client = (Client) (Object) new jalview.javascript.web.Client(); + clientResponseClass = (Class) (Object) jalview.javascript.web.ClientResponse.class; + } + else + /** + * Java only + * + * @j2sIgnore + */ + { + client = Client.create(new DefaultClientConfig()); + clientResponseClass = ClientResponse.class; + } + + WebResource webResource; if (pdbRestRequest.isFacet()) { webResource = client.resource(PDB_SEARCH_ENDPOINT) .queryParam("wt", "json").queryParam("fl", wantedFields) .queryParam("rows", String.valueOf(responseSize)) .queryParam("q", query) + .queryParam("start", String.valueOf(offSet)) .queryParam("sort", sortParam).queryParam("facet", "true") .queryParam("facet.pivot", facetPivot) .queryParam("facet.pivot.mincount", facetPivotMinCount); @@ -137,57 +169,92 @@ public class PDBFTSRestClient extends FTSRestClient webResource = client.resource(PDB_SEARCH_ENDPOINT) .queryParam("wt", "json").queryParam("fl", wantedFields) .queryParam("rows", String.valueOf(responseSize)) - .queryParam("q", query) - .queryParam("sort", sortParam); + .queryParam("start", String.valueOf(offSet)) + .queryParam("q", query).queryParam("sort", sortParam); } - // Execute the REST request - ClientResponse clientResponse = webResource.accept( - MediaType.APPLICATION_JSON).get(ClientResponse.class); - // Get the JSON string from the response object - String responseString = clientResponse.getEntity(String.class); - // System.out.println("query >>>>>>> " + pdbRestRequest.toString()); + URI uri = webResource.getURI(); - // Check the response status and report exception if one occurs - if (clientResponse.getStatus() != 200) + System.out.println(uri); + ClientResponse clientResponse = null; + int responseStatus = -1; + // Get the JSON string from the response object or directly from the + // client (JavaScript) + Map jsonObj = null; + String responseString = null; + + System.out.println("query >>>>>>> " + pdbRestRequest.toString()); + + if (!isMocked()) { - String errorMessage = ""; - if (clientResponse.getStatus() == 400) + // Execute the REST request + clientResponse = webResource.accept(MediaType.APPLICATION_JSON) + .get(clientResponseClass); + responseStatus = clientResponse.getStatus(); + } + else + { + // mock response + if (mockQueries.containsKey(uri.toString())) { - errorMessage = parseJsonExceptionString(responseString); - throw new Exception(errorMessage); + responseStatus = 200; } else { - errorMessage = getMessageByHTTPStatusCode(clientResponse - .getStatus()); - throw new Exception(errorMessage); + // FIXME - may cause unexpected exceptions for callers when mocked + responseStatus = 400; } } - // Make redundant objects eligible for garbage collection to conserve - // memory - clientResponse = null; - client = null; + // Check the response status and report exception if one occurs + switch (responseStatus) + { + case 200: + + if (isMocked()) + { + responseString = mockQueries.get(uri.toString()); + } + else + { + if (Platform.isJS()) + { + jsonObj = clientResponse.getEntity(Map.class); + } + else + { + responseString = clientResponse.getEntity(String.class); + } + } + break; + case 400: + throw new Exception(isMocked() ? "400 response (Mocked)" + : parseJsonExceptionString(responseString)); + default: + throw new Exception( + getMessageByHTTPStatusCode(responseStatus, "PDB")); + } // Process the response and return the result to the caller. - return parsePDBJsonResponse(responseString, pdbRestRequest); + return parsePDBJsonResponse(responseString, jsonObj, pdbRestRequest); } catch (Exception e) { + if (e.getMessage() == null) + { + throw (e); + } String exceptionMsg = e.getMessage(); if (exceptionMsg.contains("SocketException")) { // No internet connection - throw new Exception( - MessageManager - .getString("exception.unable_to_detect_internet_connection")); + throw new Exception(MessageManager.getString( + "exception.unable_to_detect_internet_connection")); } else if (exceptionMsg.contains("UnknownHostException")) { // The server 'www.ebi.ac.uk' is unreachable - throw new Exception( - MessageManager - .getString("exception.pdb_server_unreachable")); + throw new Exception(MessageManager.formatMessage( + "exception.fts_server_unreachable", "PDB Solr")); } else { @@ -196,36 +263,6 @@ public class PDBFTSRestClient extends FTSRestClient } } - public String getMessageByHTTPStatusCode(int code) - { - String message = ""; - switch (code) - { - case 410: - message = MessageManager - .getString("exception.pdb_rest_service_no_longer_available"); - break; - case 403: - case 404: - message = MessageManager.getString("exception.resource_not_be_found"); - break; - case 408: - case 409: - case 500: - case 501: - case 502: - case 503: - case 504: - case 505: - message = MessageManager.getString("exception.pdb_server_error"); - break; - - default: - break; - } - return message; - } - /** * Process error response from PDB server if/when one occurs. * @@ -233,20 +270,43 @@ public class PDBFTSRestClient extends FTSRestClient * the JSON string containing error message from the server * @return the processed error message from the JSON string */ + @SuppressWarnings("unchecked") public static String parseJsonExceptionString(String jsonErrorResponse) { StringBuilder errorMessage = new StringBuilder( "\n============= PDB Rest Client RunTime error =============\n"); + // { + // "responseHeader":{ + // "status":0, + // "QTime":0, + // "params":{ + // "q":"(text:q93xj9_soltu) AND molecule_sequence:['' TO *] AND status:REL", + // "fl":"pdb_id,title,experimental_method,resolution", + // "start":"0", + // "sort":"overall_quality desc", + // "rows":"500", + // "wt":"json"}}, + // "response":{"numFound":1,"start":0,"docs":[ + // { + // "experimental_method":["X-ray diffraction"], + // "pdb_id":"4zhp", + // "resolution":2.46, + // "title":"The crystal structure of Potato ferredoxin I with 2Fe-2S + // cluster"}] + // }} + // try { - JSONParser jsonParser = new JSONParser(); - JSONObject jsonObj = (JSONObject) jsonParser.parse(jsonErrorResponse); - JSONObject errorResponse = (JSONObject) jsonObj.get("error"); + Map jsonObj = (Map) JSONUtils + .parse(jsonErrorResponse); + Map errorResponse = (Map) jsonObj + .get("error"); - JSONObject responseHeader = (JSONObject) jsonObj + Map responseHeader = (Map) jsonObj .get("responseHeader"); - JSONObject paramsObj = (JSONObject) responseHeader.get("params"); + Map paramsObj = (Map) responseHeader + .get("params"); String status = responseHeader.get("status").toString(); String message = errorResponse.get("msg").toString(); String query = paramsObj.get("q").toString(); @@ -276,37 +336,51 @@ public class PDBFTSRestClient extends FTSRestClient * JSON string * @return */ - @SuppressWarnings("unchecked") public static FTSRestResponse parsePDBJsonResponse( String pdbJsonResponseString, FTSRestRequest pdbRestRequest) { + return parsePDBJsonResponse(pdbJsonResponseString, + (Map) null, pdbRestRequest); + } + + @SuppressWarnings("unchecked") + public static FTSRestResponse parsePDBJsonResponse( + String pdbJsonResponseString, Map jsonObj, + FTSRestRequest pdbRestRequest) + { FTSRestResponse searchResult = new FTSRestResponse(); 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(); + if (jsonObj == null) + { + jsonObj = (Map) JSONUtils + .parse(pdbJsonResponseString); + } + Map pdbResponse = (Map) jsonObj + .get("response"); + String queryTime = ((Map) jsonObj + .get("responseHeader")).get("QTime").toString(); int numFound = Integer .valueOf(pdbResponse.get("numFound").toString()); + List docs = (List) pdbResponse.get("docs"); + + result = new ArrayList(); if (numFound > 0) { - result = new ArrayList(); - JSONArray docs = (JSONArray) pdbResponse.get("docs"); - for (Iterator docIter = docs.iterator(); docIter - .hasNext();) + + for (Iterator docIter = docs.iterator(); docIter.hasNext();) { - JSONObject doc = docIter.next(); + Map doc = (Map) docIter.next(); result.add(getFTSData(doc, pdbRestRequest)); } - searchResult.setNumberOfItemsFound(numFound); - searchResult.setResponseTime(queryTime); - searchResult.setSearchSummary(result); } + // this is the total number found by the query, + // rather than the set returned in SearchSummary + searchResult.setNumberOfItemsFound(numFound); + searchResult.setResponseTime(queryTime); + searchResult.setSearchSummary(result); + } catch (ParseException e) { e.printStackTrace(); @@ -314,7 +388,7 @@ public class PDBFTSRestClient extends FTSRestClient return searchResult; } - public static FTSData getFTSData(JSONObject pdbJsonDoc, + public static FTSData getFTSData(Map pdbJsonDoc, FTSRestRequest request) { @@ -327,8 +401,9 @@ public class PDBFTSRestClient extends FTSRestClient Collection diplayFields = request.getWantedFields(); SequenceI associatedSeq = request.getAssociatedSequence(); int colCounter = 0; - summaryRowData = new Object[(associatedSeq != null) ? diplayFields - .size() + 1 : diplayFields.size()]; + summaryRowData = new Object[(associatedSeq != null) + ? diplayFields.size() + 1 + : diplayFields.size()]; if (associatedSeq != null) { associatedSequence = associatedSeq; @@ -338,8 +413,10 @@ public class PDBFTSRestClient extends FTSRestClient for (FTSDataColumnI field : diplayFields) { + // System.out.println("Field " + field); String fieldData = (pdbJsonDoc.get(field.getCode()) == null) ? "" : pdbJsonDoc.get(field.getCode()).toString(); + // System.out.println("Field Data : " + fieldData); if (field.isPrimaryKeyColumn()) { primaryKey = fieldData; @@ -353,15 +430,17 @@ public class PDBFTSRestClient extends FTSRestClient { try { - summaryRowData[colCounter++] = (field.getDataColumnClass() == Integer.class) ? Integer - .valueOf(fieldData) - : (field.getDataColumnClass() == Double.class) ? Double - .valueOf(fieldData) - : fieldData; + summaryRowData[colCounter++] = (field.getDataType() + .getDataTypeClass() == Integer.class) + ? Integer.valueOf(fieldData) + : (field.getDataType() + .getDataTypeClass() == Double.class) + ? Double.valueOf(fieldData) + : sanitiseData(fieldData); } catch (Exception e) { e.printStackTrace(); - System.out.println("offending value:" + fieldData); + System.out.println("offending value:" + fieldData); } } } @@ -407,16 +486,29 @@ public class PDBFTSRestClient extends FTSRestClient { return Objects.hash(primaryKey1, this.toString()); } + + @Override + public boolean equals(Object that) + { + return this.toString().equals(that.toString()); + } }; } + private static String sanitiseData(String data) + { + String cleanData = data.replaceAll("\\[\"", "").replaceAll("\\]\"", "") + .replaceAll("\\[", "").replaceAll("\\]", "") + .replaceAll("\",\"", ", ").replaceAll("\"", ""); + return cleanData; + } + @Override public String getColumnDataConfigFileName() { - return getResourceFile("/fts/pdb_data_columns.conf"); + return "/fts/pdb_data_columns.txt"; } - public static FTSRestClientI getInstance() { if (instance == null) @@ -425,4 +517,41 @@ public class PDBFTSRestClient extends FTSRestClient } return instance; } + + private Collection allDefaultDisplayedStructureDataColumns; + + @Override + public Collection getAllDefaultDisplayedStructureDataColumns() + { + if (allDefaultDisplayedStructureDataColumns == null + || allDefaultDisplayedStructureDataColumns.isEmpty()) + { + allDefaultDisplayedStructureDataColumns = new ArrayList<>(); + allDefaultDisplayedStructureDataColumns + .addAll(super.getAllDefaultDisplayedFTSDataColumns()); + } + return allDefaultDisplayedStructureDataColumns; + } + + @Override + public String[] getPreferencesColumnsFor(PreferenceSource source) + { + String[] columnNames = null; + switch (source) + { + case SEARCH_SUMMARY: + columnNames = new String[] { "", "Display", "Group" }; + break; + case STRUCTURE_CHOOSER: + columnNames = new String[] { "", "Display", "Group" }; + break; + case PREFERENCES: + columnNames = new String[] { "PDB Field", "Show in search summary", + "Show in structure summary" }; + break; + default: + break; + } + return columnNames; + } }