JAL-3860 prototype for highlight species/assembly/chromosome/position
[jalview.git] / src / jalview / rest / API.java
index aada285..2455914 100644 (file)
@@ -1,27 +1,8 @@
 package jalview.rest;
 
-import java.io.File;
-import java.io.IOException;
-import java.io.PrintWriter;
 import java.net.BindException;
-import java.net.MalformedURLException;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.concurrent.CompletableFuture;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.xml.bind.DatatypeConverter;
-
-import jalview.bin.Cache;
-import jalview.gui.CutAndPasteTransfer;
-import jalview.gui.Desktop;
-import jalview.gui.SequenceFetcher;
-import jalview.util.DBRefUtils;
 
 public class API extends RestHandler
 {
@@ -33,6 +14,8 @@ public class API extends RestHandler
 
   private static Map<String, String> requestMap = new HashMap<>();
 
+  private static Map<String, Object> objectMap = new HashMap<>();
+
   private static API instance = null;
 
   public static API getInstance() throws BindException
@@ -62,12 +45,12 @@ public class API extends RestHandler
     super.init(MY_PATH);
 
     // add endpoints here
-    addEndpoint("fetchsequence", (String s, HttpServletRequest rq,
-            HttpServletResponse rs) -> fetchSequence(s, rq, rs));
-    addEndpoint("opensequence", (String s, HttpServletRequest rq,
-            HttpServletResponse rs) -> openSequence(s, rq, rs));
-    addEndpoint("highlight", (String s, HttpServletRequest rq,
-            HttpServletResponse rs) -> highlight(s, rq, rs));
+    addEndpoint(new FetchSequencesEndpoint(this));
+    addEndpoint(new InputAlignmentEndpoint(this));
+    addEndpoint(new HighlightSequenceEndpoint(this));
+    addEndpoint(new SelectSequencesEndpoint(this));
+    addEndpoint(new GetCrossReferencesEndpoint(this));
+    addEndpoint(new HighlightGenomicRangeEndpoint(this));
 
     setPath(MY_PATH);
     this.registerHandler();
@@ -75,231 +58,6 @@ public class API extends RestHandler
     init = true;
   }
 
-  // for the "fetchsequence" endpoint
-  private void fetchSequence(String endpointName,
-          HttpServletRequest request, HttpServletResponse response)
-  {
-    // note that endpointName should always be "fetchsequence"
-
-    String[] parameters = getEndpointPathParameters(request);
-
-    // check we can run fetchsequence
-    if (parameters.length < 2)
-    {
-      returnError(request, response,
-              "requires 2 path parameters: dbname, ids");
-      return;
-    }
-
-    String dbName = parameters[0];
-    String dbId = parameters[1];
-
-    // final for async later
-    final String id = getId(request, endpointName, dbName + "::" + dbId);
-    if (checkStatus(request, response, id))
-      return;
-
-    String db = DBRefUtils.getCanonicalName(dbName);
-    Desktop desktop = Desktop.instance;
-    SequenceFetcher sf = new SequenceFetcher(desktop, db, dbId);
-    CompletableFuture<Void> cf = sf.ok_actionPerformed(true);
-
-    setFuture(cf, id);
-    returnStatus(response, id);
-    changeStatus(id, Status.IN_PROGRESS);
-  }
-
-  // for the "opensequence" endpoint
-  private void openSequence(String endpointName, HttpServletRequest request,
-          HttpServletResponse response)
-  {
-    // note that endpointName should always be "opensequence"
-    String fileString = request.getParameter("file");
-    String urlString = request.getParameter("url");
-    String method = request.getMethod().toLowerCase();
-    String dataString = request.getParameter("data");
-    String body = null;
-    boolean post = method.equalsIgnoreCase("post");
-    boolean data = dataString != null;
-
-    String access = null;
-    String ref = null;
-    if (post)
-    {
-      access = "post";
-      try
-      {
-        body = getRequestBody(request);
-      } catch (IOException e)
-      {
-        returnError(request, response, "could not read POST body");
-        Cache.debug(e);
-        return;
-      }
-      // for ref see md5 later
-    }
-    else if (data)
-    {
-      access = "data";
-      // for ref see md5 later
-    }
-    else if (fileString != null)
-    {
-      access = "file";
-      ref = fileString;
-    }
-    else if (urlString != null)
-    {
-      access = "url";
-      ref = urlString;
-    }
-
-    if (access == null)
-    {
-      returnError(request, response,
-              "requires POST body or one of parameters 'data', 'file' or 'url'");
-      return;
-    }
-
-    // final content used in Future
-    final String content;
-    if (post || data)
-    {
-      content = post ? body : dataString;
-      try
-      {
-        MessageDigest md5 = MessageDigest.getInstance("MD5");
-        md5.update(content.getBytes());
-        byte[] digest = md5.digest();
-        ref = DatatypeConverter.printBase64Binary(digest).toLowerCase();
-      } catch (NoSuchAlgorithmException e)
-      {
-        Cache.debug(e);
-      }
-    }
-    else
-    {
-      content = null;
-    }
-
-    // final for async later
-    final String id = getId(request, endpointName, access + "::" + ref);
-    if (checkStatus(request, response, id))
-      return;
-
-    CompletableFuture<Void> cf = CompletableFuture.runAsync(() -> {
-      if (post || data)
-      {
-        // Sequence file contents being posted
-        // use File -> Input Alignment -> from Textbox
-        CutAndPasteTransfer cap = new CutAndPasteTransfer();
-        cap.setText(content);
-        cap.ok_actionPerformed(null);
-        cap.cancel_actionPerformed(null);
-      }
-      else if (fileString != null)
-      {
-        // Sequence file on filesystem
-        // use File -> Input Alignment -> From File
-        URL url = null;
-        File file = null;
-        try
-        {
-          url = new URL(fileString);
-          file = new File(url.toURI());
-        } catch (MalformedURLException | URISyntaxException e)
-        {
-          returnError(request, response,
-                  "could not resolve file='" + fileString + "'");
-          Cache.debug(e);
-          return;
-        }
-        if (!file.exists())
-        {
-          returnError(request, response,
-                  "file='" + fileString + "' does not exist");
-          return;
-        }
-        Desktop.instance.openFile(file, null, null);
-      }
-      else if (urlString != null)
-      {
-        boolean success = Desktop.instance.loadUrl(urlString, null);
-        if (!success)
-        {
-          returnError(request, response,
-                  "url='" + urlString + "' could not be opened");
-          return;
-        }
-      }
-    });
-
-    setFuture(cf, id);
-    returnStatus(response, id);
-    changeStatus(id, Status.IN_PROGRESS);
-  }
-
-  // for the "highlight" endpoint
-  private void highlight(String endpointName, HttpServletRequest request,
-          HttpServletResponse response)
-  {
-    String[] parameters = getEndpointPathParameters(request);
-
-    // check we can run highlight
-    if (parameters.length < 1)
-    {
-      returnError(request, response, "requires 1 path parameters: ranges");
-      return;
-    }
-
-    String rangesString = parameters[0];
-    String[] rangeStrings = rangesString.split(",");
-    int[][] ranges = new int[rangeStrings.length][2];
-    for (int i = 0; i < rangeStrings.length; i++)
-    {
-      String range = rangeStrings[i];
-      try
-      {
-        int hyphenpos = range.indexOf('-');
-        if (hyphenpos < 0)
-        {
-          ranges[i][0] = Integer.parseInt(range);
-          ranges[i][1] = ranges[i][0];
-        }
-        else
-        {
-          ranges[i][0] = Integer.parseInt(range.substring(0, hyphenpos));
-          ranges[i][1] = Integer.parseInt(range.substring(hyphenpos));
-        }
-      } catch (NumberFormatException nfe)
-      {
-        returnError(request, response,
-                "couldn't parse ranges component '" + range + "'");
-        return;
-      }
-    }
-
-  }
-
-  // template endpoint
-  private void templateEndpoint(String endpointName,
-          HttpServletRequest request, HttpServletResponse response)
-  {
-    // final for async later
-    final String id = getId(request, endpointName,
-            "some identifier for this endpoint request");
-    if (checkStatus(request, response, id))
-      return;
-
-    CompletableFuture<Void> cf = CompletableFuture.runAsync(() -> {
-      // do stuff
-    });
-
-    setFuture(cf, id);
-    returnStatus(response, id);
-    changeStatus(id, Status.IN_PROGRESS);
-  }
-
   /*
    * Shared methods below here
    */
@@ -310,86 +68,6 @@ public class API extends RestHandler
     return MY_PATH;
   }
 
-  private void changeStatus(String id, Status status)
-  {
-    // don't change a job's status if it has finished or died
-    if (statusMap.get(id) == Status.FINISHED
-            || statusMap.get(id) == Status.ERROR)
-      return;
-    statusMap.put(id, status);
-  }
-
-  private Status getStatus(String id)
-  {
-    return statusMap.get(id);
-  }
-
-  protected void returnStatus(HttpServletResponse response, String id)
-  {
-    try
-    {
-      PrintWriter writer = response.getWriter();
-      if (id != null)
-        writer.write("id=" + id + "\n");
-      if (requestMap.get(id) != null)
-        writer.write("request=" + requestMap.get(id).toString() + "\n");
-      if (statusMap.get(id) != null)
-      {
-        if (statusMap.get(id) == Status.ERROR)
-          response.setStatus(500);
-        writer.write("status=" + statusMap.get(id).toString() + "\n");
-      }
-    } catch (IOException e)
-    {
-      Cache.debug(e);
-    }
-  }
-
-  private String getId(HttpServletRequest request, String endpointName,
-          String extra)
-  {
-    String idString = request.getParameter("id");
-    if (idString == null)
-    {
-      idString = endpointName + "::" + extra;
-    }
-    return idString;
-  }
-
-  private boolean checkStatus(HttpServletRequest request,
-          HttpServletResponse response, String id)
-  {
-    Status status = statusMap.get(id);
-    if (status == null)
-    {
-      statusMap.put(id, Status.STARTED);
-      requestMap.put(id, request.getRequestURI());
-    }
-    else
-    {
-      returnStatus(response, id);
-      return true;
-    }
-    return false;
-  }
-
-  private void setFuture(CompletableFuture<Void> cf, String id)
-  {
-    cf.whenComplete((Void, e) -> {
-      if (e != null)
-      {
-        Cache.error("API job " + id + " did not complete");
-        Cache.debug(e);
-        changeStatus(id, Status.ERROR);
-      }
-      else
-      {
-        Cache.info("API job " + id + " completed successfully");
-        changeStatus(id, Status.FINISHED);
-      }
-    });
-  }
-
   protected static Map<String, Status> getStatusMap()
   {
     return statusMap;
@@ -399,4 +77,9 @@ public class API extends RestHandler
   {
     return requestMap;
   }
+
+  protected static Map<String, Object> getObjectMap()
+  {
+    return objectMap;
+  }
 }