From d5f003d08ca67af199bb347d66aa80981db751d2 Mon Sep 17 00:00:00 2001
From: David Hoksza <david.hoksza@uni.lu>
Date: Fri, 16 Feb 2018 11:26:41 +0100
Subject: [PATCH] Passing annotators descriptions to client, tooltips, fixes of
 failing annotator tests

---
 .../services/DrugbankHTMLParser.java          |  2 +-
 .../annotation/services/ModelAnnotator.java   |  9 +-
 .../services/annotators/ElementAnnotator.java | 17 +++-
 .../services/annotators/KeggAnnotator.java    |  6 ++
 .../services/ModelAnnotatorTest.java          |  3 +
 .../annotators/CazyAnnotatorTest.java         |  2 +-
 .../annotators/ChebiAnnotatorTest.java        |  6 +-
 .../annotators/EnsemblAnnotatorTest.java      |  2 +-
 .../annotators/EntrezAnnotatorTest.java       |  2 +-
 .../annotators/HgncAnnotatorTest.java         | 12 +--
 .../annotators/TairAnnotatorTest.java         |  2 +-
 .../annotators/UniprotAnnotatorTest.java      |  6 +-
 frontend-js/src/main/css/global.css           | 27 +++++-
 .../js/gui/admin/ChooseAnnotatorsDialog.js    | 17 ++--
 .../src/main/js/gui/leftPanel/GuiUtils.js     | 87 ++++++++++---------
 .../src/main/js/map/data/Annotation.js        | 30 +++++--
 frontend-js/src/main/js/map/data/Annotator.js | 10 +++
 .../java/lcsb/mapviewer/api/BaseRestImpl.java | 25 ++++--
 .../configuration/ConfigurationRestImpl.java  |  1 +
 19 files changed, 175 insertions(+), 91 deletions(-)

diff --git a/annotation/src/main/java/lcsb/mapviewer/annotation/services/DrugbankHTMLParser.java b/annotation/src/main/java/lcsb/mapviewer/annotation/services/DrugbankHTMLParser.java
index bfb4eb7ab8..8339571989 100644
--- a/annotation/src/main/java/lcsb/mapviewer/annotation/services/DrugbankHTMLParser.java
+++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/DrugbankHTMLParser.java
@@ -700,7 +700,7 @@ public class DrugbankHTMLParser extends DrugAnnotation implements IExternalServi
         protienLinkPosition = protienLinkPosition + "/polypeptides/".length(); // 20;
         int j = page.indexOf('"', protienLinkPosition);
         String uniprotId = page.substring(protienLinkPosition, j);
-        MiriamData uniprotMiriam = new MiriamData(MiriamType.UNIPROT, uniprotId);
+        MiriamData uniprotMiriam = new MiriamData(MiriamType.UNIPROT, uniprotId, UniprotAnnotator.class);
         MiriamData hgncMiriam = uniprotAnnotator.uniProtToHgnc(uniprotMiriam);
         if (hgncMiriam == null || !hgncMiriam.equals(hgncTarget)) {
           logger.debug("Invalid target found. Expected " + hgncTarget + ", but found: " + hgncMiriam + " ("
diff --git a/annotation/src/main/java/lcsb/mapviewer/annotation/services/ModelAnnotator.java b/annotation/src/main/java/lcsb/mapviewer/annotation/services/ModelAnnotator.java
index 8516fd4f6b..792c637103 100644
--- a/annotation/src/main/java/lcsb/mapviewer/annotation/services/ModelAnnotator.java
+++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/ModelAnnotator.java
@@ -17,7 +17,6 @@ import org.apache.log4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 
 import lcsb.mapviewer.annotation.services.annotators.AnnotatorException;
-import lcsb.mapviewer.annotation.services.annotators.AnnotatorParamDefinition;
 import lcsb.mapviewer.annotation.services.annotators.BrendaAnnotator;
 import lcsb.mapviewer.annotation.services.annotators.BiocompendiumAnnotator;
 import lcsb.mapviewer.annotation.services.annotators.CazyAnnotator;
@@ -360,9 +359,11 @@ public class ModelAnnotator {
 
 			for (ElementAnnotator elementAnnotator : list) {
 				try {
-					List<UserAnnotatorsParam> params = annotatorsParams.get(elementAnnotator.getClass());					
-					if (params != null) {
-						elementAnnotator.annotateElement(element, params);						
+					if (annotatorsParams != null){
+						List<UserAnnotatorsParam> params = annotatorsParams.get(elementAnnotator.getClass());					
+						if (params != null) {
+							elementAnnotator.annotateElement(element, params);
+						}
 					} else {
 						elementAnnotator.annotateElement(element);
 					}
diff --git a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/ElementAnnotator.java b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/ElementAnnotator.java
index b353a3f86b..7be1c6bde1 100644
--- a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/ElementAnnotator.java
+++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/ElementAnnotator.java
@@ -153,7 +153,16 @@ public abstract class ElementAnnotator extends CachableInterface {
 	 */
 	public abstract String getUrl();
 	
-	
+	/**
+	 * Provides description of the extraction process 
+	 * for {@link ElementAnnotator} to be used in the front end.
+	 * @return 
+	 * 		the description
+	 */
+	public String getDescription(){
+		return "";		
+	}
+		
 	/**
 	 * Provides description for {@link ElementAnnotator} and {@link MiriamType} pair
 	 * to be used in the frontend.
@@ -161,9 +170,9 @@ public abstract class ElementAnnotator extends CachableInterface {
 	 * 		{@link MiriamType} annotated by this annotator.
 	 * @return 
 	 * 		the description
-	 */
+	 */	
 	public String getDescription(MiriamType mt){
-		return getCommonName();		
+		return "";		
 	}
 
 	/**
@@ -177,7 +186,7 @@ public abstract class ElementAnnotator extends CachableInterface {
 	 * 		the description
 	 */
 	public String getDescription(MiriamType mt, MiriamRelationType relationType){
-		return getCommonName();		
+		return "";		
 	}
 	
 	/**
diff --git a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/KeggAnnotator.java b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/KeggAnnotator.java
index 2097537be8..180871318e 100644
--- a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/KeggAnnotator.java
+++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/KeggAnnotator.java
@@ -271,6 +271,12 @@ public class KeggAnnotator extends ElementAnnotator implements IExternalService
 	public String getUrl() {
 		return "http://www.genome.jp/kegg/";
 	}
+	
+	@Override
+	public String getDescription() {
+		return "Annotations extracted from KEGG ENZYME Database based on species EC numbers. "
+				+ "Annotation include relevant publications and homologous genes for given EC numbers.";
+	}
 
 	@Override
 	protected WebPageDownloader getWebPageDownloader() {
diff --git a/annotation/src/test/java/lcsb/mapviewer/annotation/services/ModelAnnotatorTest.java b/annotation/src/test/java/lcsb/mapviewer/annotation/services/ModelAnnotatorTest.java
index 17af451888..0efd208ec9 100644
--- a/annotation/src/test/java/lcsb/mapviewer/annotation/services/ModelAnnotatorTest.java
+++ b/annotation/src/test/java/lcsb/mapviewer/annotation/services/ModelAnnotatorTest.java
@@ -88,6 +88,8 @@ public class ModelAnnotatorTest extends AnnotationTestFunctions {
 
 			assertTrue(model.getElementByElementId("a1").getMiriamData().size() > 0);
 			assertTrue(model.getElementByElementId("a2").getMiriamData().size() >= 1);
+			
+			modelAnnotator.annotateModel(model, updater, null);
 
 		} catch (Exception e) {
 			e.printStackTrace();
@@ -129,6 +131,7 @@ public class ModelAnnotatorTest extends AnnotationTestFunctions {
 		}
 	}
 
+	
 	@Test
 	public void testCopyMissingAnnotationsInCD() throws Exception {
 		try {
diff --git a/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/CazyAnnotatorTest.java b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/CazyAnnotatorTest.java
index 66f7e4f58f..e00ab89303 100644
--- a/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/CazyAnnotatorTest.java
+++ b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/CazyAnnotatorTest.java
@@ -41,7 +41,7 @@ public class CazyAnnotatorTest extends AnnotationTestFunctions {
 	@Test
 	public void testUniprotToCazy() throws Exception {
 		try {
-			assertEquals(new MiriamData(MiriamType.CAZY, "GH5_7"), 
+			assertEquals(new MiriamData(MiriamType.CAZY, "GH5_7", CazyAnnotator.class), 
 					cazyAnnotator.uniprotToCazy(new MiriamData(MiriamType.UNIPROT, "Q9SG95")));
 		} catch (Exception e) {
 			e.printStackTrace();
diff --git a/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/ChebiAnnotatorTest.java b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/ChebiAnnotatorTest.java
index a000cdc242..0c25808d4f 100644
--- a/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/ChebiAnnotatorTest.java
+++ b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/ChebiAnnotatorTest.java
@@ -59,7 +59,7 @@ public class ChebiAnnotatorTest extends AnnotationTestFunctions {
   public void testGetIdByName() throws Exception {
     try {
       MiriamData id = backend.getChebiForChebiName("adenine");
-      assertEquals(new MiriamData(MiriamType.CHEBI, "CHEBI:16708"), id);
+      assertEquals(new MiriamData(MiriamType.CHEBI, "CHEBI:16708", ChebiAnnotator.class), id);
       id = backend.getChebiForChebiName("asdf bvclcx lcxj vxlcvkj");
       assertNull(id);
       assertNull(backend.getChebiForChebiName(null));
@@ -250,7 +250,7 @@ public class ChebiAnnotatorTest extends AnnotationTestFunctions {
     try {
       // easy tests with some molecule
       MiriamData result = backend.getChebiForChebiName("Ca2+");
-      assertEquals(new MiriamData(MiriamType.CHEBI, "CHEBI:29108"), result);
+      assertEquals(new MiriamData(MiriamType.CHEBI, "CHEBI:29108", ChebiAnnotator.class), result);
 
     } catch (Exception e) {
       e.printStackTrace();
@@ -271,7 +271,7 @@ public class ChebiAnnotatorTest extends AnnotationTestFunctions {
       assertNotNull(res);
       assertTrue(res.size() > 1);
       assertTrue(
-          res.contains(new MiriamData(MiriamRelationType.BQ_BIOL_IS_DESCRIBED_BY, MiriamType.CHEBI, "CHEBI:24431")));
+          res.contains(new MiriamData(MiriamRelationType.BQ_BIOL_IS_DESCRIBED_BY, MiriamType.CHEBI, "CHEBI:24431", ChebiAnnotator.class)));
     } catch (Exception e) {
       e.printStackTrace();
       throw e;
diff --git a/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/EnsemblAnnotatorTest.java b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/EnsemblAnnotatorTest.java
index 8366b4f6c7..6c92f99481 100644
--- a/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/EnsemblAnnotatorTest.java
+++ b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/EnsemblAnnotatorTest.java
@@ -240,7 +240,7 @@ public class EnsemblAnnotatorTest extends AnnotationTestFunctions {
 		try {
 			MiriamData ensembl = new MiriamData(MiriamType.ENSEMBL, "ENSG00000154930");
 			MiriamData entrez = ensemblAnnotator.ensemblIdToEntrezId(ensembl);
-			assertEquals(new MiriamData(MiriamType.ENTREZ, "84532"), entrez);
+			assertEquals(new MiriamData(MiriamType.ENTREZ, "84532", EnsemblAnnotator.class), entrez);
 
 		} catch (Exception e) {
 			e.printStackTrace();
diff --git a/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/EntrezAnnotatorTest.java b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/EntrezAnnotatorTest.java
index be988ab502..b83f4b449e 100644
--- a/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/EntrezAnnotatorTest.java
+++ b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/EntrezAnnotatorTest.java
@@ -172,7 +172,7 @@ public class EntrezAnnotatorTest extends AnnotationTestFunctions {
 	@Test
 	public void testGetHgncFromEntrez() throws Exception {
 		try {
-			assertEquals(new MiriamData(MiriamType.HGNC, "11179"), entrezAnnotator.getHgncIdFromEntrez(new MiriamData(MiriamType.ENTREZ, "6647")));
+			assertEquals(new MiriamData(MiriamType.HGNC, "11179", EntrezAnnotator.class), entrezAnnotator.getHgncIdFromEntrez(new MiriamData(MiriamType.ENTREZ, "6647", EntrezAnnotator.class)));
 		} catch (Exception e) {
 			e.printStackTrace();
 			throw e;
diff --git a/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/HgncAnnotatorTest.java b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/HgncAnnotatorTest.java
index 2a28675529..71347a9620 100644
--- a/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/HgncAnnotatorTest.java
+++ b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/HgncAnnotatorTest.java
@@ -289,8 +289,8 @@ public class HgncAnnotatorTest extends AnnotationTestFunctions {
 		try {
 			List<MiriamData> result = hgncAnnotator.hgncToUniprot(new MiriamData(MiriamType.HGNC, "11138"));
 			assertEquals(1, result.size());
-			assertEquals(new MiriamData(MiriamType.UNIPROT, "P37840"), result.get(0));
-			assertEquals(0, hgncAnnotator.hgncToUniprot(new MiriamData(MiriamType.HGNC, "1")).size());
+			assertEquals(new MiriamData(MiriamType.UNIPROT, "P37840", HgncAnnotator.class), result.get(0));
+			assertEquals(0, hgncAnnotator.hgncToUniprot(new MiriamData(MiriamType.HGNC, "1", HgncAnnotator.class)).size());
 		} catch (Exception e) {
 			e.printStackTrace();
 			throw e;
@@ -300,8 +300,8 @@ public class HgncAnnotatorTest extends AnnotationTestFunctions {
 	@Test
 	public void testHgncIdToName() throws Exception {
 		try {
-			assertEquals(new MiriamData(MiriamType.HGNC_SYMBOL, "FSD2"), hgncAnnotator.hgncIdToHgncName(new MiriamData(MiriamType.HGNC, "18024")));
-			assertEquals(new MiriamData(MiriamType.HGNC_SYMBOL, "LMOD1"), hgncAnnotator.hgncIdToHgncName(new MiriamData(MiriamType.HGNC, "6647")));
+			assertEquals(new MiriamData(MiriamType.HGNC_SYMBOL, "FSD2", HgncAnnotator.class), hgncAnnotator.hgncIdToHgncName(new MiriamData(MiriamType.HGNC, "18024")));
+			assertEquals(new MiriamData(MiriamType.HGNC_SYMBOL, "LMOD1", HgncAnnotator.class), hgncAnnotator.hgncIdToHgncName(new MiriamData(MiriamType.HGNC, "6647")));
 		} catch (Exception e) {
 			e.printStackTrace();
 			throw e;
@@ -430,13 +430,13 @@ public class HgncAnnotatorTest extends AnnotationTestFunctions {
 			MiriamData data1 = new MiriamData(MiriamType.HGNC_SYMBOL, "PTGS1");
 			MiriamData entrez = hgncAnnotator.hgncToEntrez(data1);
 			assertNotNull(entrez);
-			assertTrue(new MiriamData(MiriamType.ENTREZ, "5742").equals(entrez));
+			assertTrue(new MiriamData(MiriamType.ENTREZ, "5742", HgncAnnotator.class).equals(entrez));
 
 			// check by id
 			data1 = new MiriamData(MiriamType.HGNC, "11138");
 			entrez = hgncAnnotator.hgncToEntrez(data1);
 			assertNotNull(entrez);
-			assertTrue(new MiriamData(MiriamType.ENTREZ, "6622").equals(entrez));
+			assertTrue(new MiriamData(MiriamType.ENTREZ, "6622", HgncAnnotator.class).equals(entrez));
 
 		} catch (Exception e) {
 			e.printStackTrace();
diff --git a/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/TairAnnotatorTest.java b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/TairAnnotatorTest.java
index 10d1bb10e7..c7700dbb95 100644
--- a/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/TairAnnotatorTest.java
+++ b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/TairAnnotatorTest.java
@@ -154,7 +154,7 @@ public class TairAnnotatorTest extends AnnotationTestFunctions {
 	@Test
 	public void testTairToUniprot() throws Exception {
 		try {
-			assertEquals(new MiriamData(MiriamType.UNIPROT, "Q9MAN1"), 
+			assertEquals(new MiriamData(MiriamType.UNIPROT, "Q9MAN1", TairAnnotator.class), 
 					tairAnnotator.tairToUniprot(new MiriamData(MiriamType.TAIR_LOCUS, "AT1G01030")));
 		} catch (Exception e) {
 			e.printStackTrace();
diff --git a/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/UniprotAnnotatorTest.java b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/UniprotAnnotatorTest.java
index aec70cf429..18172cd7d1 100644
--- a/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/UniprotAnnotatorTest.java
+++ b/annotation/src/test/java/lcsb/mapviewer/annotation/services/annotators/UniprotAnnotatorTest.java
@@ -87,8 +87,8 @@ public class UniprotAnnotatorTest extends AnnotationTestFunctions {
 			Collection<MiriamData> mds = uniprotAnnotator.uniProtToEC(new MiriamData(MiriamType.UNIPROT, "P12345"));
 
 			assertEquals(mds.size(), 2);			
-			MiriamData md1 = new MiriamData(MiriamType.EC, "2.6.1.1");
-			MiriamData md2 = new MiriamData(MiriamType.EC, "2.6.1.7");
+			MiriamData md1 = new MiriamData(MiriamType.EC, "2.6.1.1", UniprotAnnotator.class);
+			MiriamData md2 = new MiriamData(MiriamType.EC, "2.6.1.7", UniprotAnnotator.class);
 			for (MiriamData md: mds) {
 				assertTrue(md.compareTo(md1) == 0 || md.compareTo(md2) == 0);
 			}
@@ -244,7 +244,7 @@ public class UniprotAnnotatorTest extends AnnotationTestFunctions {
 	@Test
 	public void testUniprotToHgnc() throws Exception {
 		try {
-			assertEquals(new MiriamData(MiriamType.HGNC_SYMBOL, "KDR"), uniprotAnnotator.uniProtToHgnc(new MiriamData(MiriamType.UNIPROT, "P35968")));
+			assertEquals(new MiriamData(MiriamType.HGNC_SYMBOL, "KDR", UniprotAnnotator.class), uniprotAnnotator.uniProtToHgnc(new MiriamData(MiriamType.UNIPROT, "P35968")));
 		} catch (Exception e) {
 			e.printStackTrace();
 			throw e;
diff --git a/frontend-js/src/main/css/global.css b/frontend-js/src/main/css/global.css
index b0b3be3a99..0c3e27b0be 100644
--- a/frontend-js/src/main/css/global.css
+++ b/frontend-js/src/main/css/global.css
@@ -582,9 +582,8 @@ h1 {
     font-weight: bold;
 }
 
-.minerva-annotator-param-name .annotator-tooltip {
-    visibility: hidden;
-    width: 50%;
+.minerva-annotator-param-name .annotator-tooltip, .minerva-annotation-group .annotator-tooltip{
+    visibility: hidden;    
     background-color: rgba(0, 0, 0, .5);
     color: #fff;
     text-align: left;
@@ -596,7 +595,27 @@ h1 {
     z-index: 1;
 }
 
-.minerva-annotator-param-name:hover .annotator-tooltip {
+.minerva-annotator-param-name .annotator-tooltip {
+    width: 50%;
+}
+
+.minerva-annotation-group .annotator-tooltip {
+    width: 250px;
+}
+
+.minerva-annotator-param-name>span:hover .annotator-tooltip, .minerva-annotation-group-header>span:hover .annotator-tooltip {
     visibility: visible;
 }
 
+.minerva-annotation-group-header>span {
+    position: relative;
+}
+
+.minerva-annotation-group .tooltip-icon, .minerva-annotator-param-name .tooltip-icon{
+    font-size: 0.8em;
+    left: 3px;
+    top: -3px;
+    font-weight: 700;
+}
+
+
diff --git a/frontend-js/src/main/js/gui/admin/ChooseAnnotatorsDialog.js b/frontend-js/src/main/js/gui/admin/ChooseAnnotatorsDialog.js
index 9c4e8b9c56..aafcd38207 100644
--- a/frontend-js/src/main/js/gui/admin/ChooseAnnotatorsDialog.js
+++ b/frontend-js/src/main/js/gui/admin/ChooseAnnotatorsDialog.js
@@ -88,7 +88,7 @@ ChooseAnnotatorsDialog.prototype.setElementType = function (elementType) {
       className: "minerva-multi-select"
     });
 
-    var annotators = configuration.getElementAnnotators(elementType);
+    var annotators = configuration.getElementAnnotators(elementType);    
 
     var selectedAnnotators = user.getPreferences().getElementAnnotators(elementType.className);
 
@@ -149,14 +149,21 @@ ChooseAnnotatorsDialog.prototype.setElementType = function (elementType) {
                   className: "minerva-annotator-param-name",
                   content: param.name
                 });
-  
-                var toolTip = Functions.createElement({
+
+                var tooltipContainer = Functions.createElement({
+                  type: "span"            
+                });
+                tooltipContainer.appendChild(Functions.createElement({
+                  type: "span",    
+                  className: "glyphicon glyphicon-question-sign tooltip-icon"
+                }));
+                tooltipContainer.appendChild(Functions.createElement({
                   type: "span",
                   className: "annotator-tooltip",
                   content: param.description
-                });
+                }));
   
-                paramName.appendChild(toolTip)
+                paramName.appendChild(tooltipContainer)
                 paramElement.appendChild(paramName);    
   
                 var paramValue;
diff --git a/frontend-js/src/main/js/gui/leftPanel/GuiUtils.js b/frontend-js/src/main/js/gui/leftPanel/GuiUtils.js
index 1ac0e50928..2e1caa0851 100644
--- a/frontend-js/src/main/js/gui/leftPanel/GuiUtils.js
+++ b/frontend-js/src/main/js/gui/leftPanel/GuiUtils.js
@@ -182,23 +182,56 @@ GuiUtils.prototype.createAnnotationList = function (annotations, options) {
   var self = this;
   var result = document.createElement("div");
 
+  var annotators = this.getConfiguration().getAnnotators();
+  var annotatorsClassMapping = {};
+  for (var i = 0; i < annotators.length; i++) {
+    annotatorsClassMapping[annotators[i].getClassName()] = annotators[i];    
+  }
+
   var grouppedAnnotations = {};
   for (var i = 0; i < annotations.length; i++) {
-    var desc = annotations[i].getDescription();
-    if (desc == "") desc = "Annotated by curator"
-    if (!(desc in grouppedAnnotations)) grouppedAnnotations[desc] = [];
-    grouppedAnnotations[desc].push(annotations[i])
+    var clazz = annotations[i].getAnnotatorClassName();
+    if (!(clazz in grouppedAnnotations)) grouppedAnnotations[clazz] = [];
+    grouppedAnnotations[clazz].push(annotations[i])
   }
 
+  // = annotatorClasName ? annotatorsClassMapping[annotatorClasName].getName() : "Annotated by curator";
+
   var cntAnnotations = 0;
-  // for (var i = 0; i < grouppedAnnotations.keys().length; i++) {
-  Object.keys(grouppedAnnotations).sort().forEach(function(desc){
+  
+  Object.keys(grouppedAnnotations).sort().forEach(function(annotatorClass){
 
     // var desc = grouppedAnnotations.keys()[i];
     var groupContainer = (inline ? document.createElement("span") : document.createElement("div"));
     var descContainer = (inline ? document.createElement("span") : document.createElement("div"));
     
-    descContainer.innerHTML = (inline ? desc + ': ' : desc);
+    var annotatorName = annotatorClass ? annotatorsClassMapping[annotatorClass].getName() : "Annotated by curator";
+
+    if (inline) {
+      descContainer.innerHTML = annotatorName + ': ';
+    } else {
+      descContainer.innerHTML = annotatorName; 
+      
+      if (annotatorClass) {
+        var annotatorDescription = annotatorsClassMapping[annotatorClass].getDescription();
+        if (annotatorDescription) {
+          var tooltipContainer = Functions.createElement({
+            type: "span"            
+          });
+          tooltipContainer.appendChild(Functions.createElement({
+            type: "span",    
+            className: "glyphicon glyphicon-question-sign tooltip-icon"
+          }));
+          tooltipContainer.appendChild(Functions.createElement({
+            type: "span",
+            className: "annotator-tooltip",
+            content: annotatorsClassMapping[annotatorClass].getDescription()
+          }));
+
+          descContainer.appendChild(tooltipContainer);
+        }
+      }      
+    }    
     descContainer.className = "minerva-annotation-group-header";
     if (!inline) groupContainer.className = "minerva-annotation-group";
     groupContainer.appendChild(descContainer);
@@ -209,7 +242,7 @@ GuiUtils.prototype.createAnnotationList = function (annotations, options) {
       groupContainer.appendChild(par);
     }
 
-    grouppedAnnotations[desc] = grouppedAnnotations[desc].sort(function(a, b) {
+    grouppedAnnotations[annotatorClass] = grouppedAnnotations[annotatorClass].sort(function(a, b) {
       const aType = a.getType().toUpperCase();
       const bType = b.getType().toUpperCase();
       if (aType < bType) return -1;
@@ -217,11 +250,11 @@ GuiUtils.prototype.createAnnotationList = function (annotations, options) {
       else return 0;
     });
 
-    for (var j = 0; j < grouppedAnnotations[desc].length; j++) {
+    for (var j = 0; j < grouppedAnnotations[annotatorClass].length; j++) {
 
       cntAnnotations += 1;
 
-      var element = grouppedAnnotations[desc][j];
+      var element = grouppedAnnotations[annotatorClass][j];
       var link = self.createAnnotationLink(element, showType);
       if (inline) {
         if (j > 0) {
@@ -262,39 +295,7 @@ GuiUtils.prototype.createAnnotationList = function (annotations, options) {
 
     result.appendChild(groupContainer);
   });
-
-  // for (var i = 0; i < annotations.length; i++) {
-  //   var element = annotations[i];
-  //   var link = self.createAnnotationLink(element, showType);
-  //   if (inline) {
-  //     if (i > 0) {
-  //       var coma = document.createElement("span");
-  //       coma.innerHTML = ", ";
-  //       result.appendChild(coma);
-  //     }
-  //     result.appendChild(link);
-  //   } else {
-  //
-  //     var row = document.createElement("div");
-  //     row.style.height = "26px";
-  //     if (i % 2 === 0) {
-  //       row.className = "minerva-annotation-row-odd";
-  //     } else {
-  //       row.className = "minerva-annotation-row-even";
-  //     }
-  //     var header = document.createElement("div");
-  //     header.style.width = "24px";
-  //     header.style.float = "left";
-  //     header.innerHTML = "[" + (i + 1) + "]";
-  //     row.appendChild(header);
-  //
-  //     var body = document.createElement("div");
-  //     body.style.float = "left";
-  //     body.appendChild(link);
-  //     row.appendChild(body);
-  //     result.appendChild(row);
-  //   }
-  // }
+ 
   return result;
 };
 
diff --git a/frontend-js/src/main/js/map/data/Annotation.js b/frontend-js/src/main/js/map/data/Annotation.js
index 1496051649..489e4a3dc7 100644
--- a/frontend-js/src/main/js/map/data/Annotation.js
+++ b/frontend-js/src/main/js/map/data/Annotation.js
@@ -15,7 +15,9 @@ function Annotation(javaObject) {
     }
     this.setType(javaObject.getType());
     this.setResource(javaObject.getResource());
-    this.setDescription(javaObject.getDescription());
+    this.setAnnotatorClassName(javaObject.getAnnotatorClassName());
+    this.setDescriptionByType(javaObject.getDescriptionByType());
+    this.setDescriptionByTypeRelation(javaObject.getDescriptionByTypeRelation());
   } else {
     this.setLink(javaObject.link);
     this.setId(javaObject.id);
@@ -24,7 +26,7 @@ function Annotation(javaObject) {
     }
     this.setType(javaObject.type);
     this.setResource(javaObject.resource);
-    this.setDescription(javaObject.description);
+    this.setAnnotatorClassName(javaObject.annotatorClassName);
   }
 }
 
@@ -74,12 +76,28 @@ Annotation.prototype.getArticle = function() {
   return this._article;
 };
 
-Annotation.prototype.setDescription = function(description) {
-  this._description = description;
+Annotation.prototype.setAnnotatorClassName = function(annotatorClassName) {
+  this._annotatorClassName = annotatorClassName;
 };
 
-Annotation.prototype.getDescription = function() {
-  return this._description;
+Annotation.prototype.getAnnotatorClassName = function() {
+  return this._annotatorClassName;
+};
+
+Annotation.prototype.setDescriptionByType = function(descriptionByType) {
+  this._descriptionByType = descriptionByType;
+};
+
+Annotation.prototype.getDescriptionByType = function() {
+  return this.descriptionByType;
+};
+
+Annotation.prototype.setDescriptionByTypeRelation = function(descriptionByTypeRelation) {
+  this._descriptionByTypeRelation = descriptionByTypeRelation;
+};
+
+Annotation.prototype.getDescriptionByTypeRelation = function() {
+  return this.descriptionByTypeRelation;
 };
 
 module.exports = Annotation;
diff --git a/frontend-js/src/main/js/map/data/Annotator.js b/frontend-js/src/main/js/map/data/Annotator.js
index 74d342558a..4ab6dc69be 100644
--- a/frontend-js/src/main/js/map/data/Annotator.js
+++ b/frontend-js/src/main/js/map/data/Annotator.js
@@ -12,12 +12,14 @@ function Annotator(javaObject, configuration) {
     self.setClassName(javaObject.getClassName());
     this._elementTypes = javaObject.getElementTypes();
     self.setName(javaObject.getName());
+    self.setDescription(javaObject.getDescription());
     self.setParametersDefinitions(javaObject.getParametersDefinitions());
     self.setUrl(javaObject.getUrl());
   } else {
     self.setClassName(javaObject.className);
     self.setElementTypes(javaObject.elementClassNames, configuration);
     self.setName(javaObject.name);
+    self.setDescription(javaObject.description);
     self.setParametersDefinitions(javaObject.parametersDefinitions);
     self.setUrl(javaObject.url);
   }
@@ -39,6 +41,14 @@ Annotator.prototype.getName = function () {
   return this._name;
 };
 
+Annotator.prototype.setDescription = function (description) {
+  this._description = description;
+};
+
+Annotator.prototype.getDescription = function () {
+  return this._description;
+};
+
 Annotator.prototype.setUrl = function (url) {
   this._url = url;
 };
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/BaseRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/BaseRestImpl.java
index 6a53cd7b72..a42e0686b8 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/BaseRestImpl.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/BaseRestImpl.java
@@ -110,17 +110,26 @@ public abstract class BaseRestImpl {
             
       if (annotation.getAnnotator() != null) {    	  
     	  try {
-    	  result.put("description",
-    			  ((ElementAnnotator) annotation.getAnnotator().getConstructor().newInstance()).getDescription(
-    					  annotation.getDataType(),
-    					  annotation.getRelationType())
-    			  );
-    	  }catch(Exception e) { //TODO
+    		  result.put("annotatorClassName", annotation.getAnnotator().getName());
+    		  result.put("descriptionByType",
+        			  ((ElementAnnotator) annotation.getAnnotator().getConstructor().newInstance()).getDescription( annotation.getDataType())    					  
+        			  );
+    		  result.put("descriptionByTypeRelation",
+        			  ((ElementAnnotator) annotation.getAnnotator().getConstructor().newInstance()).getDescription(
+        					  annotation.getDataType(),
+        					  annotation.getRelationType())
+        			  );
+    		  
+    	  }catch(Exception e) {
     		  logger.error("Problem with retrieving description from annotator", e);
-    		  result.put("description", ""); 
+    		  result.put("annotatorClassName", ""); 
+    		  result.put("descriptionByType", "");
+        	  result.put("descriptionByTypeRelation", "");
     	  }
       } else {
-    	  result.put("description", "");    	      	  
+    	  result.put("annotatorClassName", "");    	      	  
+    	  result.put("descriptionByType", "");
+    	  result.put("descriptionByTypeRelation", "");
       }
       
       return result;
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/configuration/ConfigurationRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/configuration/ConfigurationRestImpl.java
index 29a85d63d3..c6519c98fb 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/configuration/ConfigurationRestImpl.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/configuration/ConfigurationRestImpl.java
@@ -247,6 +247,7 @@ public class ConfigurationRestImpl {
     Map<String, Object> result = new HashMap<>();
     result.put("className", annotator.getClass().getName());
     result.put("name", annotator.getCommonName());
+    result.put("description", annotator.getDescription());
     result.put("url", annotator.getUrl());
     result.put("elementClassNames", annotator.getValidClasses());
     result.put("parametersDefinitions", annotator.getParametersDefinitions());
-- 
GitLab