*/
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()
{
* @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())
}
}
- 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()
: " 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<ClientResponse> clientResponseClass;
+ if (Platform.isJS())
+ {
+ // JavaScript only -- coerce types to Java types for Java
+ client = (Client) (Object) new jalview.javascript.web.Client();
+ clientResponseClass = (Class<ClientResponse>) (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);
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)
+ jalview.bin.Console.outPrintln(uri);
+ ClientResponse clientResponse = null;
+ int responseStatus = -1;
+ // Get the JSON string from the response object or directly from the
+ // client (JavaScript)
+ Map<String, Object> jsonObj = null;
+ String responseString = null;
+
+ jalview.bin.Console
+ .outPrintln("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
{
}
}
- 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.
*
* 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<String, Object> jsonObj = (Map<String, Object>) JSONUtils
+ .parse(jsonErrorResponse);
+ Map<String, Object> errorResponse = (Map<String, Object>) jsonObj
+ .get("error");
- JSONObject responseHeader = (JSONObject) jsonObj
+ Map<String, Object> responseHeader = (Map<String, Object>) jsonObj
.get("responseHeader");
- JSONObject paramsObj = (JSONObject) responseHeader.get("params");
+ Map<String, Object> paramsObj = (Map<String, Object>) responseHeader
+ .get("params");
String status = responseHeader.get("status").toString();
String message = errorResponse.get("msg").toString();
String query = paramsObj.get("q").toString();
* JSON string
* @return
*/
- @SuppressWarnings("unchecked")
public static FTSRestResponse parsePDBJsonResponse(
String pdbJsonResponseString, FTSRestRequest pdbRestRequest)
{
+ return parsePDBJsonResponse(pdbJsonResponseString,
+ (Map<String, Object>) null, pdbRestRequest);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static FTSRestResponse parsePDBJsonResponse(
+ String pdbJsonResponseString, Map<String, Object> jsonObj,
+ FTSRestRequest pdbRestRequest)
+ {
FTSRestResponse searchResult = new FTSRestResponse();
List<FTSData> 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<String, Object>) JSONUtils
+ .parse(pdbJsonResponseString);
+ }
+ Map<String, Object> pdbResponse = (Map<String, Object>) jsonObj
+ .get("response");
+ String queryTime = ((Map<String, Object>) jsonObj
+ .get("responseHeader")).get("QTime").toString();
int numFound = Integer
.valueOf(pdbResponse.get("numFound").toString());
+ List<Object> docs = (List<Object>) pdbResponse.get("docs");
+
+ result = new ArrayList<FTSData>();
if (numFound > 0)
{
- result = new ArrayList<FTSData>();
- JSONArray docs = (JSONArray) pdbResponse.get("docs");
- for (Iterator<JSONObject> docIter = docs.iterator(); docIter
- .hasNext();)
+
+ for (Iterator<Object> docIter = docs.iterator(); docIter.hasNext();)
{
- JSONObject doc = docIter.next();
+ Map<String, Object> doc = (Map<String, Object>) 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();
return searchResult;
}
- public static FTSData getFTSData(JSONObject pdbJsonDoc,
+ public static FTSData getFTSData(Map<String, Object> pdbJsonDoc,
FTSRestRequest request)
{
Collection<FTSDataColumnI> 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;
for (FTSDataColumnI field : diplayFields)
{
+ // jalview.bin.Console.outPrintln("Field " + field);
String fieldData = (pdbJsonDoc.get(field.getCode()) == null) ? ""
: pdbJsonDoc.get(field.getCode()).toString();
+ // jalview.bin.Console.outPrintln("Field Data : " + fieldData);
if (field.isPrimaryKeyColumn())
{
primaryKey = fieldData;
{
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);
+ jalview.bin.Console.outPrintln("offending value:" + fieldData);
}
}
}
{
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.txt");
+ return "/fts/pdb_data_columns.txt";
}
-
public static FTSRestClientI getInstance()
{
if (instance == null)
}
return instance;
}
+
+ private Collection<FTSDataColumnI> allDefaultDisplayedStructureDataColumns;
+
+ @Override
+ public Collection<FTSDataColumnI> 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;
+ }
}