Skip to content
Snippets Groups Projects
Commit 7a4fe157 authored by Habfast's avatar Habfast
Browse files

added experiment api

parent a6941a9c
No related branches found
Tags 2.5.8
No related merge requests found
......@@ -57,7 +57,9 @@
<connection.password>test</connection.password>
<hibernate.dialect>org.hibernate.dialect.PostgreSQL82Dialect</hibernate.dialect>
<schema.deploy>false</schema.deploy>
<frontend.redirect>http://frontend/#/home</frontend.redirect>
<frontend.redirect>http://frontend/home</frontend.redirect>
<workflow.experimentUrl>http://as-dev.cloudapp.net:8087/experiment</workflow.experimentUrl>
<workflow.listMethodsUrl>http://as-dev.cloudapp.net:8087/list-methods</workflow.listMethodsUrl>
</properties>
</profile>
<profile>
......@@ -71,7 +73,9 @@
<connection.password>test</connection.password>
<hibernate.dialect>org.hibernate.dialect.PostgreSQL82Dialect</hibernate.dialect>
<schema.deploy>false</schema.deploy>
<frontend.redirect>https://hbp-dev.ahead-solutions.ch/#/home</frontend.redirect>
<frontend.redirect>https://hbp-dev.ahead-solutions.ch/home</frontend.redirect>
<workflow.experimentUrl>http://as-dev.cloudapp.net:8087/experiment</workflow.experimentUrl>
<workflow.listMethodsUrl>http://as-dev.cloudapp.net:8087/list-methods</workflow.listMethodsUrl>
</properties>
</profile>
</profiles>
......
package org.hbp.mip.controllers;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import io.swagger.annotations.*;
import org.hbp.mip.MIPApplication;
import org.hbp.mip.model.Experiment;
import org.hbp.mip.model.Model;
import org.hbp.mip.model.User;
import org.hbp.mip.utils.HibernateUtil;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.exception.DataException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.*;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
/**
* Created by habfast on 21/04/16.
*/
@RestController
@RequestMapping(value = "/experiments", produces = {APPLICATION_JSON_VALUE})
@Api(value = "/experiments", description = "the experiments API")
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.SpringMVCServerCodegen", date = "2016-01-07T07:38:20.227Z")
public class ExperimentApi {
private static final Gson gson = new GsonBuilder()
.serializeNulls()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
.excludeFieldsWithoutExposeAnnotation()
.create();
@Value("#{'${workflow.experimentUrl:http://as-dev.cloudapp.net:8087/experiment}'}")
private String experimentUrl;
@Value("#{'${workflow.listMethodsUrl:http://as-dev.cloudapp.net:8087/list-methods}'}")
private String listMethodsUrl;
@Autowired
MIPApplication mipApplication;
private void sendPost(Experiment experiment) throws MalformedURLException {
URL obj = new URL(experimentUrl);
// this runs in the background. For future optimization: use a thread pool
new Thread() {
public void run() {
try {
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
String query = experiment.computeQuery();
System.out.println("Running experiment: " + query);
// create query
try {
con.setRequestMethod("POST");
} catch (ProtocolException pe) {} // ignore; won't happen
con.addRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Content-Length", Integer.toString(query.length()));
con.setFollowRedirects(true);
con.setReadTimeout(3600000); // 1 hour: 60*60*1000 ms
// write body of query
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.write(query.getBytes("UTF8"));
wr.flush();
wr.close();
// get response
InputStream stream = con.getResponseCode() < 400 ? con.getInputStream() : con.getErrorStream();
BufferedReader in = new BufferedReader(new InputStreamReader(stream));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine + '\n');
}
in.close();
// write to experiment
experiment.setResult(response.toString().replace("\0", ""));
experiment.setHasError(con.getResponseCode() >= 400);
experiment.setHasServerError(con.getResponseCode() >= 500);
} catch (IOException ioe) {
// write error to
experiment.setHasError(true);
experiment.setHasServerError(true);
experiment.setResult(ioe.getMessage());
}
experiment.setFinished(new Date());
// finally
try {
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction transaction = session.beginTransaction();
session.update(experiment);
transaction.commit();
session.close();
} catch (DataException e) {
throw e;
}
}
}.start();
}
@ApiOperation(value = "Send a request to the workflow to run an experiment", response = Experiment.class)
@ApiResponses(value = { @ApiResponse(code = 200, message = "Success") })
@RequestMapping(method = RequestMethod.POST)
public ResponseEntity<String> runExperiment(@RequestBody String incomingQueryString) {
JsonObject incomingQuery = gson.fromJson(incomingQueryString, JsonObject.class);
Experiment experiment = new Experiment();
experiment.setUuid(UUID.randomUUID());
User user = mipApplication.getUser();
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction transaction = session.beginTransaction();
try {
experiment.setAlgorithms(incomingQuery.get("algorithms").toString());
experiment.setValidations(incomingQuery.get("validations").toString());
experiment.setName(incomingQuery.get("name").getAsString());
experiment.setCreatedBy(user);
Query hibernateQuery = session.createQuery("from Model as model where model.slug = :slug");
hibernateQuery.setParameter("slug", incomingQuery.get("model").getAsString());
experiment.setModel((Model)hibernateQuery.uniqueResult());
session.save(experiment);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
e.printStackTrace();
// 400 here probably
return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
}
try {
sendPost(experiment);
} catch (MalformedURLException mue) {} // ignore
return new ResponseEntity<>(gson.toJson(experiment), HttpStatus.OK);
}
@ApiOperation(value = "get an experiment", response = Experiment.class)
@ApiResponses(value = { @ApiResponse(code = 200, message = "Success") })
@RequestMapping(value = "/{uuid}", method = RequestMethod.GET)
public ResponseEntity<String> getExperiment(@ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
Experiment experiment;
UUID experimentUuid;
try {
experimentUuid = UUID.fromString(uuid);
} catch (IllegalArgumentException iae) {
return ResponseEntity.badRequest().body("Invalid Experiment UUID");
}
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
try {
session.beginTransaction();
Query hibernateQuery = session.createQuery("from Experiment as experiment where experiment.uuid = :uuid");
hibernateQuery.setParameter("uuid", experimentUuid);
experiment = (Experiment) hibernateQuery.uniqueResult();
session.getTransaction().commit();
} catch (Exception e) {
// 404 here probably
session.getTransaction().rollback();
throw e;
}
if (experiment == null) {
return new ResponseEntity<>("Not found", HttpStatus.NOT_FOUND);
}
return new ResponseEntity<>(gson.toJson(experiment), HttpStatus.OK);
}
@ApiOperation(value = "get an experiment", response = Experiment.class)
@ApiResponses(value = { @ApiResponse(code = 200, message = "Success") })
@RequestMapping(value = "/{uuid}/markAsViewed", method = RequestMethod.GET)
public ResponseEntity<String> markExperimentAsViewed(@ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
Experiment experiment;
UUID experimentUuid;
User user = mipApplication.getUser();
try {
experimentUuid = UUID.fromString(uuid);
} catch (IllegalArgumentException iae) {
return ResponseEntity.badRequest().body("Invalid Experiment UUID");
}
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction transaction = null;
try {
transaction = session.beginTransaction();
Query hibernateQuery = session.createQuery("from Experiment as experiment where experiment.uuid = :uuid");
hibernateQuery.setParameter("uuid", experimentUuid);
experiment = (Experiment) hibernateQuery.uniqueResult();
if (!experiment.getCreatedBy().getUsername().equals(user.getUsername()))
return new ResponseEntity<>("You're not the owner of this experiment", HttpStatus.BAD_REQUEST);
experiment.setResultsViewed(true);
session.update(experiment);
transaction.commit();
} catch (Exception e) {
// 404 here probably
transaction.rollback();
throw e;
}
if (experiment == null) {
return new ResponseEntity<>("Not found", HttpStatus.NOT_FOUND);
}
return new ResponseEntity<>(gson.toJson(experiment), HttpStatus.OK);
}
public ResponseEntity<String> doMarkExperimentAsShared(String uuid, boolean shared) {
Experiment experiment;
UUID experimentUuid;
User user = mipApplication.getUser();
try {
experimentUuid = UUID.fromString(uuid);
} catch (IllegalArgumentException iae) {
return ResponseEntity.badRequest().body("Invalid Experiment UUID");
}
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction transaction = null;
try {
transaction = session.beginTransaction();
Query hibernateQuery = session.createQuery("from Experiment as experiment where experiment.uuid = :uuid");
hibernateQuery.setParameter("uuid", experimentUuid);
experiment = (Experiment) hibernateQuery.uniqueResult();
if (!experiment.getCreatedBy().getUsername().equals(user.getUsername()))
return new ResponseEntity<>("You're not the owner of this experiment", HttpStatus.BAD_REQUEST);
experiment.setShared(shared);
session.update(experiment);
transaction.commit();
} catch (Exception e) {
// 404 here probably
transaction.rollback();
throw e;
}
if (experiment == null) {
return new ResponseEntity<>("Not found", HttpStatus.NOT_FOUND);
}
return new ResponseEntity<>(gson.toJson(experiment), HttpStatus.OK);
}
@ApiOperation(value = "get an experiment", response = Experiment.class)
@ApiResponses(value = { @ApiResponse(code = 200, message = "Success") })
@RequestMapping(value = "/{uuid}/markAsShared", method = RequestMethod.GET)
public ResponseEntity<String> markExperimentAsShared(@ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
return doMarkExperimentAsShared(uuid, true);
}
@ApiOperation(value = "get an experiment", response = Experiment.class)
@ApiResponses(value = { @ApiResponse(code = 200, message = "Success") })
@RequestMapping(value = "/{uuid}/markAsUnshared", method = RequestMethod.GET)
public ResponseEntity<String> markExperimentAsUnshared(@ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
return doMarkExperimentAsShared(uuid, false);
}
public ResponseEntity<String> doListExperiments(
boolean mine,
int maxResultCount,
String modelSlug
) {
List<Experiment> experiments = new LinkedList<>();
User user = mipApplication.getUser();
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
try {
session.beginTransaction();
Query hibernateQuery;
String baseQuery = "from Experiment as e WHERE ";
baseQuery += mine ? "e.createdBy = :user" : "(e.createdBy = :user OR e.shared is true)";
if (modelSlug == null || modelSlug.equals("")) {
hibernateQuery = session.createQuery(baseQuery);
} else {
hibernateQuery = session.createQuery(baseQuery + " AND e.model.slug = :slug");
hibernateQuery.setParameter("slug", modelSlug);
}
hibernateQuery.setParameter("user", user);
if (maxResultCount > 0)
hibernateQuery.setMaxResults(maxResultCount);
for (Object experiment: hibernateQuery.list()) {
if (experiment instanceof Experiment) { // should definitely be true
Experiment experiment1 = (Experiment) experiment;
// remove some fields because it is costly and not useful to send them over the network
experiment1.setResult(null);
experiment1.setAlgorithms(null);
experiment1.setValidations(null);
experiments.add(experiment1);
}
}
} catch (Exception e) {
// 404 here probably
throw e;
} finally {
session.getTransaction().rollback();
}
return new ResponseEntity<>(gson.toJson(experiments), HttpStatus.OK);
}
@ApiOperation(value = "list experiments", response = Experiment.class, responseContainer = "List")
@ApiResponses(value = { @ApiResponse(code = 200, message = "Success") })
@RequestMapping(value = "/mine", method = RequestMethod.GET, params = {"maxResultCount"})
public ResponseEntity<String> listExperiments(
@ApiParam(value = "maxResultCount", required = false) @RequestParam int maxResultCount
) {
return doListExperiments(true, maxResultCount, null);
}
@ApiOperation(value = "list experiments", response = Experiment.class, responseContainer = "List")
@ApiResponses(value = { @ApiResponse(code = 200, message = "Success") })
@RequestMapping(method = RequestMethod.GET, params = {"slug", "maxResultCount"})
public ResponseEntity<String> listExperiments(
@ApiParam(value = "slug", required = false) @RequestParam("slug") String modelSlug,
@ApiParam(value = "maxResultCount", required = false) @RequestParam("maxResultCount") int maxResultCount
) {
if (maxResultCount <= 0 && (modelSlug == null || modelSlug.equals(""))) {
return new ResponseEntity<>("You must provide at least a slug or a limit of result", HttpStatus.BAD_REQUEST);
}
return doListExperiments(false, maxResultCount, modelSlug);
}
@ApiOperation(value = "List available methods and validations", response = String.class)
@ApiResponses(value = { @ApiResponse(code = 200, message = "Success") })
@RequestMapping(path = "/methods", method = RequestMethod.GET)
public ResponseEntity<String> listAvailableMethodsAndValidations() throws Exception {
URL obj = new URL(listMethodsUrl);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int respCode = con.getResponseCode();
BufferedReader in = new BufferedReader(new InputStreamReader(respCode == 200 ? con.getInputStream() : con.getErrorStream()));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
return new ResponseEntity<>(response.toString(), HttpStatus.valueOf(respCode));
}
}
package org.hbp.mip.model;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.annotations.Expose;
import org.hibernate.annotations.*;
import javax.persistence.*;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.util.Date;
import java.util.UUID;
/**
* Created by habfast on 21/04/16.
*/
@Entity
@Table(name = "`experiment`")
public class Experiment {
private static final Gson gson = new GsonBuilder()
.serializeNulls()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
.excludeFieldsWithoutExposeAnnotation()
.create();
@Id
@Column(columnDefinition = "uuid")
@org.hibernate.annotations.Type(type="pg-uuid")
@Expose
private UUID uuid;
@Column(columnDefinition="TEXT")
@Expose
private String name;
@Expose
@ManyToOne
@JoinColumn(name = "createdby_username")
private User createdBy;
@ManyToOne
@Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
@Expose
private Model model;
@Column(columnDefinition="TEXT")
@Expose
private String algorithms;
@Column(columnDefinition="TEXT")
@Expose
private String validations;
@Column(columnDefinition="TEXT")
@Expose
private String result;
@Expose
private Date created = new Date();
@Expose
private Date finished;
@Expose
private boolean hasError = false;
@Expose
private boolean hasServerError = false;
@Expose
private boolean shared = false;
// whether or not the experiment's result have been resultsViewed by its owner
@Expose
private boolean resultsViewed = false;
public Experiment() {
}
public String computeQuery() {
JsonObject outgoingQuery = new JsonObject();
outgoingQuery.add("algorithms", gson.fromJson(algorithms, JsonArray.class));
outgoingQuery.add("validations", gson.fromJson(validations, JsonArray.class));
outgoingQuery.add("covariables", gson.toJsonTree(model.getQuery().getCovariables()));
outgoingQuery.add("variables", gson.toJsonTree(model.getQuery().getVariables()));
outgoingQuery.add("filters", gson.toJsonTree(model.getQuery().getFilters()));
outgoingQuery.add("grouping", gson.toJsonTree(model.getQuery().getGrouping()));
return outgoingQuery.toString();
}
public String getValidations() {
return validations;
}
public void setValidations(String validations) {
this.validations = validations;
}
public String getAlgorithms() {
return algorithms;
}
public void setAlgorithms(String algorithms) {
this.algorithms = algorithms;
}
public Model getModel() {
return model;
}
public void setModel(Model model) {
this.model = model;
}
public boolean isHasError() {
return hasError;
}
public void setHasError(boolean hasError) {
this.hasError = hasError;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
public Date getFinished() {
return finished;
}
public void setFinished(Date finished) {
this.finished = finished;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public UUID getUuid() {
return uuid;
}
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public User getCreatedBy() {
return createdBy;
}
public void setCreatedBy(User createdBy) {
this.createdBy = createdBy;
}
public boolean isResultsViewed() {
return resultsViewed;
}
public void setResultsViewed(boolean resultsViewed) {
this.resultsViewed = resultsViewed;
}
public boolean isHasServerError() {
return hasServerError;
}
public void setHasServerError(boolean hasServerError) {
this.hasServerError = hasServerError;
}
public boolean isShared() {
return shared;
}
public void setShared(boolean shared) {
this.shared = shared;
}
}
......@@ -5,6 +5,7 @@
package org.hbp.mip.model;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.google.gson.annotations.Expose;
import io.swagger.annotations.ApiModel;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
......@@ -19,8 +20,10 @@ import java.util.Date;
public class Model {
@Id
@Expose
private String slug = null;
@Expose
private String title = null;
private String description = null;
......
......@@ -5,6 +5,7 @@
package org.hbp.mip.model;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.google.gson.annotations.Expose;
import io.swagger.annotations.ApiModel;
import javax.persistence.*;
......@@ -20,44 +21,62 @@ import java.util.regex.Pattern;
public class User {
@Id
@Expose
private String username = null;
@Expose
private String fullname = null;
@Expose
private String firstname = null;
@Expose
private String lastname = null;
@Expose
private String picture = null;
@Expose
private String web = null;
@Expose
private String phone = null;
@Expose
private String birthday = null;
@Expose
private String gender = null;
@Expose
private String city = null;
@Expose
private String country = null;
@Expose
private String password = null;
@Expose
private String email = null;
@Expose
private String apikey = null;
@Expose
private String team = null;
@Expose
private Boolean isActive = null;
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "user_languages", joinColumns = @JoinColumn(name = "user_username"))
@Expose
private List<String> languages = new LinkedList<>();
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "user_roles", joinColumns = @JoinColumn(name = "user_username"))
@Expose
private List<String> roles = new LinkedList<>();
private Boolean agreeNDA = null;
......
......@@ -7,6 +7,7 @@ package org.hbp.mip.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.gson.annotations.Expose;
import io.swagger.annotations.ApiModel;
import javax.persistence.*;
......@@ -21,6 +22,7 @@ import java.util.List;
public class Variable {
@Id
@Expose
private String code = null;
private String label = null;
......
......@@ -20,6 +20,7 @@
<mapping class="org.hbp.mip.model.Article"/>
<mapping class="org.hbp.mip.model.Dataset"/>
<mapping class="org.hbp.mip.model.Model"/>
<mapping class="org.hbp.mip.model.Experiment"/>
<mapping class="org.hbp.mip.model.Query"/>
<mapping class="org.hbp.mip.model.Tag"/>
<mapping class="org.hbp.mip.model.User"/>
......
db @ 2870ec6b
Subproject commit cce1c65bcde8f9a20ceb233442135fdd9cdb73ae
Subproject commit 2870ec6bc3a5e33d5e0c59c23abd154ad836028c
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment