From b1438b7844f9d52076f4327e150ce27dc99e951b Mon Sep 17 00:00:00 2001
From: Piotr Gawron <piotr.gawron@uni.lu>
Date: Fri, 26 Jan 2018 14:13:33 +0100
Subject: [PATCH] rest API for mesh data stored on the server side

---
 frontend-js/src/main/js/ServerConnector.js    | 19 +++++-
 frontend-js/src/main/js/map/data/Mesh.js      | 37 ++++++++++
 .../src/test/js/ServerConnector-test.js       |  9 +++
 frontend-js/src/test/js/map/data/Mesh-test.js | 22 ++++++
 .../mesh/D010300/token=MOCK_TOKEN_ID&         |  1 +
 .../mapviewer/api/mesh/MeshController.java    | 67 +++++++++++++++++++
 .../lcsb/mapviewer/api/mesh/MeshRestImpl.java | 43 ++++++++++++
 .../lcsb/mapviewer/api/mesh/AllMeshTests.java | 11 +++
 .../mapviewer/api/mesh/MeshRestImplTest.java  | 29 ++++++++
 9 files changed, 237 insertions(+), 1 deletion(-)
 create mode 100644 frontend-js/src/main/js/map/data/Mesh.js
 create mode 100644 frontend-js/src/test/js/map/data/Mesh-test.js
 create mode 100644 frontend-js/testFiles/apiCalls/mesh/D010300/token=MOCK_TOKEN_ID&
 create mode 100644 rest-api/src/main/java/lcsb/mapviewer/api/mesh/MeshController.java
 create mode 100644 rest-api/src/main/java/lcsb/mapviewer/api/mesh/MeshRestImpl.java
 create mode 100644 rest-api/src/test/java/lcsb/mapviewer/api/mesh/AllMeshTests.java
 create mode 100644 rest-api/src/test/java/lcsb/mapviewer/api/mesh/MeshRestImplTest.java

diff --git a/frontend-js/src/main/js/ServerConnector.js b/frontend-js/src/main/js/ServerConnector.js
index 01fb6ac66a..cf8845a05b 100644
--- a/frontend-js/src/main/js/ServerConnector.js
+++ b/frontend-js/src/main/js/ServerConnector.js
@@ -23,6 +23,7 @@ var LayoutAlias = require('./map/data/LayoutAlias');
 var LayoutData = require('./map/data/LayoutData');
 var LayoutReaction = require('./map/data/LayoutReaction');
 var MapModel = require('./map/data/MapModel');
+var Mesh = require('./map/data/Mesh');
 var MiRna = require('./map/data/MiRna');
 var NetworkError = require('./NetworkError');
 var Project = require('./map/data/Project');
@@ -341,6 +342,12 @@ ServerConnector.getProjectLogsUrl = function (queryParams, filterParams) {
     params: filterParams
   });
 };
+ServerConnector.getMeshUrl = function (queryParams, filterParams) {
+  return this.getApiUrl({
+    type: "mesh/" + queryParams.id,
+    params: filterParams
+  });
+};
 
 
 ServerConnector.getReferenceGenomeUrl = function (queryParams, filterParams) {
@@ -1355,7 +1362,7 @@ ServerConnector.login = function (login, password) {
 
 ServerConnector.logout = function () {
   var self = this;
-  return self.sendGetRequest(self.logoutUrl()).then(function(){
+  return self.sendGetRequest(self.logoutUrl()).then(function () {
     self.getSessionData().setToken(undefined);
     self.getSessionData().setLogin(undefined);
     window.location.reload(false);
@@ -1824,4 +1831,14 @@ ServerConnector.getProjectLogs = function (params) {
   });
 };
 
+ServerConnector.getMesh = function (params) {
+  var self = this;
+  if (params === undefined) {
+    params = {};
+  }
+  return self.sendGetRequest(self.getMeshUrl(params)).then(function (content) {
+    return new Mesh(JSON.parse(content));
+  });
+};
+
 module.exports = ServerConnector;
diff --git a/frontend-js/src/main/js/map/data/Mesh.js b/frontend-js/src/main/js/map/data/Mesh.js
new file mode 100644
index 0000000000..612111fec6
--- /dev/null
+++ b/frontend-js/src/main/js/map/data/Mesh.js
@@ -0,0 +1,37 @@
+"use strict";
+
+function Mesh(jsonObject) {
+  var self = this;
+  self.setSynonyms(jsonObject.synonyms);
+  self.setName(jsonObject.name);
+  self.setId(jsonObject.id);
+  self.setDescription(jsonObject.description);
+}
+
+Mesh.prototype.setSynonyms = function (synonyms) {
+  this.synonyms = synonyms;
+};
+Mesh.prototype.getSynonyms = function () {
+  return this.synonyms;
+};
+Mesh.prototype.setName = function (name) {
+  this.name = name;
+};
+Mesh.prototype.getName = function () {
+  return this.name;
+};
+Mesh.prototype.setId = function (id) {
+  this.id = id;
+};
+Mesh.prototype.getId = function () {
+  return this.id;
+};
+Mesh.prototype.setDescription = function (description) {
+  this.description = description;
+};
+Mesh.prototype.getDescription = function () {
+  return this.description;
+};
+
+
+module.exports = Mesh;
diff --git a/frontend-js/src/test/js/ServerConnector-test.js b/frontend-js/src/test/js/ServerConnector-test.js
index c48d2795a5..b674de121f 100644
--- a/frontend-js/src/test/js/ServerConnector-test.js
+++ b/frontend-js/src/test/js/ServerConnector-test.js
@@ -369,5 +369,14 @@ describe('ServerConnector', function () {
     });
   });
 
+  it('getMesh', function () {
+    return ServerConnector.getMesh({id: "D010300"}).then(function (mesh) {
+      assert.ok(mesh.getSynonyms().length > 0);
+      assert.equal("Parkinson Disease", mesh.getName());
+      assert.ok(mesh.getDescription().indexOf("A progressive, degenerative ..." >= 0));
+      assert.equal("D010300", mesh.getId());
+    });
+  });
+
 
 });
diff --git a/frontend-js/src/test/js/map/data/Mesh-test.js b/frontend-js/src/test/js/map/data/Mesh-test.js
new file mode 100644
index 0000000000..ee109bb8a3
--- /dev/null
+++ b/frontend-js/src/test/js/map/data/Mesh-test.js
@@ -0,0 +1,22 @@
+"use strict";
+
+var Mesh = require('../../../../main/js/map/data/Mesh');
+var assert = require('assert');
+
+describe('Mesh', function () {
+  describe("constructor", function () {
+    it("from json", function () {
+      var mesh = new Mesh({
+        "synonyms": ["Parkinson's Disease"],
+        "name": "Parkinson Disease",
+        "description": "A progressive, degenerative ...",
+        "id": "D010300"
+      });
+      assert.ok(mesh);
+      assert.equal("Parkinson's Disease",mesh.getSynonyms()[0]);
+      assert.equal("Parkinson Disease",mesh.getName());
+      assert.equal("A progressive, degenerative ...",mesh.getDescription());
+      assert.equal("D010300",mesh.getId());
+    });
+  });
+});
diff --git a/frontend-js/testFiles/apiCalls/mesh/D010300/token=MOCK_TOKEN_ID& b/frontend-js/testFiles/apiCalls/mesh/D010300/token=MOCK_TOKEN_ID&
new file mode 100644
index 0000000000..bb1bc41aaf
--- /dev/null
+++ b/frontend-js/testFiles/apiCalls/mesh/D010300/token=MOCK_TOKEN_ID&
@@ -0,0 +1 @@
+{"synonyms":["Parkinson's Disease, Idiopathic","Primary Parkinsonism","Idiopathic Parkinson's Disease","Paralysis Agitans","Parkinsonism, Primary","Parkinson's Disease","Lewy Body Parkinson Disease","Parkinson's Disease, Lewy Body","Parkinson Disease, Idiopathic","Lewy Body Parkinson's Disease","Idiopathic Parkinson Disease"],"name":"Parkinson Disease","description":"A progressive, degenerative neurologic disease characterized by a TREMOR that is maximal at rest, retropulsion (i.e. a tendency to fall backwards), rigidity, stooped posture, slowness of voluntary movements, and a masklike facial expression. Pathologic features include loss of melanin containing neurons in the substantia nigra and other pigmented nuclei of the brainstem. LEWY BODIES are present in the substantia nigra and locus coeruleus but may also be found in a related condition (LEWY BODY DISEASE, DIFFUSE) characterized by dementia in combination with varying degrees of parkinsonism. (Adams et al., Principles of Neurology, 6th ed, p1059, pp1067-75)","id":"D010300"}
\ No newline at end of file
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/mesh/MeshController.java b/rest-api/src/main/java/lcsb/mapviewer/api/mesh/MeshController.java
new file mode 100644
index 0000000000..82d645cb89
--- /dev/null
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/mesh/MeshController.java
@@ -0,0 +1,67 @@
+package lcsb.mapviewer.api.mesh;
+
+import java.io.IOException;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+
+import lcsb.mapviewer.api.BaseController;
+import lcsb.mapviewer.api.ObjectNotFoundException;
+import lcsb.mapviewer.api.QueryException;
+import lcsb.mapviewer.common.Configuration;
+import lcsb.mapviewer.services.SecurityException;
+import lcsb.mapviewer.services.interfaces.IUserService;
+import lcsb.mapviewer.services.view.AuthenticationToken;
+
+@RestController
+public class MeshController extends BaseController {
+  /**
+   * Default class logger.
+   */
+  @SuppressWarnings("unused")
+  private Logger logger = Logger.getLogger(MeshController.class);
+
+  @Autowired
+  private MeshRestImpl userRest;
+
+  @RequestMapping(value = "/mesh/{id:.+}", method = { RequestMethod.GET }, produces = {
+      MediaType.APPLICATION_JSON_VALUE })
+  public Map<String, Object> getMesh(//
+      @CookieValue(value = Configuration.AUTH_TOKEN) String token, //
+      @PathVariable(value = "id") String id //
+  ) throws Exception {
+    return userRest.getMesh(token, id);
+  }
+
+  public MeshRestImpl getUserRest() {
+    return userRest;
+  }
+
+  public void setUserRest(MeshRestImpl userRest) {
+    this.userRest = userRest;
+  }
+
+}
\ No newline at end of file
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/mesh/MeshRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/mesh/MeshRestImpl.java
new file mode 100644
index 0000000000..52ecc08744
--- /dev/null
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/mesh/MeshRestImpl.java
@@ -0,0 +1,43 @@
+package lcsb.mapviewer.api.mesh;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+import lcsb.mapviewer.annotation.data.MeSH;
+import lcsb.mapviewer.annotation.services.MeSHParser;
+import lcsb.mapviewer.annotation.services.annotators.AnnotatorException;
+import lcsb.mapviewer.api.BaseRestImpl;
+import lcsb.mapviewer.api.ObjectNotFoundException;
+import lcsb.mapviewer.model.map.MiriamData;
+import lcsb.mapviewer.model.map.MiriamType;
+
+@Transactional(value = "txManager")
+public class MeshRestImpl extends BaseRestImpl {
+
+  /**
+   * Default class logger.
+   */
+  @SuppressWarnings("unused")
+  private Logger logger = Logger.getLogger(MeshRestImpl.class);
+
+  @Autowired
+  private MeSHParser meSHParser;
+
+  public Map<String, Object> getMesh(String token, String id) throws AnnotatorException, ObjectNotFoundException {
+
+    MeSH mesh = meSHParser.getMeSH(new MiriamData(MiriamType.MESH_2012, id));
+    if (mesh == null) {
+      throw new ObjectNotFoundException("Object not found: " + id);
+    }
+    Map<String, Object> result = new HashMap<>();
+    result.put("name", mesh.getName());
+    result.put("id", mesh.getMeSHId());
+    result.put("description", mesh.getDescription());
+    result.put("synonyms", mesh.getSynonyms());
+    return result;
+  }
+}
diff --git a/rest-api/src/test/java/lcsb/mapviewer/api/mesh/AllMeshTests.java b/rest-api/src/test/java/lcsb/mapviewer/api/mesh/AllMeshTests.java
new file mode 100644
index 0000000000..c17b65885c
--- /dev/null
+++ b/rest-api/src/test/java/lcsb/mapviewer/api/mesh/AllMeshTests.java
@@ -0,0 +1,11 @@
+package lcsb.mapviewer.api.mesh;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+@RunWith(Suite.class)
+@SuiteClasses({ MeshRestImplTest.class })
+public class AllMeshTests {
+
+}
diff --git a/rest-api/src/test/java/lcsb/mapviewer/api/mesh/MeshRestImplTest.java b/rest-api/src/test/java/lcsb/mapviewer/api/mesh/MeshRestImplTest.java
new file mode 100644
index 0000000000..93e6211849
--- /dev/null
+++ b/rest-api/src/test/java/lcsb/mapviewer/api/mesh/MeshRestImplTest.java
@@ -0,0 +1,29 @@
+package lcsb.mapviewer.api.mesh;
+
+import static org.junit.Assert.*;
+
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import lcsb.mapviewer.annotation.services.annotators.AnnotatorException;
+import lcsb.mapviewer.api.ObjectNotFoundException;
+import lcsb.mapviewer.api.RestTestFunctions;
+
+public class MeshRestImplTest extends RestTestFunctions {
+
+  Logger logger = Logger.getLogger(MeshRestImplTest.class);
+  @Autowired
+  MeshRestImpl meshRestImpl;
+
+  @Test
+  public void test() throws ObjectNotFoundException, AnnotatorException {
+    Map<String, Object> result = meshRestImpl.getMesh(token.getId(), "D010300");
+    assertNotNull(result);
+    String name =(String) result.get("name"); 
+    assertTrue(name.toLowerCase().contains("parkinson"));
+  }
+
+}
-- 
GitLab