--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.fts.service.threedbeacons;
+
+import java.net.URI;
+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.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.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.FTSRestClient;
+import jalview.fts.core.FTSRestRequest;
+import jalview.fts.core.FTSRestResponse;
+import jalview.fts.core.FTSDataColumnPreferences.PreferenceSource;
+import jalview.fts.service.pdb.PDBFTSRestClient;
+import jalview.util.JSONUtils;
+import jalview.util.MessageManager;
+import jalview.util.Platform;
+
+public class TDBeaconsFTSRestClient extends FTSRestClient
+ implements StructureFTSRestClientI
+{
+ /**
+ * production server URI
+ */
+ private static String TDB_PROD_API = "https://www.ebi.ac.uk/pdbe/pdbe-kb/3dbeacons/api/uniprot/summary/";
+
+ /**
+ * dev server URI
+ */
+ private static String TDB_DEV_API = "https://wwwdev.ebi.ac.uk/pdbe/pdbe-kb/3dbeacons/api/uniprot/summary/";
+
+ private static String DEFAULT_THREEDBEACONS_DOMAIN = TDB_PROD_API;
+
+ public static FTSRestClientI instance = null;
+
+ protected TDBeaconsFTSRestClient()
+ {
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public FTSRestResponse executeRequest(FTSRestRequest tdbRestRequest)
+ throws Exception
+ {
+ try
+ {
+ String query = tdbRestRequest.getSearchTerm();
+ Client client;
+ Class<ClientResponse> clientResponseClass;
+ if (Platform.isJS())
+ {
+ // JavaScript only
+ 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;
+ webResource = client.resource(DEFAULT_THREEDBEACONS_DOMAIN + query);
+
+ URI uri = webResource.getURI();
+ System.out.println(uri.toString());
+
+ // Execute the REST request
+ ClientResponse clientResponse;
+ if (isMocked())
+ {
+ clientResponse = null;
+ }
+ else
+ {
+ clientResponse = webResource.accept(MediaType.APPLICATION_JSON)
+ .get(clientResponseClass);
+ }
+
+ // Get the JSON string from the response object or directly from the
+ // client (JavaScript)
+ Map<String, Object> jsonObj = null;
+ String responseString = null;
+
+ // Check the response status and report exception if one occurs
+ int responseStatus = isMocked()
+ ? (mockQueries.containsKey(query) ? 200 : 404)
+ : clientResponse.getStatus();
+ switch (responseStatus)
+ {
+ // if success
+ case 200:
+ if (Platform.isJS())
+ {
+ jsonObj = clientResponse.getEntity(Map.class);
+ }
+ else
+ {
+ responseString = isMocked() ? mockQueries.get(query)
+ : clientResponse.getEntity(String.class);
+ }
+ break;
+ case 400:
+ throw new Exception(parseJsonExceptionString(responseString));
+ case 404:
+ return emptyTDBeaconsJsonResponse();
+ default:
+ throw new Exception(
+ getMessageByHTTPStatusCode(responseStatus, "3DBeacons"));
+ }
+ // Process the response and return the result to the caller.
+ return parseTDBeaconsJsonResponse(responseString, jsonObj,
+ tdbRestRequest);
+ } catch (Exception e)
+ {
+ String exceptionMsg = e.getMessage();
+ if (exceptionMsg != null)
+ {
+ if (exceptionMsg.contains("SocketException"))
+ {
+ // No internet connection
+ throw new Exception(MessageManager.getString(
+ "exception.unable_to_detect_internet_connection"));
+ }
+ else if (exceptionMsg.contains("UnknownHostException"))
+ {
+ // The server is unreachable
+ throw new Exception(MessageManager.formatMessage(
+ "exception.fts_server_unreachable", "3DB Hub"));
+ }
+ }
+ throw e;
+
+ }
+
+ }
+
+ /**
+ * returns response for when the 3D-Beacons service doesn't have a record for
+ * the given query - in 2.11.2 this triggers a failover to the PDBe FTS
+ *
+ * @return null
+ */
+ private FTSRestResponse emptyTDBeaconsJsonResponse()
+ {
+ return null;
+ }
+
+ public String setSearchTerm(String term)
+ {
+ return term;
+ }
+
+ public static FTSRestResponse parseTDBeaconsJsonResponse(
+ String tdbJsonResponseString, FTSRestRequest tdbRestRequest)
+ {
+ return parseTDBeaconsJsonResponse(tdbJsonResponseString,
+ (Map<String, Object>) null, tdbRestRequest);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static FTSRestResponse parseTDBeaconsJsonResponse(
+ String tdbJsonResponseString, Map<String, Object> jsonObj,
+ FTSRestRequest tdbRestRequest)
+ {
+ FTSRestResponse searchResult = new FTSRestResponse();
+ List<FTSData> result = null;
+
+ try
+ {
+ if (jsonObj == null)
+ {
+ jsonObj = (Map<String, Object>) JSONUtils
+ .parse(tdbJsonResponseString);
+ }
+
+ Object uniprot_entry = jsonObj.get("uniprot_entry");
+ // TODO: decide if anything from uniprot_entry needs to be reported via
+ // the FTSRestResponse object
+ // Arnaud added seqLength = (Long) ((Map<String, Object>)
+ // jsonObj.get("uniprot_entry")).get("sequence_length");
+
+ List<Object> structures = (List<Object>) jsonObj.get("structures");
+ result = new ArrayList<>();
+
+ int numFound = 0;
+ for (Iterator<Object> strucIter = structures.iterator(); strucIter
+ .hasNext();)
+ {
+ Map<String, Object> structure = (Map<String, Object>) strucIter
+ .next();
+ result.add(getFTSData(structure, tdbRestRequest));
+ numFound++;
+ }
+
+ searchResult.setNumberOfItemsFound(numFound);
+ searchResult.setSearchSummary(result);
+
+ } catch (ParseException e)
+ {
+ e.printStackTrace();
+ }
+ return searchResult;
+ }
+
+ private static FTSData getFTSData(Map<String, Object> tdbJsonStructure,
+ FTSRestRequest tdbRequest)
+ {
+ String primaryKey = null;
+ Object[] summaryRowData;
+
+ SequenceI associatedSequence;
+
+ Collection<FTSDataColumnI> displayFields = tdbRequest.getWantedFields();
+ SequenceI associatedSeq = tdbRequest.getAssociatedSequence();
+ int colCounter = 0;
+ summaryRowData = new Object[(associatedSeq != null)
+ ? displayFields.size() + 1
+ : displayFields.size()];
+ if (associatedSeq != null)
+ {
+ associatedSequence = associatedSeq;
+ summaryRowData[0] = associatedSequence;
+ colCounter = 1;
+ }
+
+ for (FTSDataColumnI field : displayFields)
+ {
+ String fieldData = (tdbJsonStructure.get(field.getCode()) == null)
+ ? " "
+ : tdbJsonStructure.get(field.getCode()).toString();
+ // System.out.println("Field : " + field + " Data : " + fieldData);
+ if (field.isPrimaryKeyColumn())
+ {
+ primaryKey = fieldData;
+ summaryRowData[colCounter++] = primaryKey;
+ }
+ else if (fieldData == null || fieldData.trim().isEmpty())
+ {
+ summaryRowData[colCounter++] = null;
+ }
+ else
+ {
+ try
+ {
+ summaryRowData[colCounter++] = (field.getDataType()
+ .getDataTypeClass() == Integer.class)
+ ? Integer.valueOf(fieldData)
+ : (field.getDataType()
+ .getDataTypeClass() == Double.class)
+ ? Double.valueOf(fieldData)
+ : fieldData;
+ } catch (Exception e)
+ {
+ // e.printStackTrace();
+ System.out.println("offending value:" + fieldData + fieldData);
+ }
+ }
+ }
+ final String primaryKey1 = primaryKey;
+ final Object[] summaryRowData1 = summaryRowData;
+
+ return new TDB_FTSData(primaryKey, tdbJsonStructure, summaryRowData1);
+ }
+
+ // private static FTSData getFTSData(Map<String, Object> doc,
+ // FTSRestRequest tdbRestRequest)
+ // {
+ // String primaryKey = null;
+ //
+ // Object[] summaryRowData;
+ //
+ // Collection<FTSDataColumnI> displayFields =
+ // tdbRestRequest.getWantedFields();
+ // int colCounter = 0;
+ // summaryRowData = new Object[displayFields.size() + 1];
+ //
+ // return null;
+ // }
+
+ private String parseJsonExceptionString(String jsonErrorString)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getColumnDataConfigFileName()
+ {
+ return "/fts/tdbeacons_data_columns.txt";
+ }
+
+ public static FTSRestClientI getInstance()
+ {
+ if (instance == null)
+ {
+ instance = new TDBeaconsFTSRestClient();
+ }
+ return instance;
+ }
+
+ private Collection<FTSDataColumnI> allDefaultDisplayedStructureDataColumns;
+
+ 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[] { "3DB Beacons Field",
+ "Show in search summary", "Show in structure summary" };
+ break;
+ default:
+ break;
+ }
+ return columnNames;
+ }
+}