From c70f20cbe903a0d8c1a6b0f391d2b1c32e3ba53e Mon Sep 17 00:00:00 2001
From: Manuel Spuhler <manuel.spuhler@chuv.ch>
Date: Wed, 12 Jun 2019 18:22:30 +0200
Subject: [PATCH] Workflow gateway methods

---
 docker/config/application.tmpl                |   5 +-
 .../eu/hbp/mip/controllers/ExperimentApi.java | 189 ++++++++++++------
 .../eu/hbp/mip/controllers/MethodsApi.java    |  27 +++
 src/main/java/eu/hbp/mip/utils/HTTPUtil.java  |  72 ++-----
 4 files changed, 172 insertions(+), 121 deletions(-)

diff --git a/docker/config/application.tmpl b/docker/config/application.tmpl
index 5f9ea27f9..b4c1909d5 100644
--- a/docker/config/application.tmpl
+++ b/docker/config/application.tmpl
@@ -89,4 +89,7 @@ endpoints:
 services:
   exareme:
     miningExaremeUrl: {{ default .Env.EXAREME_URL "http://localhost:9090" }}/mining/query
-    algorithmsUrl: {{ default .Env.EXAREME_URL "http://localhost:9090" }}/mining/algorithms.json
\ No newline at end of file
+    algorithmsUrl: {{ default .Env.EXAREME_URL "http://localhost:9090" }}/mining/algorithms.json
+  workflows:
+    workflowUrl: {{ default .Env.WORKFLOW_URL "http://localhost:9090" }}
+    workflowAuthorization: {{ default .Env.WORKFLOW_AUTHORIZATION "-" }}
\ No newline at end of file
diff --git a/src/main/java/eu/hbp/mip/controllers/ExperimentApi.java b/src/main/java/eu/hbp/mip/controllers/ExperimentApi.java
index 1f36e8710..2c6260608 100644
--- a/src/main/java/eu/hbp/mip/controllers/ExperimentApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/ExperimentApi.java
@@ -2,6 +2,7 @@ package eu.hbp.mip.controllers;
 
 import akka.dispatch.OnSuccess;
 import ch.chuv.lren.mip.portal.WokenConversions;
+import com.google.gson.*;
 import com.google.common.collect.Lists;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
@@ -46,6 +47,12 @@ public class ExperimentApi extends WokenClientController {
     @Value("#{'${services.exareme.miningExaremeUrl:http://localhost:9090/mining/query}'}")
     public String miningExaremeQueryUrl;
 
+    @Value("#{'${services.workflows.workflowUrl}'}")
+    private String workflowUrl;
+
+    @Value("#{'${services.workflows.workflowAuthorization}'}")
+    private String workflowAuthorization;
+
     @Autowired
     private UserInfo userInfo;
 
@@ -75,7 +82,34 @@ public class ExperimentApi extends WokenClientController {
 
         String algoCode = expQuery.getAlgorithms().get(0).getCode();
         List<AlgorithmParam> params = expQuery.getAlgorithms().get(0).getParameters();
-        sendExaremeExperiment(experiment, algoCode, params);
+        new Thread(() -> {
+            List<HashMap<String, String>> queryList = new ArrayList<HashMap<String, String>>();
+
+            if (params != null) {
+                for (AlgorithmParam p : params) {
+                    queryList.add(makeObject(p.getName(), p.getValue()));
+                }
+            }
+
+            String query = gson.toJson(queryList);
+            String url = miningExaremeQueryUrl + "/" + algoCode;
+
+            // Results are stored in the experiment object
+            try {
+                StringBuilder results = new StringBuilder();
+                int code = HTTPUtil.sendPost(url, query, results);
+                experiment.setResult("[" + results.toString() + "]");
+                experiment.setHasError(code >= 400);
+                experiment.setHasServerError(code >= 500);
+            } catch (IOException e) {
+                LOGGER.trace("Invalid UUID", e);
+                LOGGER.warn("Exareme experiment failed to run properly !");
+                experiment.setHasError(true);
+                experiment.setHasServerError(true);
+                experiment.setResult(e.getMessage());
+            }
+            finishExperiment(experiment);
+        }).start();
 
         return new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
     }
@@ -89,7 +123,37 @@ public class ExperimentApi extends WokenClientController {
 
         String algoCode = expQuery.getAlgorithms().get(0).getCode();
         List<AlgorithmParam> params = expQuery.getAlgorithms().get(0).getParameters();
-        sendWorkflow(experiment, algoCode, params);
+        new Thread(() -> {
+            HashMap<String, String> queryMap = new HashMap<String, String>();
+
+            if (params != null) {
+                for (AlgorithmParam p : params) {
+                    queryMap.put(p.getName(), p.getValue());
+                }
+            }
+
+            String query = gson.toJson(queryMap);
+            LOGGER.info("****************************** query");
+            LOGGER.info(query);
+            String url = workflowUrl + "/runWorkflow/" + algoCode;
+            // Results are stored in the experiment object
+            try {
+                StringBuilder results = new StringBuilder();
+                int code = HTTPUtil.sendAuthorizedHTTP(url, query, results, "POST", workflowAuthorization);
+                experiment.setResult("[" + results.toString() + "]");
+                LOGGER.info("****************************** results");
+                LOGGER.info(results.toString());
+                experiment.setHasError(code >= 400);
+                experiment.setHasServerError(code >= 500);
+            } catch (IOException e) {
+                LOGGER.trace("Invalid UUID", e);
+                LOGGER.warn("Workflow failed to run properly !");
+                experiment.setHasError(true);
+                experiment.setHasServerError(true);
+                experiment.setResult(e.getMessage());
+            }
+            finishExperiment(experiment);
+        }).start();
 
         return new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
     }
@@ -119,6 +183,62 @@ public class ExperimentApi extends WokenClientController {
         return new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
     }
 
+    @ApiOperation(value = "get workflow status", response = String.class)
+    @RequestMapping(value = "/workflow/status/{historyId}", method = RequestMethod.GET)
+    public ResponseEntity<String> getWorkflowStatus(
+            @ApiParam(value = "historyId", required = true) @PathVariable("historyId") String historyId) {
+        LOGGER.info("Get a workflow status");
+
+        String url = workflowUrl + "/getWorkflowStatus/" + historyId;
+        try {
+            StringBuilder response = new StringBuilder();
+            HTTPUtil.sendAuthorizedHTTP(url, "", response, "GET", workflowAuthorization);
+            JsonElement element = new JsonParser().parse(response.toString());
+
+            return ResponseEntity.ok(gson.toJson(element));
+        } catch (IOException e) {
+            return ResponseEntity.status(500).body(e.getMessage());
+        }
+    }
+
+    // TODO: factorize workflow results
+    @ApiOperation(value = "get workflow results", response = String.class)
+    @RequestMapping(value = "/workflow/results/{historyId}", method = RequestMethod.GET)
+    public ResponseEntity<String> getWorkflowResults(
+            @ApiParam(value = "historyId", required = true) @PathVariable("historyId") String historyId) {
+        LOGGER.info("Get a workflow results");
+
+        String url = workflowUrl + "/getWorkflowResults/" + historyId;
+        try {
+            StringBuilder response = new StringBuilder();
+            HTTPUtil.sendAuthorizedHTTP(url, "", response, "GET", workflowAuthorization);
+            JsonElement element = new JsonParser().parse(response.toString());
+
+            return ResponseEntity.ok(gson.toJson(element));
+        } catch (IOException e) {
+            return ResponseEntity.status(500).body(e.getMessage());
+        }
+    }
+
+    @ApiOperation(value = "get workflow result body", response = String.class)
+    @RequestMapping(value = "/workflow/resultsbody/{historyId}/content/{resultId}", method = RequestMethod.GET)
+    public ResponseEntity<String> getWorkflowResultBody(
+            @ApiParam(value = "historyId", required = true) @PathVariable("historyId") String historyId,
+            @ApiParam(value = "resultId", required = true) @PathVariable("resultId") String resultId) {
+        LOGGER.info("Get a workflow result content");
+
+        String url = workflowUrl + "/getWorkflowResultsBody/" + historyId + "/contents/" + resultId;
+        try {
+            StringBuilder response = new StringBuilder();
+            HTTPUtil.sendAuthorizedHTTP(url, "", response, "GET", workflowAuthorization);
+            JsonElement element = new JsonParser().parse(response.toString());
+
+            return ResponseEntity.ok(gson.toJson(element));
+        } catch (IOException e) {
+            return ResponseEntity.status(500).body(e.getMessage());
+        }
+    }
+
     @ApiOperation(value = "Mark an experiment as viewed", response = Experiment.class)
     @RequestMapping(value = "/{uuid}/markAsViewed", method = RequestMethod.GET)
     public ResponseEntity<String> markExperimentAsViewed(
@@ -279,69 +399,6 @@ public class ExperimentApi extends WokenClientController {
         }, ec);
     }
 
-    private void sendExaremeExperiment(Experiment experiment, String algoCode, List<AlgorithmParam> params) {
-        // this runs in the background. For future optimization: use a thread pool
-        new Thread(() -> {
-            List<HashMap<String, String>> queryList = new ArrayList<HashMap<String, String>>();
-
-            if (params != null) {
-                for (AlgorithmParam p : params) {
-                    queryList.add(makeObject(p.getName(), p.getValue()));
-                }
-            }
-
-            String query = gson.toJson(queryList);
-            String url = miningExaremeQueryUrl + "/" + algoCode;
-
-            // Results are stored in the experiment object
-            try {
-                StringBuilder results = new StringBuilder();
-                int code = HTTPUtil.sendPost(url, query, results);
-                experiment.setResult("[" + results.toString() + "]");
-                experiment.setHasError(code >= 400);
-                experiment.setHasServerError(code >= 500);
-            } catch (IOException e) {
-                LOGGER.trace("Invalid UUID", e);
-                LOGGER.warn("Exareme experiment failed to run properly !");
-                experiment.setHasError(true);
-                experiment.setHasServerError(true);
-                experiment.setResult(e.getMessage());
-            }
-            finishExperiment(experiment);
-        }).start();
-    }
-
-    private void sendWorkflow(Experiment experiment, String algoCode, List<AlgorithmParam> params) {
-        // this runs in the background. For future optimization: use a thread pool
-        new Thread(() -> {
-            HashMap<String, String> queryMap = new HashMap<String, String>();
-
-            if (params != null) {
-                for (AlgorithmParam p : params) {
-                    queryMap.put(p.getName(), p.getValue());
-                }
-            }
-
-            String query = gson.toJson(queryMap);
-            String url = "http://88.197.53.36:8080/Gateway_API-1.0.0-SNAPSHOT/api/runWorkflow/3f5830403180d620";
-            // Results are stored in the experiment object
-            try {
-                StringBuilder results = new StringBuilder();
-                int code = HTTPUtil.sendWorkflowHTTP(url, query, results);
-                experiment.setResult("[" + results.toString() + "]");
-                experiment.setHasError(code >= 400);
-                experiment.setHasServerError(code >= 500);
-            } catch (IOException e) {
-                LOGGER.trace("Invalid UUID", e);
-                LOGGER.warn("Exareme experiment failed to run properly !");
-                experiment.setHasError(true);
-                experiment.setHasServerError(true);
-                experiment.setResult(e.getMessage());
-            }
-            finishExperiment(experiment);
-        }).start();
-    }
-
     private void finishExperiment(Experiment experiment) {
         experiment.setFinished(new Date());
         experimentRepository.save(experiment);
@@ -350,7 +407,7 @@ public class ExperimentApi extends WokenClientController {
     }
 
     private HashMap<String, String> makeObject(String name, String value) {
-        HashMap<String, String> o =  new HashMap<String, String>();
+        HashMap<String, String> o = new HashMap<String, String>();
         o.put("name", name);
         o.put("value", value);
 
diff --git a/src/main/java/eu/hbp/mip/controllers/MethodsApi.java b/src/main/java/eu/hbp/mip/controllers/MethodsApi.java
index 21d3b9f2f..5eaf651b7 100644
--- a/src/main/java/eu/hbp/mip/controllers/MethodsApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/MethodsApi.java
@@ -30,6 +30,12 @@ public class MethodsApi extends WokenClientController {
     @Value("#{'${services.exareme.algorithmsUrl:http://localhost:9090/mining/algorithms.json}'}")
     private String exaremeAlgorithmsUrl;
 
+    @Value("#{'${services.workflows.workflowUrl}'}")
+    private String workflowUrl;
+
+    @Value("#{'${services.workflows.workflowAuthorization}'}")
+    private String workflowAuthorization;
+
     @ApiOperation(value = "List available methods and validations", response = String.class)
     @Cacheable(value = "methods", unless = "#result.getStatusCode().value()!=200")
     @RequestMapping(method = RequestMethod.GET)
@@ -62,4 +68,25 @@ public class MethodsApi extends WokenClientController {
 
     }
 
+    @ApiOperation(value = "List Galaxy workflows", response = String.class)
+    @RequestMapping(value = "/workflows", method = RequestMethod.GET)
+    public ResponseEntity<Object> getWorkflows() {
+        LOGGER.info("List Galaxy workflows");
+
+        try {
+            StringBuilder response = new StringBuilder();
+            HTTPUtil.sendAuthorizedHTTP(workflowUrl + "/getAllWorkflowWithDetails", "", response, "GET", workflowAuthorization);
+            LOGGER.info("************************************************* workflows");
+            LOGGER.info(workflowUrl + "/getAllWorkflowWithDetails");
+            LOGGER.info(workflowAuthorization);
+            LOGGER.info(response.toString());
+            JsonElement element = new JsonParser().parse(response.toString());
+
+            return ResponseEntity.ok(gson.toJson(element));
+        } catch (IOException e) {
+            return ResponseEntity.status(500).body(e.getMessage());
+        }
+
+    }
+
 }
diff --git a/src/main/java/eu/hbp/mip/utils/HTTPUtil.java b/src/main/java/eu/hbp/mip/utils/HTTPUtil.java
index e3c1de511..5c5043463 100644
--- a/src/main/java/eu/hbp/mip/utils/HTTPUtil.java
+++ b/src/main/java/eu/hbp/mip/utils/HTTPUtil.java
@@ -13,29 +13,37 @@ import java.nio.charset.StandardCharsets;
  */
 public class HTTPUtil {
 
-    private HTTPUtil()
-    {
+    private HTTPUtil() {
         /* Hide implicit public constructor */
         throw new IllegalAccessError("HTTPUtil class");
     }
 
     public static int sendGet(String url, StringBuilder resp) throws IOException {
-        return sendHTTP(url, "", resp, "GET");
+        return sendHTTP(url, "", resp, "GET", null);
     }
 
     public static int sendPost(String url, String query, StringBuilder resp) throws IOException {
-        return sendHTTP(url, query, resp, "POST");
+        return sendHTTP(url, query, resp, "POST", null);
     }
 
-    private static int sendHTTP(String url, String query, StringBuilder resp, String httpVerb) throws IOException {
+    public static int sendAuthorizedHTTP(String url, String query, StringBuilder resp, String httpVerb,
+            String authorization) throws IOException {
+        return sendHTTP(url, query, resp, httpVerb, authorization);
+    }
+
+    private static int sendHTTP(String url, String query, StringBuilder resp, String httpVerb, String authorization)
+            throws IOException {
 
         URL obj = new URL(url);
         HttpURLConnection con = (HttpURLConnection) obj.openConnection();
 
-        if(!"GET".equals(httpVerb)) {
+        if (authorization != null) {
+            con.setRequestProperty("Authorization", authorization);
+        }
+
+        if (!"GET".equals(httpVerb)) {
             con.setRequestMethod(httpVerb);
-            if(query != null && query.length() > 0)
-            {
+            if (query != null && query.length() > 0) {
                 con.addRequestProperty("Content-Type", "application/json");
                 con.setRequestProperty("Content-Length", Integer.toString(query.length()));
 
@@ -50,53 +58,9 @@ public class HTTPUtil {
         int respCode = con.getResponseCode();
 
         BufferedReader in;
-        if(respCode == 200) {
+        if (respCode == 200) {
             in = new BufferedReader(new InputStreamReader(con.getInputStream()));
-        }
-        else
-        {
-            in = new BufferedReader(new InputStreamReader(con.getErrorStream()));
-        }
-        String inputLine;
-        StringBuilder response = new StringBuilder();
-
-        while ((inputLine = in.readLine()) != null) {
-            response.append(inputLine);
-        }
-        in.close();
-        resp.append(response.toString());
-
-        return respCode;
-    }
-
-    /* FIXME: Authorization */ 
-    public static int sendWorkflowHTTP(String url, String query, StringBuilder resp) throws IOException {
-
-        URL obj = new URL(url);
-        HttpURLConnection con = (HttpURLConnection) obj.openConnection();
-
-        con.setRequestMethod("POST");
-        if(query != null && query.length() > 0)
-        {
-            con.addRequestProperty("Content-Type", "application/json");
-            con.setRequestProperty("Content-Length", Integer.toString(query.length()));
-
-            con.setDoOutput(true);
-            DataOutputStream wr = new DataOutputStream(con.getOutputStream());
-            wr.write(query.getBytes(StandardCharsets.UTF_8));
-            wr.flush();
-            wr.close();
-        }
-        
-
-        int respCode = con.getResponseCode();
-
-        BufferedReader in;
-        if(respCode == 200) {
-            in = new BufferedReader(new InputStreamReader(con.getInputStream()));
-        }
-        else
-        {
+        } else {
             in = new BufferedReader(new InputStreamReader(con.getErrorStream()));
         }
         String inputLine;
-- 
GitLab