JAL-3829 point at production 3d-beacons url
[jalview.git] / src / jalview / fts / service / threedbeacons / TDBeaconsFTSRestClient.java
index 1ee7f37..cb0bc2d 100644 (file)
@@ -6,6 +6,7 @@ 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;
 
@@ -20,21 +21,34 @@ 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
 {
-  private static final String DEFAULT_THREEDBEACONS_DOMAIN = 
-          "https://wwwdev.ebi.ac.uk/pdbe/pdbe-kb/3dbeacons-hub-api/uniprot/";
-  
-  private static FTSRestClientI instance = null;
-  
+  /**
+   * 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)
@@ -42,15 +56,7 @@ public class TDBeaconsFTSRestClient extends FTSRestClient
   {
     try
     {
-      // Removed wantedFields, sortParam & facetPivot from PDBFTSRClient
-      String wantedFields = getDataColumnsFieldsAsCommaDelimitedString(
-              tdbRestRequest.getWantedFields());
-      int responseSize = (tdbRestRequest.getResponseSize() == 0)
-              ? getDefaultResponsePageSize()
-              : tdbRestRequest.getResponseSize();
-      
-      String query = tdbRestRequest.getFieldToSearchBy()
-              + tdbRestRequest.getSearchTerm();
+      String query = tdbRestRequest.getSearchTerm();
       Client client;
       Class<ClientResponse> clientResponseClass;
       if (Platform.isJS())
@@ -62,6 +68,7 @@ public class TDBeaconsFTSRestClient extends FTSRestClient
       else
       /**
        * Java only
+       * 
        * @j2sIgnore
        */
       {
@@ -70,27 +77,31 @@ public class TDBeaconsFTSRestClient extends FTSRestClient
       }
       WebResource webResource;
       webResource = client.resource(DEFAULT_THREEDBEACONS_DOMAIN)
-              .queryParam("P",query);
+              .path(query);
       URI uri = webResource.getURI();
-        
-      System.out.println(uri);
-        
+      System.out.println(uri.toString());
+
       // Execute the REST request
-      ClientResponse clientResponse = webResource
-              .accept(MediaType.APPLICATION_JSON).get(clientResponseClass);
-  
+      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;
-  
-      System.out.println("query >>>>>>> " + tdbRestRequest.toString());
-        
+
       // Check the response status and report exception if one occurs
-      int responseStatus = clientResponse.getStatus();
+      int responseStatus = isMocked() ? (mockQuery.equals(query) ? 200 : 404) : clientResponse.getStatus();
       switch (responseStatus)
       {
-      // if succesful
+      // if success
       case 200:
         if (Platform.isJS())
         {
@@ -98,17 +109,20 @@ public class TDBeaconsFTSRestClient extends FTSRestClient
         }
         else
         {
-          responseString = clientResponse.getEntity(String.class);
+          responseString = isMocked() ? mockResponse: 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);
+      return parseTDBeaconsJsonResponse(responseString, jsonObj,
+              tdbRestRequest);
     } catch (Exception e)
     {
       String exceptionMsg = e.getMessage();
@@ -129,59 +143,70 @@ public class TDBeaconsFTSRestClient extends FTSRestClient
         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)
+  public static FTSRestResponse parseTDBeaconsJsonResponse(
+          String tdbJsonResponseString, Map<String, Object> jsonObj,
+          FTSRestRequest tdbRestRequest)
   {
     FTSRestResponse searchResult = new FTSRestResponse();
-    //searchResult.setNumberOfItemsFound(1);
     List<FTSData> result = null;
-    
+
     try
     {
       if (jsonObj == null)
       {
-        jsonObj = (Map<String, Object>) JSONUtils.parse(tdbJsonResponseString);
-      }
-      Map<String, Object> tdbEntry = (Map<String, Object>) jsonObj.get("uniprot_entry");
-      //String seqLength = tdbEntry.get("sequence_length").toString();
-      int seqLength = Integer.valueOf(tdbEntry.get("sequence_length").toString());
-      
-      // tdbStructures is the list of found structures
-//      Map<String, Object> tdbStructures = (Map<String, Object>) jsonObj.get("structures");
-      Object[] structures = (Object[]) jsonObj.get("structures");
-      String accessName = ((Map<String, Object>) jsonObj.get("uniprot_entry"))
-              .get("ac").toString();
-      // this is to be modified
-      int numFound = structures.length;
-//      if (numFound > 0)
-//      {
-//        
-//        result = new ArrayList<>();
-//        List<String> models;
-//        //= ((Map<String, Object>) jsonObj.get("structures"))
-//                //.get("model_identifier").toString();
-//        for (Iterator<String> modelsIter = models.iterator(); modelsIter.hasNext();)
-//                .hasNext();)
-//        {
-//          Map<String, Object> doc = (Map<String, Object>) docIter.next();
-//          result.add(getFTSData(doc, tdbRestRequest));
-//        }
-        searchResult.setNumberOfItemsFound(numFound); 
-        // searchResult.setAccessionName(accessName); ?usefulness?       
-//        searchResult.setSearchSummary(result);
-//        
-//      }
+        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();
@@ -189,19 +214,127 @@ public class TDBeaconsFTSRestClient extends FTSRestClient
     return searchResult;
   }
 
-//  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 static FTSData getFTSData(Map<String, Object> tdbJsonStructure,
+          FTSRestRequest tdbRequest)
+  {
+    // TODO: consider reusing PDBFTSRestClient.getFTSData ?
+
+    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 FTSData()
+    {
+
+      @Override
+      public Object[] getSummaryData()
+      {
+        return summaryRowData1;
+      }
+
+      @Override
+      public Object getPrimaryKey()
+      {
+        return primaryKey1;
+      }
+
+      /**
+       * Returns a string representation of this object;
+       */
+      @Override
+      public String toString()
+      {
+        StringBuilder summaryFieldValues = new StringBuilder();
+        for (Object summaryField : summaryRowData1)
+        {
+          summaryFieldValues.append(
+                  summaryField == null ? " " : summaryField.toString())
+                  .append("\t");
+        }
+        return summaryFieldValues.toString();
+      }
+
+      /**
+       * Returns hash code value for this object
+       */
+      @Override
+      public int hashCode()
+      {
+        return Objects.hash(primaryKey1, this.toString());
+      }
+
+      @Override
+      public boolean equals(Object that)
+      {
+        return this.toString().equals(that.toString());
+      }
+    };
+  }
+
+  // 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)
   {
@@ -212,10 +345,9 @@ public class TDBeaconsFTSRestClient extends FTSRestClient
   @Override
   public String getColumnDataConfigFileName()
   {
-    // TODO Auto-generated method stub
-    return null;
+    return "/fts/tdbeacons_data_columns.txt";
   }
-  
+
   public static FTSRestClientI getInstance()
   {
     if (instance == null)
@@ -224,7 +356,7 @@ public class TDBeaconsFTSRestClient extends FTSRestClient
     }
     return instance;
   }
-  
+
   private Collection<FTSDataColumnI> allDefaultDisplayedStructureDataColumns;
 
   public Collection<FTSDataColumnI> getAllDefaultDisplayedStructureDataColumns()
@@ -238,5 +370,26 @@ public class TDBeaconsFTSRestClient extends FTSRestClient
     }
     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;
+  }
 }